[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]字符串或二进制数据将被截断。 (SQL-22001)[状态现在是22001,现在为01000]
[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]该语句已终止。 (SQL-01000)在。\ insert.pl第106行。
如何找出哪个列正在生成该错误并且缺少输入的长度?有没有办法不用蛮力猜测所有的
varchar
?#1 楼
不,它不会记录在任何地方。投票并陈述您的业务案例;这是SQL Server应该修复的一长串内容。这是几年前在Connect上提出的(可能是在SQL Server 2000或2005年的时间范围内),然后在新的反馈系统:
二进制或字符串数据将被截断=>错误消息增强功能
现在已提供以下版本:
SQL Server 2019
SQL Server 2017 CU12
SQL Server 2016 SP2 CU6
SQL Server 2019的第一个公共CTP ,它仅在跟踪标志460下浮出水面。这听起来有些秘密,但已在此Microsoft白皮书中发布。这将是默认行为(无需跟踪标志),尽管您可以通过新的数据库范围配置
VERBOSE_TRUNCATION_WARNINGS
进行控制。以下是示例:USE tempdb;
GO
CREATE TABLE dbo.x(a char(1));
INSERT dbo.x(a) VALUES('foo');
GO
SQL Server 2019之前所有受支持的版本中的结果:
Msg 8152,级别16,状态30,第5行
字符串或二进制数据将被截断。
语句已终止。
现在,在SQL Server 2019 CTP上,启用了跟踪标志:
DBCC TRACEON(460);
GO
INSERT dbo.x(a) VALUES('foo');
GO
DROP TABLE dbo.x;
DBCC TRACEOFF(460);
结果显示表,列和(截断的,不完整的)值:
Msg 2628,级别16,状态1,行11
表'tempdb.dbo.x'的列'a'中的字符串或二进制数据将被截断。截断的值:'f'。
该语句已终止。
在可以移至受支持的版本/ CU或移至Azure SQL数据库之前,您可以更改“自动”代码以实际从
sys.columns
中提取max_length以及无论如何必须到达的名称,然后应用LEFT(column, max_length)
或任何PG的等效物。或者,由于这仅意味着您将无声地丢失数据,因此请找出哪些列不匹配并修复目标列,以使它们适合源中的所有数据。给定元数据访问这两个系统的权限,并且您已经在编写一个必须与源->目标列自动匹配的查询(否则,该错误几乎不是您的最大问题),您不必进行任何暴力完全是猜测。#2 楼
如果您有权从SQL Server Management Studio运行SQL Server导入和导出向导(右键单击数据库>任务>导入数据...),请创建一个任务,该任务使用查询作为数据源从SQL Client导入到目标表。在运行导入之前,您可以查看数据映射,它会告诉您哪些列的字段类型不一致。而且,如果您运行导入任务,它将告诉您哪些列导入失败。
示例验证警告:
警告0x802092a7:数据流任务1:由于
将数据从长度为316的数据流列“ NARRATIVE”插入到长度为60的数据库列“ NARRATIVE”,所以可能会发生截断。(SQL Server导出向导)
#3 楼
最终,Microsoft决定从SQL Server 2016 SP2 CU,SQL Server 2017 CU12和SQL Server 2019开始为String or binary would be truncated
提供有意义的信息。有问题的值(被截断为120个字符):消息2628,级别16,状态1,行x字符串或二进制数据将在表'TheDb.TheSchema中被截断.TheTable”,“ TheColumn”列。截断的值:“ ...”。
该语句已终止。
#4 楼
最终,我无法找到一种无需自己编写即可获取列信息的方法。我在列列表中使用了类似的代码,以获取包含两个元素
DBD::ODBC
和sys.columns (max_length)
(在DBI COLUMN_NAME
中记录)的数组列表。 /> 然后我在
MAX_LENGTH
上捕获了异常,并打印了一些有用的东西。在此示例中,column_info()
是发送到INSERT
的数据my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ]
, map $dbh_mssql->column_info('database', 'dbo', $dest_table, $_)
, @col_mssql
;
另外,请投票并投票赞成其他答案
评论
我没有放置任何引用sys.columns的代码,因为我完全不知道您当前使用什么代码来“自动”生成查询。与SELECT名称,object_id,max_length FROM sys.columns;相比,我想将代码合并到您的代码中实际上没有什么复杂的。由于您已经具有必须执行此操作的自动代码-或类似的代码-我认为没有必要提供示例。
–亚伦·伯特兰(Aaron Bertrand)
2013年12月15日20:26
我不确定sys.columns如何与两个具有相同名称的列一起使用。另外,我使用库而不是sys来工作,为什么要选择它作为答案? Microsoft SQL没有x,而是y是有效的贡献,但是如果您的y不如我的y,则我将做一些不同的事情并将其标记为已选择。
–埃文·卡洛尔(Evan Carroll)
2013年12月16日8:00
从本质上讲,您的问题是,我如何找出导致错误的列(大概是这样,您可以修复一个问题,而不是重新设计解决方案)。我告诉你去哪里看:sys.columns。您应该在哪里比较源列长度和目标列长度。您的操作方式取决于您。我没有告诉您如何修复代码,因为我完全不知道首先如何生成自动查询,因此,就像我说的那样,不知道如何将长度确定添加到您已经拥有的任何查询中。
–亚伦·伯特兰(Aaron Bertrand)
2013年12月16日12:42