代码之家  ›  专栏  ›  技术社区  ›  TheLegendaryCopyCoder

SQLServer十进制插入到bigint列会丢失精度,但不会引发错误

  •  1
  • TheLegendaryCopyCoder  · 技术社区  · 6 年前

    下面的代码演示如何使用标准的insert语句将精度为的十进制值插入到bigint列中。 SqlServer会截断精度,但不会抛出错误来通知DBA。

    CREATE TABLE [dbo].[TableX]
    (
        [ColumnA] [bigint] NULL
    );
    
    SET NUMERIC_ROUNDABORT ON;
    SET XACT_ABORT ON;
    
    insert into [dbo].[TableX] (ColumnA)
    select 999999999.99;
    
    select * from [dbo].[TableX] 
    -- output ==> 999999999 (precision missing) -- no error thrown?
    

    问题:

    一、 你能解释一下为什么精度会丢失而不会抛出错误吗?

    二、在这种情况下,您能建议一种强制SQLServer抛出错误的方法吗?

    注: SQL bulk insert在尝试将十进制转换为bigint时会引发错误,因为精度将丢失,所以我非常确定,必须有一种方法可以通过示例代码中的标准insert语句来实现这一点。

    1 回复  |  直到 6 年前
        1
  •  1
  •   iamdave    6 年前

    第一个问题的答案是,它是经过设计的: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql

    这就意味着,对于第二个问题,您需要添加一些逻辑来检查十进制值,并以您需要的方式处理它们。


    关于大容量插入的最后一点,我不是百分之百同意,所以我很乐意接受建议,我相信这是因为SQL Server不知道平面文件中的数据类型,所以所有内容都是字符串。然后,您可以声明应将其转换为 date int SQL将尝试进行转换。

    从字符串转换为 decimal 内景 数据类型要严格得多,这就是 bulk insert 抛出错误,如下所示:

    declare @t table([ColumnA] decimal(12,2) NULL);
    
    SET NUMERIC_ROUNDABORT ON;
    SET XACT_ABORT ON;
    
    insert into @t(ColumnA)
    select '9999.99';
    
    select * from @t
    -- output ==> 9999.99 -- no error thrown
    
    go
    
    declare @t table([ColumnA] [bigint] NULL);
    
    SET NUMERIC_ROUNDABORT ON;
    SET XACT_ABORT ON;
    
    insert into @t(ColumnA)
    select '9999.99';
    
    select * from @t
    -- output ==> error thrown