Ошибка арифметического переполнения (числовое числовое значение) с ошибкой MERGE: SQL Server?

У меня есть целевая таблица TargetTable, которая имеет столбец DECIMAL(20, 7). У меня также есть исходная таблица SourceTable, которая имеет столбец DECIMAL(20, 7), но значения в этой таблице все равно целые числа.

Когда я пытаюсь загрузить данные в TargetTable из SourceTable с помощью инструкции MERGE, я получаю стандартную ошибку.

Ошибка арифметического переполнения, преобразующая числовые данные в числовые данные.

Я действительно не понимаю, почему это произойдет, поскольку оба типа данных идентичны.

Однако это странно: когда я использую SELECT INTO on TargetTable для создания тестовой таблицы TestTable, измените цель слияния на TestTable, upsert завершает. Я также не понимаю, почему это было бы так, поскольку TargetTable и TestTable по большей части идентичны.

Кто-нибудь сталкивался с этим раньше, это ошибка, или есть какой-то неясный нюанс 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;

Ответ 1

У вашего кода, похоже, нет никакой ошибки. Кроме того, тот факт, что он отлично работает, когда вы создаете другую таблицу в качестве цели, используя ту же структуру и данные, что в исходной таблице показано, что ошибки там нет. Наиболее вероятная причина заключается в том, что у вас есть триггер в исходной таблице, выполняющий запрос, который терпит неудачу, и это ошибка, которую вы видите.