gpt4 book ai didi

PHP、ORM、MSSQL 和 Unicode,是否可以让它们一起工作?

转载 作者:可可西里 更新时间:2023-11-01 14:02:08 30 4
gpt4 key购买 nike

如果要将 unicode 数据保存到 MSSQL,则需要将其保存到列类型 nvarchar(等)中,并且必须在 SQL STRING LITERALS 前加上大写 N。如果您使用的是准备好的语句,则不需要前缀带 N 的值。

插入 tbl (col) 值 (N'hello')

如果您使用的是像 ZF DB 这样的 ORM,那么您正在使用 PDO 连接到 MSSQL(或者您正在 Windows 上部署,在这种情况下,您使用的是 SQLSRV 或 PDO_SQLSRV,并且一切正常,我的问题没有有意义了)。

如果您在 Linux 上使用连接到 mssql(sybase、dblib 等)的任何 PDO 变体,那么您不会获得真正的准备好的语句,只能模拟。

如果您模拟了准备好的语句,在线路级别,SQL 完全只用字符串文字写出,这意味着您必须在任何可能的 unicode 值前加上 N。

  1. 是否可以自动在任何字符值前加上 N 和 ZF?
  2. 是否有任何允许这种值操作的 ORM/TableGateway 库?
  3. 有什么方法可以从 Linux 启用服务器端准备好的语句吗?
  4. 有没有人实际从 Linux 代码运行生产 PHP 并让它针对 MSSQL 运行? (如果是,您如何处理 Unicode?)

编辑:我可以从 Linux 获取 unicode 以保存到 MSSQL,但是将 FreeTDS 协议(protocol)升级到 7/8 似乎会破坏所有框架/库/orms,因为绝对需要改变带有 N 前缀的普通 SQL。我不确定 Internet 上声称升级到协议(protocol)版本 7/8 解决了他们的 unicode 问题的人除了以不可移植的方式手写每个 SQL 语句之外,实际上是如何做的。看来留在 Freetds 4.2 上是处理 Unicode/UTF-8 和 mssql 的最佳方式。

最佳答案

更新:驱动程序不再处于预览状态。 MS 已经为现在发布的版本提供了官方说明:https://www.microsoft.com/en-us/sql-server/developer-get-started/php-ubuntu

以下说明现已过时,因为 MS 已取消预览驱动程序下载。


嗯,有微软提供的ODBC驱动。这应该在这方面提供适当的行为。 请参阅文章末尾了解我如何测试其行为(以初步方式)。它是针对 Azure SQL 数据库 V12 进行测试的。

如何在Ubuntu 16.04上安装Microsoft SQL ODBC驱动

这是在基于 Canonical 提供的 Ubuntu 16.04 Azure 镜像的全新 Ubuntu 16.04 Azure 实例上进行测试的。登录后,我使用 sudo -i 切换到 root 用户,然后:

apt-get update
apt-get -y install atool make build-essential libc6 libkrb5-3 libgss3 e2fsprogs openssl equivs
wget https://download.microsoft.com/download/2/E/5/2E58F097-805C-4AB8-9FC6-71288AB4409D/msodbcsql-13.0.0.0.tar.gz
atool -x msodbcsql-13.0.0.0.tar.gz
rm msodbcsql-13.0.0.0.tar.gz

pushd msodbcsql-13.0.0.0/
./build_dm.sh --accept-warning | tee build_dm_result.txt
command=$(cat build_dm_result.txt | grep "Run the command" | cut -d"'" -f2)
rm build_dm_result.txt
sh -c "$command"
popd

echo "/usr/lib64" > /etc/ld.so.conf.d/microsoft-lib64.conf
ldconfig

pushd msodbcsql-13.0.0.0/
./install.sh install --accept-license

测试一下

将以下命令中的服务器和凭据替换为您自己的。

sqlcmd -S somedatabase.database.windows.net -U someuser -P somepassword

此时您应该能够发出 SQL 命令。好的,让我们让它与 php 一起工作。

与 php 一起使用

我们必须确保没有安装 libodbc1 包,并且它不会被安装,因为 php 会使用它而不是我们自定义的编译包,这会导致编码问题。

cat > libodbc1<<EOL
Section: misc
Priority: optional
Standards-Version: 3.9.2

Package: libodbc1
Version: 9999
Description: fake pkg, so that we satisfy the dependency of php7-odbc, so that we can keep our custom built libodbc
EOL

equivs-build libodbc1
dpkg -i libodbc1_9999_all.deb
rm libodbc1
rm libodbc1_9999_all.deb

apt-get install php7.0-odbc php7.0-cli

此时,您应该可以使用它作为 ODBC 驱动程序。

测试其行为

创建一个 php 文件 test.php,UTF-8 编码,内容如下。将连接字符串中的服务器、数据库和凭据替换为您自己的。

<?php

$pdo = new PDO('odbc:Driver={ODBC Driver 13 for SQL Server};Server=tcp:somedatabase.database.windows.net,1433;Database=somedatabase;Uid=someuser@somedatabase;Pwd=somepassword;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;');

$str = 'Árvíztűrő tükörfúrógép, and... 你好,世界';

$pdo->prepare("DROP TABLE test")->execute();
$pdo->prepare("CREATE TABLE test(a NVARCHAR(MAX))")->execute();
$stmt = $pdo->prepare("INSERT INTO test VALUES(?)");
$stmt->bindParam(1, $str);
$stmt->execute();

$stmt = $pdo->prepare("SELECT * FROM test");
$stmt->execute();
$data = $stmt->fetchall();
var_dump($data[0][0]==$str); //Returns true

$stmt = $pdo->prepare("SELECT * FROM test WHERE a=?");
$stmt->bindParam(1, $str);
$stmt->execute();
$data = $stmt->fetchall();
var_dump($data[0][0]==$str); //Returns true

使用 php -f test.php 运行它表明我们取回了没有任何损坏的字符串。此外,该字符串在 SQL Server Management Studio 中看起来也不错。我在 Azure 门户的 Performance Insight 页面上观察到以下查询:(@P1 nvarchar(max))INSERT INTO test VALUES(@P1),所以显然使用了准备好的语句,所以我假设它可以处理你的(和我的)场景。

(这篇文章在尝试让它发挥作用时提供了很大帮助:http://www.codesynthesis.com/~boris/blog/2011/12/02/microsoft-sql-server-odbc-driver-linux/ 谢谢鲍里斯!)

关于PHP、ORM、MSSQL 和 Unicode,是否可以让它们一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24230694/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com