VARCHAR 字段被截断为 255 个字符

Posted

技术标签:

【中文标题】VARCHAR 字段被截断为 255 个字符【英文标题】:VARCHAR fields trucated to 255 chars 【发布时间】:2017-09-05 23:44:08 【问题描述】:

我正在使用 php、SQL Server 2012 和 FreeTDS。使用 TDS 版本 = 7.4,我的所有 VARCHAR 字段都被截断为 255 个字符。

我了解到,低于 7.0 的 TDS 版本会发生这种情况,因此不适用于此配置。

当我们使用 TDS 7.1 版时,这可以正常工作,但我们的托管服务提供商似乎已经改变了一些东西(仍在努力解决这个问题),现在由于某种原因我们无法连接到 7.1。

这是tsql -C的输出:

编译时设置(使用“配置”脚本建立) 版本:freetds v1.00.27 freetds.conf 目录:/usr/local/etc MS db-lib 源兼容性:否 Sybase 二进制兼容性:否 线程安全:是 iconv 库:是的 TDS 版本:自动 iODBC:没有 unixodbc:是的 SSPI“可信”登录:否 Kerberos:没有 OpenSSL:是的 GnuTLS:没有 火星:没有

这是我的 freetds.conf:

[全球的] tds 版本 = 7.4 文字大小 = 2147483647 [我的服务器名称] 主机 = 我的服务器名称 端口 = 1433 tds 版本 = 7.4 实例 = 我的数据库实例

我通过 PHP 连接(使用旧的 mssql_* 函数)使用与 my-server-name 相同的值。我已通过将 tds version 更改为 7.1 来验证它正在使用该配置,但连接不起作用。

我之前使用的是 freetds v0.91,我下载了最新的稳定版本并按照他们网站上的构建说明进行更新,但这并没有解决问题。

此代码库中有大量的表、查询、存储过程和函数,因此更新对这些 VARCHAR 字段的所有调用以使用类似 CAST(column AS TEXT) 的内容不是一种选择。

显示问题的示例代码如下:

<?php
$conn = mssql_connect('my-server-name', 'my-username', 'my-password');
mssql_select_db('my-database', $conn);
$result = mssql_query("SELECT longFieldName FROM myTable");
while ($row = mssql_fetch_array($result, MSSQL_ASSOC)) 
    var_dump($row);

这是从创建为的表中提取的:

CREATE TABLE myTable (longFieldName VARCHAR(2000));
INSERT INTO myTable (longFieldName) VALUES ('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.');

当我运行 PHP 代码时,我希望转储完整的字符串,但它会输出以下字符串:

array(1) 
  'longFieldName' =>
  string(255) "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor i"

是什么导致这些字段被截断为 255 个字符?


编辑:

看来这可能是 PHP 特有的。我尝试使用tsql 进行连接,然后我进行了查询并取回了完整的字符串。我使用的是 PHP 5.5.15 (cli),我使用以下配置设置了 xdebug:

[xdebug]
zend_extension="/usr/local/lib/xdebug.so"
xdebug.var_display_max_children = -1
xdebug.var_display_max_data = -1
xdebug.var_display_max_depth = -1
xdebug.remote_port = 9000
xdebug.remote_enable = 1
xdebug.remote_connect_back = 1

以及下面的MSSQL配置:

[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatability_mode = Off
mssql.connect_timeout = 5
mssql.timeout = 6000000000
mssql.textsize = 2147483647
mssql.secure_connection = Off

更新:

我在 7.0 版中没有看到这个问题。所以总结一下每个版本会发生什么:

7.0:能够连接且 varchar 字段不会被截断,但不支持 64 位整数。 7.1: 无法连接 (which is a separate issue)。当我们过去能够连接时,我们没有截断问题。 7.2 及更高版本:能够连接,但 varchar 字段被截断。

【问题讨论】:

你的创建表和插入/更新语句在哪里? 字段何时被截断?在 SELECT、INSERT 或 UPDATE 中?向我们展示执行错误操作的代码。 添加了示例代码和表格。 几年前,我遇到过类似的问题。但这只是获取一个超过 255 个字符的列,该列被转换为 Blob 到 MsSQL。它只发生在 Linux 服务器连接 SQL Server 上。在您的 SQL 服务器中,是否有完整的字符串或截断的字符串? 当直接登录到 SQL Server(在 SSMS 中)并执行相同的查询时,我得到了完整的字符串。 【参考方案1】:

我相信我已经解决了截断问题。

当我尝试更新我的 FreeTDS 版本时,我实际上安装了 FreeTDS 的第二个版本,这就是 tsql -C 所使用的。但是,当我通过在 freetds.conf 中设置 dump file = /tmp/freetds.log 启用日志记录,然后运行测试并查看日志时,第一行显示:

FreeTDS 0.91 的启动日志文件

所以 PHP 实际上使用的是 FreeTDS 0.91 版本。而根据this answer,0.91 只支持最高 TDS 7.2 版本。

因此,当我指定 7.3 或 7.4 时,我相信它默认为旧版本,日志文件下方的另一行证实了这一点:

连接到 172.19.4.129 端口 1433(TDS 版本 4.2)

所以这就是截断问题的原因。我必须更新 PHP 正在使用的 FreeTDS 版本。

【讨论】:

以上是关于VARCHAR 字段被截断为 255 个字符的主要内容,如果未能解决你的问题,请参考以下文章

访问报告字段截断为 255 个字符

第十章 创建计算字段

sql server 2000 中文字符串被截断是怎么回事

RODBC::sqlSave() 创建表,警告:在列中截断为 255 个字节?

如何区别char与varchar?

RODBC :: sqlSave()创建表,警告:在列中截断为255个字节?