私はデータ移行プロジェクトに携わっています。あるテーブルから別のテーブルにデータを挿入しようとすると、次のエラーが表示されます(SQL Server 2005)。
メッセージ8152、レベル16、状態13、行1
文字列型やバイナリは省略されます。
ソースデータ列はデータ型と一致し、宛先テーブル列の長さ定義内にあるため、このエラーの原因となっている可能性があるものについては迷います。
問題がどこにあるのかを突き止めるには、送信元テーブルと送信先テーブルのテーブル定義を投稿する必要があります。宛先列あなたが気付いていなかった方法でフォーマットを変えているのかもしれません。移動元のデータベースモデルは、それを理解する上でも重要です。
問題は非常に簡単です。ソースクエリ内の1つ以上の列に、宛先列の長さを超えるデータが含まれています。簡単な解決策は、あなたのソースクエリを取り、各カラムにMax(Len( source col ))
を実行することです。すなわち、
Select Max(Len(TextCol1))
, Max(Len(TextCol2))
, Max(Len(TextCol3))
, ...
From ...
次に、それらの長さを変換先テーブルのデータ型の長さと比較します。少なくとも1つが、宛先列の長さを超えています。
そうでないことが絶対的に正当である場合そしてそうでない場合は気にしないでください、それから別の解決策は強制的にそれらの目的の長さにソースクエリカラムをキャストすることです長すぎるデータ):
Select Cast(TextCol1 As varchar(...))
, Cast(TextCol2 As varchar(...))
, Cast(TextCol3 As varchar(...))
, ...
From ...
他の人がすでに言っているように、ソーステーブルのカラムデータ型の1つがデスティネーションカラムより大きいです。
簡単な解決策は、単に警告をオフにして切り捨てを可能にすることです。ですから、このエラーを受け取っていても、古いデータベース/テーブルのデータを切り捨てる(サイズに切り捨てる)ことが許容できると確信できる場合は、単に次のようにします。
SET ANSI_WARNINGS OFF;
-- Your insert TSQL here.
SET ANSI_WARNINGS ON;
上記のように、後で警告を再度表示することを忘れないでください。これが役に立つことを願っています。
これに対するもう1つの考えられる理由は、列の長さを超える列のデフォルト値の設定がある場合です。誰かが長さ5のカラムを指で触ったが、デフォルト値が長さ5を超えていたようです。テーブルスキーマのデフォルト値に違反するデフォルト値があると、すべてがめちゃくちゃになってしまうため、スキーマにデフォルト値のテーブルを含めることは避けてください。 :)
これはやりがいのあるエラーです。これは https://connect.Microsoft.com/japan/SQLServer/feedback/details/339410 / AmirCharaniaのコメントを参照してください。
AmirCharaniaが選んだデータの答えを、実際のテーブルではなく、実際のテーブルに合わせて調整しました。まず開発テーブルにデータセットを選択してから、以下を実行します。
WITH CTE_Dev
AS (
SELECT C.column_id
,ColumnName = C.NAME
,C.max_length
,C.user_type_id
,C.precision
,C.scale
,DataTypeName = T.NAME
FROM sys.columns C
INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
WHERE OBJECT_ID = OBJECT_ID('YOUR TARGET TABLE NAME HERE, WITH SCHEMA')
)
,CTE_Temp
AS (
SELECT C.column_id
,ColumnName = C.NAME
,C.max_length
,C.user_type_id
,C.precision
,C.scale
,DataTypeName = T.NAME
FROM sys.columns C
INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
WHERE OBJECT_ID = OBJECT_ID('YOUR TEMP TABLE NAME HERE, WITH SCHEMA')
)
SELECT *
FROM CTE_Dev D
FULL OUTER JOIN CTE_Temp T ON D.ColumnName = T.ColumnName
WHERE ISNULL(D.max_length, 0) < ISNULL(T.max_length, 999)
他の人のためにも、あなたのストアドプロシージャをチェックしてください。私の場合、ストアドプロシージャCustomSearch
で誤って列の長さが足りないと宣言したため、大きなデータを入力したときに、データベースに大きな長さがあってもそのエラーを受け取りました。カスタム検索で列の長さを変更しただけで、エラーはなくなりました。これは念のためです。ありがとう。
はい、私はまたこの種の問題に直面しています。
REMARKS VARCHAR(500)
to
REMARKS VARCHAR(1000)
ここで、REMARKSファイルの長さを500から1000に変更しました。
SQL Server 2019は、ついにもっと意味のあるエラーメッセージを返します。
バイナリデータまたは文字列データは切り捨てられます=>エラーメッセージが増えます
(本番環境で)そのエラーが発生した場合、このエラーがどの列または行に由来するのか、およびその正確な位置を特定する方法がわかりません。
新しい振る舞いを可能にするためにはDBCC TRACEON(460)
を使う必要があります。 sys.messages
からの新しいエラーテキスト:
SELECT * FROM sys.messages WHERE message_id = 2628
2628 - 文字列またはバイナリデータはテーブル '%。* ls'、列 '%。* ls'で切り捨てられます。切り捨てられた値: '%1!'
文字列またはバイナリデータは切り捨てられます。悪名高いエラー8152を置き換えます
この新しいメッセージは、SQL Server 2017 CU12(および今後のSQL Server 2016 SP2 CU)にもバックポートされますが、デフォルトではありません。セッションまたはサーバーレベルで、トレースフラグ460を有効にしてメッセージID 8152を2628に置き換える必要があります。
今のところ、SQL Server 2019 CTP 2.0でも、同じトレースフラグ460を有効にする必要があります。 将来のSQL Server 2019リリースでは、メッセージ2628がデフォルトでメッセージ8152に置き換わる予定です。
SQL Server 2017 CU12もこの機能をサポートします。
改善:SQL Server 2017では、「文字列またはバイナリデータは切り捨てられる」というメッセージが拡張情報に置き換えられました
このSQL Server 2017の更新プログラムでは、以下の追加のコンテキスト情報を含むオプションのメッセージが導入されました。
Msg 2628, Level 16, State 6, Procedure ProcedureName, Line Linenumber String or binary data would be truncated in table '%.*ls', column '%.*ls'. Truncated value: '%.*ls'.
新しいメッセージIDは2628です。トレースフラグ460が有効な場合、このメッセージはエラー出力のメッセージ8152を置き換えます。
私は今日この問題に出くわしました、そしてこの最小の有益なエラーメッセージへの答えを私の検索で私はまたこのリンクを見つけました:
そのため、Microsoftは近い将来エラーメッセージを表示する予定はありません。
だから私は他の手段に目を向けました。
エラーをExcelにコピーしました。
(影響を受ける1行)
(影響を受ける1行)
(影響を受ける1行)メッセージ8152、レベル16、状態14、行13文字列またはバイナリデータが切り捨てられます。ステートメントは終了されました。
(影響を受ける1行)
excelの行数を数え、問題の原因となったレコードカウンタに近づけました。エクスポートコードを調整して、SQLをそれに近い場所に印刷しました。問題の1つを特定し、長すぎる文字列を参照し、その列のサイズを大きくすると、大きなインポートファイルでも問題は発生しませんでした。
ちょっとしたハックとその回避策ですが、選択肢がほとんどなくなったら、できることをします。
適切な権限がない場合にも発生する可能性があります。
最小長(min_len)と最大長(max_len)の列ごとにいくつかの特性を持つソーステーブルまたはクエリを分析するストアドプロシージャを作成しました。
CREATE PROCEDURE [dbo].[sp_analysetable] (
@tableName varchar(8000),
@deep bit = 0
) AS
/*
sp_analysetable 'company'
sp_analysetable 'select * from company where name is not null'
*/
DECLARE @intErrorCode INT, @errorMSG VARCHAR(500), @tmpQ NVARCHAR(2000), @column_name VARCHAR(50), @isQuery bit
SET @intErrorCode=0
IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
DROP TABLE ##tmpTableToAnalyse
END
IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
DROP TABLE ##tmpColumns
END
if CHARINDEX('from', @tableName)>0
set @isQuery=1
IF @intErrorCode=0 BEGIN
if @isQuery=1 begin
--set @tableName = 'USE '+@db+';'+replace(@tableName, 'from', 'into ##tmpTableToAnalyse from')
--replace only first occurance. Now multiple froms may exists, but first from will be replaced with into .. from
set @tableName=Stuff(@tableName, CharIndex('from', @tableName), Len('from'), 'into ##tmpTableToAnalyse from')
exec(@tableName)
IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NULL BEGIN
set @intErrorCode=1
SET @errorMSG='Error generating temporary table from query.'
end
else begin
set @tableName='##tmpTableToAnalyse'
end
end
end
IF @intErrorCode=0 BEGIN
SET @tmpQ='USE '+DB_NAME()+';'+CHAR(13)+CHAR(10)+'
select
c.column_name as [column],
cast(sp.value as varchar(1000)) as description,
tc_fk.constraint_type,
kcu_pk.table_name as fk_table,
kcu_pk.column_name as fk_column,
c.ordinal_position as pos,
c.column_default as [default],
c.is_nullable as [null],
c.data_type,
c.character_maximum_length as length,
c.numeric_precision as [precision],
c.numeric_precision_radix as radix,
cast(null as bit) as [is_unique],
cast(null as int) as min_len,
cast(null as int) as max_len,
cast(null as int) as nulls,
cast(null as int) as blanks,
cast(null as int) as numerics,
cast(null as int) as distincts,
cast(null as varchar(500)) as distinct_values,
cast(null as varchar(50)) as remarks
into ##tmpColumns'
if @isQuery=1 begin
SET @tmpQ=@tmpQ+' from tempdb.information_schema.columns c, (select null as value) sp'
end
else begin
SET @tmpQ=@tmpQ+'
from information_schema.columns c
left join sysobjects so on so.name=c.table_name and so.xtype=''U''
left join syscolumns sc on sc.name=c.column_name and sc.id =so.id
left join sys.extended_properties sp on sp.minor_id = sc.colid AND sp.major_id = sc.id and sp.name=''MS_Description''
left join information_schema.key_column_usage kcu_fk on kcu_fk.table_name = c.table_name and c.column_name = kcu_fk.column_name
left join information_schema.table_constraints tc_fk on kcu_fk.table_name = tc_fk.table_name and kcu_fk.constraint_name = tc_fk.constraint_name
left join information_schema.referential_constraints rc on rc.constraint_name = kcu_fk.constraint_name
left join information_schema.table_constraints tc_pk on rc.unique_constraint_name = tc_pk.constraint_name
left join information_schema.key_column_usage kcu_pk on tc_pk.constraint_name = kcu_pk.constraint_name
'
end
SET @tmpQ=@tmpQ+' where c.table_name = '''+@tableName+''''
exec(@tmpQ)
end
IF @intErrorCode=0 AND @deep = 1 BEGIN
DECLARE
@count_rows int,
@count_distinct int,
@count_nulls int,
@count_blanks int,
@count_numerics int,
@min_len int,
@max_len int,
@distinct_values varchar(500)
DECLARE curTmp CURSOR LOCAL FAST_FORWARD FOR
select [column] from ##tmpColumns;
OPEN curTmp
FETCH NEXT FROM curTmp INTO @column_name
WHILE @@FETCH_STATUS = 0 and @intErrorCode=0 BEGIN
set @tmpQ = 'USE '+DB_NAME()+'; SELECT'+
' @count_rows=count(0), '+char(13)+char(10)+
' @count_distinct=count(distinct ['+@column_name+']),'+char(13)+char(10)+
' @count_nulls=sum(case when ['+@column_name+'] is null then 1 else 0 end),'+char(13)+char(10)+
' @count_blanks=sum(case when ltrim(['+@column_name+'])='''' then 1 else 0 end),'+char(13)+char(10)+
' @count_numerics=sum(isnumeric(['+@column_name+'])),'+char(13)+char(10)+
' @min_len=min(len(['+@column_name+'])),'+char(13)+char(10)+
' @max_len=max(len(['+@column_name+']))'+char(13)+char(10)+
' from ['+@tableName+']'
exec sp_executesql @tmpQ,
N'@count_rows int OUTPUT,
@count_distinct int OUTPUT,
@count_nulls int OUTPUT,
@count_blanks int OUTPUT,
@count_numerics int OUTPUT,
@min_len int OUTPUT,
@max_len int OUTPUT',
@count_rows OUTPUT,
@count_distinct OUTPUT,
@count_nulls OUTPUT,
@count_blanks OUTPUT,
@count_numerics OUTPUT,
@min_len OUTPUT,
@max_len OUTPUT
IF (@count_distinct>10) BEGIN
SET @distinct_values='Many ('+cast(@count_distinct as varchar)+')'
END ELSE BEGIN
set @distinct_values=null
set @tmpQ = N'USE '+DB_NAME()+';'+
' select @distinct_values=COALESCE(@distinct_values+'',''+cast(['+@column_name+'] as varchar), cast(['+@column_name+'] as varchar))'+char(13)+char(10)+
' from ('+char(13)+char(10)+
' select distinct ['+@column_name+'] from ['+@tableName+'] where ['+@column_name+'] is not null) a'+char(13)+char(10)
exec sp_executesql @tmpQ,
N'@distinct_values varchar(500) OUTPUT',
@distinct_values OUTPUT
END
UPDATE ##tmpColumns SET
is_unique =case when @count_rows=@count_distinct then 1 else 0 end,
distincts =@count_distinct,
nulls =@count_nulls,
blanks =@count_blanks,
numerics =@count_numerics,
min_len =@min_len,
max_len =@max_len,
distinct_values=@distinct_values,
remarks =
case when @count_rows=@count_nulls then 'all null,' else '' end+
case when @count_rows=@count_distinct then 'unique,' else '' end+
case when @count_distinct=0 then 'empty,' else '' end+
case when @min_len=@max_len then 'same length,' else '' end+
case when @count_rows=@count_numerics then 'all numeric,' else '' end
WHERE [column]=@column_name
FETCH NEXT FROM curTmp INTO @column_name
END
CLOSE curTmp DEALLOCATE curTmp
END
IF @intErrorCode=0 BEGIN
select * from ##tmpColumns order by pos
end
IF @intErrorCode=0 BEGIN --Clean up temporary tables
IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
DROP TABLE ##tmpTableToAnalyse
END
IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
DROP TABLE ##tmpColumns
END
end
IF @intErrorCode<>0 BEGIN
RAISERROR(@errorMSG, 12, 1)
END
RETURN @intErrorCode
この手順をmasterデータベースに格納して、すべてのデータベースで次のように使用できるようにします。
sp_analysetable 'table_name', 1
// deep=1 for doing value analyses
そして出力は次のとおりです。
column description constraint_type fk_table fk_column pos default null data_type length precision radix is_unique min_len max_len nulls blanks numerics distincts distinct_values remarks
id_individual NULL PRIMARY KEY NULL NULL 1 NULL NO int NULL 10 10 1 1 2 0 0 70 70 Many (70) unique,all numeric,
id_brand NULL NULL NULL NULL 2 NULL NO int NULL 10 10 0 1 1 0 0 70 2 2,3 same length,all numeric, guid NULL NULL NULL NULL 3 (newid()) NO uniqueidentifier NULL NULL NULL 1 36 36 0 0 0 70 Many (70) unique,same length,
customer_id NULL NULL NULL NULL 4 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
email NULL NULL NULL NULL 5 NULL YES varchar 100 NULL NULL 0 4 36 0 0 0 31 Many (31)
mobile NULL NULL NULL NULL 6 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
initials NULL NULL NULL NULL 7 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_short NULL NULL NULL NULL 8 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_long NULL NULL NULL NULL 9 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
firstname NULL NULL NULL NULL 10 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
lastname NULL NULL NULL NULL 11 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
address NULL NULL NULL NULL 12 NULL YES varchar 100 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
pc NULL NULL NULL NULL 13 NULL YES varchar 10 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
kixcode NULL NULL NULL NULL 14 NULL YES varchar 20 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
date_created NULL NULL NULL NULL 15 (getdate()) NO datetime NULL NULL NULL 1 19 19 0 0 0 70 Many (70) unique,same length,
created_by NULL NULL NULL NULL 16 (user_name()) NO varchar 50 NULL NULL 0 13 13 0 0 0 1 loyalz-public same length,
id_location_created NULL FOREIGN KEY location id_location 17 NULL YES int NULL 10 10 0 1 1 0 0 70 2 1,2 same length,all numeric, id_individual_type NULL FOREIGN KEY individual_type id_individual_type 18 NULL YES int NULL 10 10 0 NULL NULL 70 0 0 0 NULL all null,empty,
optin NULL NULL NULL NULL 19 NULL YES int NULL 10 10 0 1 1 39 0 31 2 0,1 same length,
うん - "ハーフパイントポットへのパイントは行かないだろう"。 2つのテーブルが同じDB内にある限り(または同じDBに入れることができる限り)、私たちは(なんらかの理由で)多くのSPがあまりにも多くの運を持っていないことを知っています。誤ったフィールドを見つけるためのCOLUMNS。
select c1.table_name,c1.COLUMN_NAME,c1.DATA_TYPE,c1.CHARACTER_MAXIMUM_LENGTH,c2.table_name,c2.COLUMN_NAME, c2.DATA_TYPE,c2.CHARACTER_MAXIMUM_LENGTH
from [INFORMATION_SCHEMA].[COLUMNS] c1
left join [INFORMATION_SCHEMA].[COLUMNS] c2 on
c1.COLUMN_NAME=c2.COLUMN_NAME
where c1.TABLE_NAME='MyTable1'
and c2.TABLE_NAME='MyTable2'
--and c1.DATA_TYPE<>c2.DATA_TYPE
--and c1.CHARACTER_MAXIMUM_LENGTH <> c2.CHARACTER_MAXIMUM_LENGTH
order by c1.COLUMN_NAME
これにより、フィールドの長さを比較しながら上下にスクロールできます。コメントされたセクションでは、データ型の不一致があるかどうか、またはフィールド長が異なるものを具体的に示すかどうかを確認できます(cosはスクロールできないので注意してください)。ターゲットの列名と一致する列名。
私は誰もそれを言及していないという理由だけでこのエラーのもう一つの考えられる原因を追加するつもりです、そしてそれは将来の人を助けるかもしれません(OPが彼の答えを見つけたので)。挿入しているテーブルにトリガがある場合、トリガがエラーを生成している可能性があります。これはテーブルフィールドの定義が変更されたときに発生しましたが、監査テーブルは変更されていません。
INSERT SELECTステートメントを使用したときのテキストの切り捨て(文字列またはバイナリデータが切り捨てられる)の問題を識別して解決するために役立つストアプロシージャを作成しました。 CHAR、VARCHAR、NCHAR、NVARCHARの各フィールドのみを比較し、エラーの原因として考えられる場合にはフィールドごとに評価フィールドを返します。
EXEC dbo.GetFieldStringTruncate SourceTableName, TargetTableName
このストアドプロシージャは、INSERT SELECTステートメントが作成されたときのテキストの切り捨ての問題を対象としています。
このストアドプロシージャの操作は、問題のあるINSERTステートメントを以前に識別したユーザーによって異なります。次に、ソースデータをグローバル一時表に挿入します。 SELECT INTOステートメントをお勧めします。
SELECTステートメントの各フィールドの別名には、宛先テーブルのフィールドと同じ名前を使用する必要があります。
機能コード:
DECLARE @strSQL nvarchar(1000)
IF NOT EXISTS (SELECT * FROM dbo.sysobjects where id = OBJECT_ID(N'[dbo].[GetFieldStringTruncate]'))
BEGIN
SET @strSQL = 'CREATE PROCEDURE [dbo].[GetFieldStringTruncate] AS RETURN'
EXEC sys.sp_executesql @strSQL
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
------------------------------------------------------------------------------------------------------------------------
Description:
Syntax
---------------
dbo.GetFieldStringTruncate(SourceTable, TargetTable)
+---------------------------+-----------------------+
| SourceTableName | VARCHAR(255) |
+---------------------------+-----------------------+
| TargetTableName | VARCHAR(255) |
+---------------------------+-----------------------+
Arguments
---------------
SourceTableName
The name of the source table. It should be a temporary table using double charp '##'. E.g. '##temp'
TargetTableName
The name of the target table. It is the table that receives the data used in the INSERT INTO stament.
Return Type
----------------
Returns a table with a list of all the fields with the type defined as text and performs an evaluation indicating which field would present the problem of string truncation.
Remarks
----------------
This stored procedure is oriented to the problem of text truncation when an INSERT SELECT statement is made.
The operation of this stored procedure depends on the user previously identifying the INSERT statement with the problem. Then inserting the source data into a global temporary table. The SELECT INTO statement is recommended.
You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.
Examples
====================================================================================================
--A. Test basic
IF EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[tblDestino]') AND TYPE IN (N'U'))
DROP TABLE tblDestino
CREATE TABLE tblDestino
(
Id INT IDENTITY,
Field1 VARCHAR(10),
Field2 VARCHAR(12),
Field3 VARCHAR(11),
Field4 VARCHAR(16),
Field5 VARCHAR(5),
Field6 VARCHAR(1),
Field7 VARCHAR(1),
Field8 VARCHAR(6),
Field9 VARCHAR(6),
Field10 VARCHAR(50),
Field11 VARCHAR(50),
Field12 VARCHAR(50)
)
INSERT INTO dbo.tblDestino
(
Field1 ,
Field2 ,
Field3 ,
Field4 ,
Field5 ,
Field6 ,
Field7 ,
Field8 ,
Field9 ,
Field10 ,
Field11 ,
Field12
)
SELECT
'123456789' , -- Field1 - varchar(10)
'123456789' , -- Field2 - varchar(12)
'123456789' , -- Field3 - varchar(11)
'123456789' , -- Field4 - varchar(16)
'123456789' , -- Field5 - varchar(5)
'123456789' , -- Field6 - varchar(1)
'123456789' , -- Field7 - varchar(1)
'123456789' , -- Field8 - varchar(6)
'123456789' , -- Field9 - varchar(6)
'123456789' , -- Field10 - varchar(50)
'123456789' , -- Field11 - varchar(50)
'123456789' -- Field12 - varchar(50)
GO
Result:
String or binary data would be truncated
*Here you get the truncation error. Then, we proceed to save the information in a global temporary table.
*IMPORTANT REMINDER: You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.
Process:
IF OBJECT_ID('tempdb..##TEMP') IS NOT NULL DROP TABLE ##TEMP
go
SELECT
[Field1] = '123456789' ,
[Field2] = '123456789' ,
[Field3] = '123456789' ,
[Field4] = '123456789' ,
[Field5] = '123456789' ,
[Field6] = '123456789' ,
[Field7] = '123456789' ,
[Field8] = '123456789' ,
[Field9] = '123456789' ,
[Field10] = '123456789' ,
[Field11] = '123456789' ,
[Field12] = '123456789'
INTO ##TEMP
Result:
(1 row(s) affected)
Test:
EXEC dbo.GetFieldStringTruncate @SourceTableName = '##TEMP', @TargetTableName = 'tblDestino'
Result:
(12 row(s) affected)
ORIGEN Nombre Campo ORIGEN Maximo Largo DESTINO Nombre Campo DESTINO Tipo de campo Evaluación
-------------------------- -------------------- ------------------------ ----------------------- -------------------------
Field1 9 02 - Field1 VARCHAR(10)
Field2 9 03 - Field2 VARCHAR(12)
Field3 9 04 - Field3 VARCHAR(11)
Field4 9 05 - Field4 VARCHAR(16)
Field5 9 06 - Field5 VARCHAR(5) possible field with error
Field6 9 07 - Field6 VARCHAR(1) possible field with error
Field7 9 08 - Field7 VARCHAR(1) possible field with error
Field8 9 09 - Field8 VARCHAR(6) possible field with error
Field9 9 10 - Field9 VARCHAR(6) possible field with error
Field10 9 11 - Field10 VARCHAR(50)
Field11 9 12 - Field11 VARCHAR(50)
Field12 9 13 - Field12 VARCHAR(50)
====================================================================================================
------------------------------------------------------------------------------------------------------------
Responsible: Javier Pardo
Date: October 19/2018
WB tests: Javier Pardo
------------------------------------------------------------------------------------------------------------
*/
ALTER PROCEDURE dbo.GetFieldStringTruncate
(
@SourceTableName AS VARCHAR(255)
, @TargetTableName AS VARCHAR(255)
)
AS
BEGIN
BEGIN TRY
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@colsUnpivotConverted AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
SELECT @colsUnpivot = stuff((
SELECT DISTINCT ',' + QUOTENAME(col.NAME)
FROM tempdb.sys.tables tab
INNER JOIN tempdb.sys.columns col
ON col.object_id = tab.object_id
INNER JOIN tempdb.sys.types typ
ON col.system_type_id = TYP.system_type_id
WHERE tab.NAME = @SourceTableName
FOR XML path('')
), 1, 1, '')
,@colsUnpivotConverted = stuff((
SELECT DISTINCT ',' + 'CONVERT(VARCHAR(MAX),' + QUOTENAME(col.NAME) + ') AS ' + QUOTENAME(col.NAME)
FROM tempdb.sys.tables tab
INNER JOIN tempdb.sys.columns col
ON col.object_id = tab.object_id
INNER JOIN tempdb.sys.types typ
ON col.system_type_id = TYP.system_type_id
WHERE tab.NAME = @SourceTableName
FOR XML path('')
), 1, 1, '')
--https://stackoverflow.com/questions/11158017/column-conflicts-with-the-type-of-other-columns-in-the-unpivot-list
IF OBJECT_ID('tempdb..##TablaConMaximos') IS NOT NULL DROP TABLE ##TablaConMaximos
set @query
= 'SELECT u.d AS colname, MAX(LEN(u.data)) as [maximo_largo]
INTO ##TablaConMaximos
FROM
(
SELECT ' + @colsUnpivotConverted + '
FROM ' + @SourceTableName + '
) T
UNPIVOT
(
data
for d in ('+ @colsunpivot +')
) u
GROUP BY u.d'
PRINT @query
exec sp_executesql @query;
------------------------------------------------------------------------------------------------------------
SELECT --'Nombre de campo' = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
--, 'Tipo de campo' = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
[ORIGEN Nombre Campo] = tcm.colname
, [ORIGEN Maximo Largo] = tcm.maximo_largo
, [DESTINO Nombre Campo] = DESTINO.[Nombre de campo]
, [DESTINO Tipo de campo] = DESTINO.[Tipo de campo]
, [Evaluación] = CASE WHEN DESTINO.maximo_largo < tcm.maximo_largo THEN 'possible field with error' ELSE '' END
--, *
FROM tempdb.sys.tables tab
INNER JOIN tempdb.sys.columns col
ON col.object_id = tab.object_id
INNER JOIN tempdb.sys.types typ
ON col.system_type_id = TYP.system_type_id
RIGHT JOIN
(
SELECT column_id
, [Nombre de campo] = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
, [Tipo de campo] = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
, [maximo_largo] = col.max_length
, [colname] = col.name
FROM sys.tables tab
INNER JOIN sys.columns col
ON col.object_id = tab.object_id
INNER JOIN sys.types typ
ON col.system_type_id = TYP.system_type_id
WHERE tab.NAME = @TargetTableName
) AS DESTINO
ON col.name = DESTINO.colname
INNER JOIN ##TablaConMaximos tcm
ON tcm.colname = DESTINO.colname
WHERE tab.NAME = @SourceTableName
AND typ.name LIKE '%char%'
ORDER BY col.column_id
END TRY
BEGIN CATCH
SELECT 'Internal error ocurred' AS Message
END CATCH
END
現時点では、データ型CHAR、VARCHAR、NCHAR、およびNVARCHARのみをサポートしています。このコードの最後のバージョンは、次のリンクで見つけることができます。また、お互いの改善に役立っています。 GetFieldStringTruncate.sql
https://Gist.github.com/jotapardo/210e85338f87507742701aa9d41cc51d
これは少し違う答えです。列名と長さはすべて一致する可能性がありますが、おそらくSELECTステートメントで間違った順序で列を指定しています。 tableXとtableYに同じ名前の列があるが順序が異なるとします。
テーブルの作成時に空の文字列 ''を使用していて、その後の更新時に 'Msg 8152、文字列またはバイナリデータが切り捨てられる'というエラーが表示されました。これは、更新値が6文字で、予想される列定義よりも大きいために発生していました。これを回避するために "SPACE"を使用したのは、最初のデータ作成後に一括で更新することがわかっていたためです。
ここで大きな警告:これは特に巧妙な解決策ではありませんが、あなたがデータセットを集める場合には役に立ちます。データマイニング用のテーブルを作成し、一括処理/解釈を適用し、後で比較/マイニングするために結果の前後に格納する、1回限りのインテリジェンス要求の場合。これは私の職業によく見られます。
最初にSPACEキーワードを使用して入力できます。
select
Table1.[column1]
,Table1.[column2]
,SPACE(10) as column_name
into table_you_are_creating
from Table1
where ...
その後の "column_name"への10文字以下の更新(必要に応じて置換)は、切り捨てエラーを引き起こさずに許可されます。繰り返しますが、これは私の警告で説明したのと同じようなシナリオでのみ使用します。
次のコードを試してください。
CREATE TABLE [dbo].[Department](
[Department_name] char(10) NULL
)
INSERT INTO [dbo].[Department]([Department_name]) VALUES ('Family Medicine')
--error will occur
ALTER TABLE [Department] ALTER COLUMN [Department_name] char(50)
INSERT INTO [dbo].[Department]([Department_name]) VALUES ('Family Medicine')
select * from [Department]
このエラーは、テーブルのカラムに制約(ほとんどの場合は長さ)が設定されている場合にスローされます。 。例えば。列myColumnのデータベーススキーマがCHAR(2)の場合は、アプリケーションから呼び出して値を挿入するときに、長さ2のStringを渡す必要があります。
エラーは基本的にそれを言います。長さ3以上の文字列は、データベーススキーマで指定されている長さ制限に適合しません。 SQL Serverが警告し、データの損失/切り捨てエラーをスローするのはそのためです。
私は同様の問題を抱えていました。名前以外のすべてのもので、あるテーブルから同一のテーブルにデータをコピーしていました。
最終的に、SELECT INTO文を使用してソース表を一時表にダンプしました。
SELECT *
INTO TEMP_TABLE
FROM SOURCE_TABLE;
ソース表のスキーマと一時表を比較しました。 varchar(4000)
を期待していたとき、私はその列の1つがvarchar(250)
であることを発見しました。
更新:あなたが興味を持っているならば、varchar(4000)問題はここで説明されることができます:
Nvarchar(Max)の場合、TSQLでは4000文字しか取得できません。
お役に立てれば。