2012-06-07 3 views
3

대상 테이블 TargetTable에는 DECIMAL(20, 7) 컬럼이 있습니다. 또한 DECIMAL(20, 7) 컬럼을 가지고있는 소스 테이블 SourceTable을 가지고 있지만,이 테이블의 값은 모두 정수입니다.MERGE로 산술 오버플로 오류 (숫자를 숫자로 나타냄) : SQL Server 버그?

TargetTableSourceTable에서 MERGE 문을 사용하여 데이터를 업 샘플하려고하면 표준 오류가 발생합니다.

수치를 데이터 유형 숫자로 변환하는 산술 오버플로 오류.

두 데이터 유형이 모두 동일하므로 왜 이런 일이 발생하는지 이해가되지 않습니다.

이상한 것은, 그래도 이것이다 : 다음, 테스트 테이블 TestTable을 만들 TestTable에 병합의 대상을 변경 TargetTableSELECT INTO를 사용할 때 upsert가 완료됩니다. TargetTableTestTable이 대부분 동일하기 때문에 나는 이것이 왜 그런지 이해할 수 없습니다.

누구나 전에이 문제가 발생 했습니까? 버그입니까, 아니면 모호한 SQL Server의 뉘앙스가 있습니까?


샘플 코드 :

실패 :

SET NUMERIC_ROUNDABORT Off 
GO 

MERGE 
    TargetTable Target 
USING 
    (
     SELECT 
      cast(forecast as DECIMAL(20, 7)) forecast 
      ,[SegmentID] 
      ,[Country] 
      ,[Environment] 
      ,[YearColumn] 
      ,[ForecastYear] 
      ,[Criterion] 
     FROM 
      SourceTable 
    ) Source 
    ON 
    (
     Target.SegmentID = Source.SegmentID 
     AND Target.Country = Source.Country 
     AND Target.Environment = Source.Environment 
     AND Target.YearColumn = Source.YearColumn 
     AND Target.ForecastYear = Source.ForecastYear 
     AND Target.Criterion = Source.Criterion 
    ) 
WHEN NOT MATCHED BY TARGET AND Source.Forecast <> 0 AND Source.Forecast IS NOT NULL THEN 
    INSERT (SegmentID, Country, Environment, YearColumn, Forecast, ForecastYear, Criterion) 
    VALUES (Source.SegmentID, Source.Country, Source.Environment, Source.YearColumn, Source.Forecast, Source.ForecastYear, Source.Criterion) 
WHEN MATCHED AND (Source.Forecast = 0 OR Source.Forecast IS NULL) THEN 
    DELETE 
WHEN MATCHED AND Source.Forecast <> Target.Forecast THEN 
    UPDATE SET Target.Forecast = Source.Forecast; 

성공합니다 :

SELECT 
    * 
INTO 
    TestTable 
FROM 
    TargetTable 
GO 

SET NUMERIC_ROUNDABORT Off 
GO 

MERGE 
    TestTable Target 
USING 
    (
     SELECT 
      cast(forecast as DECIMAL(20, 7)) forecast 
      ,[SegmentID] 
      ,[Country] 
      ,[Environment] 
      ,[YearColumn] 
      ,[ForecastYear] 
      ,[Criterion] 
     FROM 
      SourceTable 
    ) Source 
    ON 
    (
     Target.SegmentID = Source.SegmentID 
     AND Target.Country = Source.Country 
     AND Target.Environment = Source.Environment 
     AND Target.YearColumn = Source.YearColumn 
     AND Target.ForecastYear = Source.ForecastYear 
     AND Target.Criterion = Source.Criterion 
    ) 
WHEN NOT MATCHED BY TARGET AND Source.Forecast <> 0 AND Source.Forecast IS NOT NULL THEN 
    INSERT (SegmentID, Country, Environment, YearColumn, Forecast, ForecastYear, Criterion) 
    VALUES (Source.SegmentID, Source.Country, Source.Environment, Source.YearColumn, Source.Forecast, Source.ForecastYear, Source.Criterion) 
WHEN MATCHED AND (Source.Forecast = 0 OR Source.Forecast IS NULL) THEN 
    DELETE 
WHEN MATCHED AND Source.Forecast <> Target.Forecast THEN 
    UPDATE SET Target.Forecast = Source.Forecast; 
+0

dba.stackexchange.com에 비해 적절하다고 판단되면 –

+2

에 문의하시기 바랍니다. 사용하시는 질문을 게시하여 도와 드리겠습니다. – Lamak

+0

@Lamak : 코드 게시를 생각하지 않았습니다. 이것이 구체적 일 때보다는 원칙적으로 일관성이없는 것처럼 보이기 때문에 필요합니다. 그러나 나는 코드를 게시 할 것입니다. –

답변

9

코드는 전혀 오류가없는 것으로 보인다. 또한 원본 테이블에 오류가 없다는 것을 보여주는 것과 동일한 구조와 데이터를 사용하여 다른 테이블을 대상으로 만들면 올바르게 작동한다는 사실도 알 수 있습니다. 가장 가능성있는 이유는 실패한 쿼리를 실행하고있는 원래 테이블에서 트리거가 발생했기 때문입니다.

+0

그래서 이론적으로, 나는 결국 코드를 ​​게시 할 필요가 없었습니까? :)하지만 공유에 다시 한 번 감사드립니다. –

+3

사실, 코드를 보지 않고서는 오류가 없다는 것을 결코 알지 못했을 것입니다. 아마도 그 범인은 방아쇠 였을 것입니다 – Lamak

관련 문제