5

Gỡ lỗi một số mã SQL liên quan đến tài chính đã tìm thấy một vấn đề lạ với độ chính xác toán học số (24,8).SQL server 2005 mất chính xác số

Chạy truy vấn sau đây trên MSSQL của bạn, bạn sẽ nhận được một kết quả biểu hiện * C + B để được 0,123457

CHỌN A, B, C, A + B * C TỪ ( CHỌN CAST (0.12345678 AS NUMERIC (24,8)) AS A, CAST (0 AS NUMERIC (24,8)) AS B, CAST (500 AS NUMERIC (24,8)) AS C ) T

Vì vậy, chúng tôi đã mất 2 biểu tượng quan trọng. Cố gắng để có được điều này cố định theo những cách khác nhau tôi đã nhận rằng chuyển đổi của các kết quả nhân trung gian (đó là Zero!) Để số (24,8) sẽ làm việc tốt.

Và cuối cùng là giải pháp. Nhưng tôi vẫn còn một câu hỏi - tại sao MSSQL cư xử theo cách này và những chuyển đổi loại thực sự xảy ra trong mẫu của tôi?

Trả lời

7

Cũng như việc thêm kiểu float là không chính xác, phép nhân các loại thập phân có thể không chính xác (hoặc không chính xác) nếu bạn vượt quá độ chính xác. Xem Data Type Conversiondecimal and numeric.

Vì bạn nhân NUMERIC(24,8)NUMERIC(24,8) và SQL Server sẽ chỉ kiểm tra loại không nội dung, có thể sẽ cố gắng lưu 16 chữ số không thập phân tiềm năng (24 - 8) khi không thể lưu tất cả 48 chữ số độ chính xác (tối đa là 38). Kết hợp hai trong số họ, bạn nhận được 32 chữ số không thập phân, mà bạn chỉ có 6 chữ số thập phân (38 - 32).

Vì vậy, các truy vấn ban đầu

SELECT A, B, C, A + B * C 
FROM (SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A, 
    CAST(0 AS NUMERIC(24,8)) AS B, 
    CAST(500 AS NUMERIC(24,8)) AS C) T 

giảm tới

SELECT A, B, C, A + D 
FROM (SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A, 
    CAST(0 AS NUMERIC(24,8)) AS B, 
    CAST(500 AS NUMERIC(24,8)) AS C, 
    CAST(0 AS NUMERIC(38,6)) AS D) T 

Một lần nữa, giữa NUMERIC(24,8)NUMERIC(38,6), SQL Server sẽ cố gắng tiết kiệm tiềm năng 32 chữ số của phi thập phân, vì vậy A + D giảm đến

SELECT CAST(0.12345678 AS NUMERIC(38,6)) 

which gi ves bạn 0.123457 sau khi làm tròn.

+0

ý bạn là NUMERIC (32,6)) ?? Nếu số tiền phải là 38 – Edmondo1984

+0

@ Edmondo1984 Vui lòng đọc các liên kết và hiểu ý nghĩa của cả hai số. –

+0

Bạn nói rằng khi nhân hai số (24,8) máy chủ sẽ cố gắng tiết kiệm 16 bit và tạo ra một (32,6), làm thế nào nó trở thành một 38,6?Cảm ơn – Edmondo1984

0

Tiếp theo logic chỉ ra bởi eed3si9n và những gì bạn nói trong câu hỏi của bạn có vẻ như phương pháp tốt nhất khi làm toán hoạt động là để giải nén chúng vào một chức năng và bổ sung để xác định chính xác sau mỗi hoạt động,

Nó này trường hợp chức năng có thể trông giống như sau:

create function dbo.myMath(@a as numeric(24,8), @b as numeric(24,8), @c as numeric(24,8)) 
returns numeric(24,8) 
as 
begin 
    declare @d as numeric(24,8) 
    set @d = @b* @c 
    return @a + @d 
end 
+0

Cách tiếp cận đó có thể không giải quyết được vấn đề SQL Server cắt bỏ các phần thập phân. Để lưu các phần thập phân, có thể cần phải truyền thành @a và @b thành gấp đôi. –

+0

Cảm ơn, tôi sẽ ghi nhớ khi làm việc trên một số phép tính chính xác trong SQL, Cho đến nay tôi không cần phải sử dụng nó nhưng nó là tốt để bây giờ mà có thể có một số vấn đề cần xem xét – kristof

Các vấn đề liên quan