将表达式转换为数据类型货币的算术溢出错误

时间:2014-01-21 07:04:08

标签: sql sql-server runtime-error

我有以下查询,其中accc_no的数据类型是varchar,wthdrl_amt是money,sav_amt是money,trxn_id是bigint。

DECLARE @acc_no NVARCHAR(MAX) = N''
DECLARE @symbol NVARCHAR(MAX) = N''
DECLARE @loop int = 0
DECLARE @loop2 int = 0

SELECT @symbol += N'' + acc_no + ',' FROM sav_transaction GROUP BY acc_no HAVING (SUM(sav_amt)<SUM(wthdrl_amt))
IF LEN(@symbol) > 1
BEGIN
    WHILE @loop < LEN(@symbol)
    BEGIN
        SET @loop2 = CHARINDEX(',', @symbol ,@loop)
        SET @acc_no = SUBSTRING(@symbol, @loop, @loop2-@loop)

        UPDATE sav_transaction
        SET wthdrl_amt = wthdrl_amt-(SELECT ABS(SUM(sav_amt)  - SUM(wthdrl_amt))
        FROM sav_transaction WHERE acc_no = @acc_no)
        WHERE acc_no = @acc_no AND trxn_id = (SELECT MAX(trxn_id) FROM sav_transaction WHERE acc_no = @acc_no )
    END
    SET @loop = @loop2 +1
END

但是当我跑这个时,我得到错误:

Msg 8115, Level 16, State 2, Line 15
Arithmetic overflow error converting expression to data type money.
The statement has been terminated.

我使用了具有相同数据类型的字段。但是找不到错误。

2 个答案:

答案 0 :(得分:1)

要查看差异,我们可以查看文档:

money的文档:

Data type  Range                                                 Storage
money      -922,337,203,685,477.5808 to 922,337,203,685,477.5807 8 bytes
smallmoney -214,748.3648 to 214,748.3647                         4 bytes

money和s​​mallmoney数据类型精确到它们所代表的货币单位的万分之一。

decimal比较:

使用最大精度时,有效值为-10 ^ 38 + 1到10 ^ 38 - 1。

Precision    Storage
1 - 9        5 bytes
10 - 19      9 bytes
20 - 28      13 bytes
29 - 38      17 bytes

所以他们并不完全相同,只是相似。 DECIMAL(19,4)的范围略大于MONEY(它可以存储-10 ^ 15 + 0.0001到10 ^ 15 - 0.0001),但还需要一个存储字节。

换句话说,这有效:

CREATE TABLE Table1 (test DECIMAL(19,4) NOT NULL);
INSERT INTO Table1 (test) VALUES
(999999999999999.9999);
SELECT * FROM Table1 

999999999999999.9999

但这不是:

CREATE TABLE Table1 (test MONEY NOT NULL);
INSERT INTO Table1 (test) VALUES
(999999999999999.9999);
SELECT * FROM Table1 

Arithmetic overflow error converting numeric to data type money.

还有语义差异。如果你想存储货币价值,那么使用类型货币是有意义的。

Source

答案 1 :(得分:0)

更改此部分SELECT @symbol + = N''+ CAST(acc_no AS nvarchar(MAX))+因为acc_no不是nvarchar并且在添加操作期间优先,并尝试将N''和其他添加项转换为其类型< / p>

DECLARE @acc_no NVARCHAR(MAX) = N''
    DECLARE @symbol NVARCHAR(MAX) = N''
    DECLARE @loop int = 0
    DECLARE @loop2 int = 0

    SELECT @symbol += N'' + CAST(acc_no AS nvarchar(MAX)) + ',' FROM sav_transaction GROUP BY acc_no HAVING (SUM(sav_amt)<SUM(wthdrl_amt))
    IF LEN(@symbol) > 1
    BEGIN
    WHILE @loop < LEN(@symbol)
    BEGIN

                SET @loop2 = CHARINDEX(',', @symbol ,@loop)
                SET @acc_no = SUBSTRING(@symbol, @loop, @loop2-@loop)

    UPDATE sav_transaction SET 
    wthdrl_amt = wthdrl_amt-(SELECT SUM(sav_amt)  - SUM(wthdrl_amt)  FROM sav_transaction WHERE acc_no = @acc_no)
    WHERE acc_no = @acc_no AND trxn_id = (SELECT MAX(trxn_id) FROM sav_transaction WHERE acc_no = @acc_no )


    END
    SET @loop = @loop2 +1
    END