1

我在 SQL Server 2012 中遇到了这个问题,但它在 SQL Server 2017 中也很明显。

我的数据库表称为它MyTable,包含一个不可为空的decimal(18,6)列。new_balance该表还包含两个整数列,它们是主键的一部分。没有其他整数字段。

存储过程有一个参数,该参数@new_balance也定义为decimal(18,6). 还有 id( @id) 和 seq_num( @seq_num) 的参数,都定义为int.

该过程按照以下行在表中执行插入:

INSERT INTO MyTable (id, seq_num, new_balance)
VALUES (@id, @seq_num, @new_balance);

@new_balance设置为 2147483647.999999 或更低时,插入按预期进行。
@new_balance设置为大于或等于 2147483648 的数字时,例如 2147483648.1,该过程将失败,并出现将表达式转换为 int 错误的算术溢出。我很欣赏 int 列的最大值是 2147483647。

使用以下插入也是这种情况:

INSERT INTO MyTable (id, seq_num, new_balance)
SELECT @id, @seq_num, @new_balance;

鉴于参数和表列都定义为decimal(18,6),我很难理解为什么将转换为 int 作为插入的一部分(尤其是在第二个语句中,我不希望有任何隐式转换)。

我还尝试将@new_balancetodecimal(18,6)明确转换为INSERT语句的一部分:

INSERT INTO MyTable (id, seq_num, new_balance)
SELECT @id, @seq_num, CAST(@new_balance AS decimal(18,6));

这也没有奏效。

奇怪的是,如果我在查询中指定具有相同定义的表变量并执行类似的插入,它工作正常:

DECLARE @MyTable TABLE (id int, seq_num int, new_balance decimal(18,6));
INSERT INTO @MyTable (id, seq_num, new_balance)
SELECT @id, @seq_num, @new_balance;

我在程序中尝试过这种方法,即先将记录插入@MyTable,然后尝试插入MyTable如下:

DECLARE @MyTable TABLE (id int, seq_num int, new_balance decimal(18,6));
INSERT INTO @MyTable (id, seq_num, new_balance) SELECT @id, @seq_num, @new_balance;
INSERT INTO MyTable (id, seq_num, new_balance) SELECT id, seq_num, new_balance FROM @MyTable;

这也不起作用。

为了完整起见,我还尝试创建值为零的记录,然后更新现有记录 - 再次失败,因此 INSERT 和 UPDATE 都会出现此问题:

INSERT INTO MyTable (id, seq_num, new_balance) SELECT @id, @seq_num, 0.00;

这很好 - 但下一步给出与上面报告的相同的错误:

UPDATE MyTable SET new_balance = @new_balance WHERE id = @id AND seq_num = @seq_num;

确认一下,表上没有INSTEAD OF INSERT触发器或AFTER UPDATE触发器 - 没有任何类型的触发器。

数据库上未启用更改跟踪,并且此特定字段没有约束 - 实际表中的其他十进制 (18,6) 字段有默认约束。

也没有视图添加到数据库中。

我在这个论坛上的第一个问题 - 希望有人自己经历过这个问题并且可能知道如何解决它,尽管我找不到类似性质的问题。我难住了。

4

1 回答 1

1

能够在过程之外直接插入表中,我查看了一些下游事件并确定了问题:

插入记录后,系统会更新父表中关联记录的状态。此父表上有一个 AFTER UPDATE 标识此状态更改为需要审计并运行辅助过程来创建审计历史记录。作为此捕获的一部分,系统使用标量值函数将 MyTable 中的旧值和新值转换为用户友好的格式。作为其中的一部分,该值被分成两部分以创建必要的格式,并且整数部分被转换为 int。通过将此强制转换为 bigint,问题自行解决。

因此,原始问题的前提是错误的——问题有好几层。

感谢那些做出贡献的人。

于 2020-07-20T10:55:56.667 回答