[sql-server] SQL Server 문자열 또는 이진 데이터가 잘립니다

데이터 마이그레이션 프로젝트에 참여하고 있습니다. 한 테이블에서 다른 테이블로 데이터를 삽입하려고하면 다음 오류가 발생합니다 (SQL Server 2005).

메시지 8152, 수준 16, 상태 13, 줄 1
문자열 또는 이진 데이터가 잘립니다.

소스 데이터 열은 데이터 유형과 일치하고 대상 테이블 열의 길이 정의 내에 있으므로이 오류의 원인에 대해 손실됩니다.



답변

문제의 위치를 ​​파악하기 위해 소스 및 대상 테이블에 대한 테이블 정의를 게시해야하지만 , 결론은 소스 테이블의 열 중 하나가 대상 열보다 크다는 것 입니다. 모르는 방식으로 형식을 변경하고있을 수 있습니다. 이동하려는 데이터베이스 모델도이를 파악하는 데 중요합니다.


답변

다른 사람들이 이미 말했듯이 소스 테이블의 열 데이터 유형 중 하나가 대상 열보다 큽니다.

간단한 해결책은 단순히 경고를 끄고 잘리는 것을 허용하는 것입니다. 따라서이 오류가 발생하지만 이전 데이터베이스 / 테이블의 데이터가 잘 리거나 크기가 잘릴 수있는 경우 다음을 수행하면됩니다.

SET ANSI_WARNINGS  OFF;
-- Your insert TSQL here.
SET ANSI_WARNINGS ON;

위와 같이 항상 경고를 다시 설정해야합니다. 이게 도움이 되길 바란다.


답변

이 문제는 매우 간단합니다. 소스 쿼리의 하나 이상의 열에 대상 열의 길이를 초과하는 데이터가 포함되어 있습니다. 간단한 해결책은 소스 쿼리를 가져와 Max(Len( source col ))각 열에서 실행 하는 것입니다. 즉,

Select Max(Len(TextCol1))
    , Max(Len(TextCol2))
    , Max(Len(TextCol3))
    , ...
From ...

그런 다음 해당 길이를 대상 테이블의 데이터 유형 길이와 비교하십시오. 하나 이상이 대상 열 길이를 초과합니다.

이것이 사실이 아니어야 하고 그것이 사실이 아닌지 신경 쓰지 않는다고 절대적으로 긍정적 인 경우 , 또 다른 해결책은 소스 쿼리 열을 대상 길이로 강제로 캐스트하는 것입니다 (너무 긴 데이터는 잘림).

Select Cast(TextCol1 As varchar(...))
    , Cast(TextCol2 As varchar(...))
    , Cast(TextCol3 As varchar(...))
    , ...
From ...


답변

SQL Server 2019 는 마침내 더 의미있는 오류 메시지를 반환합니다.

이진 또는 문자열 데이터가 잘립니다 => 오류 메시지 향상

해당 오류 (생산 중)가있는 경우이 오류가 발생하는 열 또는 행과 정확한 위치를 확인하는 방법이 명확하지 않습니다.

새로운 동작을 사용하려면을 사용해야 DBCC TRACEON(460)합니다. 의 새로운 오류 텍스트 sys.messages:

SELECT * FROM sys.messages WHERE message_id = 2628

2628 – 열 ‘%. * ls’의 테이블 ‘%. * ls’에서 문자열 또는 이진 데이터가 잘립니다. 잘린 값 : ‘%. * ls’.

문자열 또는 이진 데이터가 잘립니다 : 악명 높은 오류 8152 대체

이 새 메시지는 SQL Server 2017 CU12 (및 곧 출시 될 SQL Server 2016 SP2 CU)에도 백 포트되지만 기본적으로는 아닙니다. 세션 또는 서버 레벨에서 메시지 ID 8152를 2628으로 바꾸려면 추적 플래그 460을 활성화해야합니다.

현재로서는 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를 대체합니다.

db <> 바이올린 데모


데이터베이스 범위 변경 구성

VERBOSE_TRUNCATION_WARNINGS = {ON | 끄기}

적용 대상 : SQL Server (SQL Server 2019 (15.x로 시작)) 및 Azure SQL Database

새 문자열을 활성화하거나 비활성화 할 수 있습니다. 이진 데이터가 잘 리면 오류 메시지가 표시됩니다. SQL Server 2019 (15.x)에는이 시나리오에 대해보다 구체적인 새 오류 메시지 (2628)가 도입되었습니다.

String or binary data would be truncated in table '%.*ls', column'%.*ls'. Truncated value: '%.*ls'.

데이터베이스 호환성 수준 150에서 ON으로 설정하면 자르기 오류가 새 오류 메시지 2628을 발생시켜 더 많은 컨텍스트를 제공하고 문제 해결 프로세스를 단순화합니다.

데이터베이스 호환성 수준 150에서 OFF로 설정하면 잘림 오류로 인해 이전 오류 메시지 8152가 발생합니다.

데이터베이스 호환성 레벨 140 이하의 경우, 오류 메시지 2628은 추적 플래그 460을 사용해야하는 옵트 인 오류 메시지로 남아 있으며이 데이터베이스 범위 구성은 적용되지 않습니다.


답변

다른 잠재적 인 이유는 열 길이를 초과하는 열에 기본값을 설정 한 경우입니다. 누군가가 길이가 5 인 열을 뚱뚱한 것으로 보였지만 기본값은 길이가 5를 초과했습니다. 이것은 내가 삽입하는 모든 것이라도 테이블 스키마의 기본값에 위반 기본값이 있기 때문에 모든 것을 엉망으로 만들었습니다. 이로 인해 교훈을 얻었습니다. 기본 값이있는 테이블을 스키마에 두지 마십시오. 🙂


답변

다른 경우에는 저장 프로시 저도 확인하십시오 . 내 경우에는 저장 프로 시저에서 CustomSearch실수로 열의 길이가 충분하지 않다고 선언 했으므로 큰 데이터를 입력하면 데이터베이스의 길이가 길어도 오류가 발생했습니다. 사용자 정의 검색에서 열 길이를 변경하여 오류가 사라졌습니다. 이것은 단지 알림입니다. 감사.


답변

이것은 어려운 오류 일 수 있습니다. 다음은 https://connect.microsoft.com/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)