如何在大查询中找到sql上的"字符串或二进制数据将被截断"错误

Ari*_*MAZ 14 sql sql-server

我有一个巨大的INSERT INTO TABLE1 (....) SELECT .... FROM TABLE2声明.它给了我错误

"字符串或二进制数据将被截断".

我知道TABLE2中的一个列对于INSERT语句中TABLE1的一列来说更大.

我在每个表中有超过100列.所以很难找出问题所在.有没有更简单的方法来解决这个问题?

Zoh*_*led 15

您可以查询Information_Schema.Columns这两个表并检查内容长度的差异.

假设您的表具有相同的列名,您可以使用:

SELECT t1.Table_Name, t1.Column_Name
FROM INFORMATION_SCHEMA.Columns t1
INNER JOIN INFORMATION_SCHEMA.Columns t2 ON (t1.Column_Name = t2.Column_Name)
WHERE t1.Table_Name = 'Table1'
AND  t2.Table_Name = 'Table2'
AND ISNULL(t1.Character_maximum_length, 0) < ISNULL(t2.Character_maximum_length, 0)
Run Code Online (Sandbox Code Playgroud)

假设您的表有不同的列名,您可以这样做,只是寻找差异

SELECT Table_Name, Column_Name, Character_maximum_length
FROM INFORMATION_SCHEMA.Columns
WHERE Table_Name IN('Table1', 'Table2')
ORDER BY Column_Name, Character_maximum_length, Table_Name
Run Code Online (Sandbox Code Playgroud)


Ton*_*ony 5

要确定数据太长适合哪一列,我将使用以下语句将结果输出到临时表。

SELECT ... 
INTO MyTempTable 
FROM Table2 
Run Code Online (Sandbox Code Playgroud)

然后使用从查询例如这篇文章让每列的最大数据长度。我附上了下面的代码副本。

DECLARE @TableName sysname = 'MyTempTable', @TableSchema sysname = 'dbo'
DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = STUFF((SELECT 
    ' UNION ALL select ' + 
    QUOTENAME(Table_Name,'''') + ' AS TableName, ' + 
    QUOTENAME(Column_Name,'''') + ' AS ColumnName, ' +  
    CASE WHEN DATA_TYPE IN ('XML','HierarchyID','Geometry','Geography','text','ntext') THEN 'MAX(DATALENGTH(' 
         ELSE 'MAX(LEN(' 
         END + QUOTENAME(Column_Name) + ')) AS MaxLength, ' + 
    QUOTENAME(C.DATA_TYPE,'''') + ' AS DataType, ' + 
    CAST(COALESCE(C.CHARACTER_MAXIMUM_LENGTH, C.NUMERIC_SCALE,0) AS VARCHAR(10)) + ' AS DataWidth ' + 
    'FROM ' + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(Table_Name)
FROM INFORMATION_SCHEMA.COLUMNS C 
WHERE TABLE_NAME = @TableName 
AND table_schema = @TableSchema
--AND DATA_TYPE NOT IN ('XML','HierarchyID','Geometry','Geography')
ORDER BY COLUMN_NAME 
FOR XML PATH(''),Type).value('.','varchar(max)'),1,11,'')  

EXECUTE (@SQL)
Run Code Online (Sandbox Code Playgroud)


Dav*_*ers 5

@ZoharPeled 答案很好,但是对于临时表,你必须做一些不同的事情:

SELECT t1.Table_Name
    ,t1.Column_Name
    ,t1.Character_maximum_length AS Table1_Character_maximum_length
    ,t2.Character_maximum_length AS Table2_Character_maximum_length
FROM INFORMATION_SCHEMA.Columns t1
INNER JOIN tempdb.INFORMATION_SCHEMA.COLUMNS t2 ON (t1.Column_Name = t2.Column_Name)
WHERE t1.Table_Name = 'Table1'
    AND t2.Table_Name LIKE '#Table2%' -- Don't remove the '%', it's required
    AND ISNULL(t1.Character_maximum_length, 0) < ISNULL(t2.Character_maximum_length, 0)
Run Code Online (Sandbox Code Playgroud)