【发布时间】:2012-06-07 14:51:24
【问题描述】:
我有一个目标表TargetTable,它有一个DECIMAL(20, 7) 列。我还有一个源表SourceTable,它有一个DECIMAL(20, 7) 列,但是这个表中的值无论如何都是整数。
当我尝试通过 MERGE 语句将数据从 SourceTable 插入到 TargetTable 时,出现标准错误。
将数字转换为数字数据类型时出现算术溢出错误。
我真的不明白为什么会发生这种情况,因为这两种数据类型是相同的。
不过,奇怪的是:当我在 TargetTable 上使用 SELECT INTO 创建测试表 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;
【问题讨论】:
-
另外,如果这听起来比 SO 更适合 dba.stackexchange.com,请权衡一下。
-
请发布您正在使用的查询,以便我们为您提供帮助
-
@Lamak:我认为没有必要发布代码,因为这似乎在原则上比在细节上更不一致,但我会发布代码。
-
您为什么不尝试使用 SET NUMERIC_ROUNDABORT Off 并查看将哪些结果插入到目标表中。这可能会让您了解是否有任何数据丢失
-
TargetTable上是否有可能导致此错误的触发器?
标签: sql sql-server sql-server-2008