【问题标题】:SQLServer decimal insert into bigint column loses precision but no error thrownSQLServer 十进制插入到 bigint 列丢失精度,但没有抛出错误
【发布时间】:2018-02-22 15:57:38
【问题描述】:

下面的代码演示了使用标准插入语句将具有精度的十进制值插入到 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 批量插入在尝试将小数转换为 bigint 时会引发错误,而精度会丢失,因此我相当肯定必须有一种方法可以按照示例代码使用标准插入语句来实现这一点。

【问题讨论】:

    标签: decimal sql-server-2014 precision sql-insert bigint


    【解决方案1】:

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

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


    关于批量插入的最后一点——我不是 100% 同意这一点,所以很乐意接受建议——我相信这是因为 SQL Server 不知道你的平面文件中的数据类型是什么,所以一切都是字符串。然后,您可以声明它应该转换为 dateint,SQL 将尝试转换。

    从字符串到decimalint 数据类型的转换要严格得多,这就是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
    

    【讨论】:

    • 良好的反馈。因此,我没有添加验证,而是将所有值包含在单引号中,这会导致错误并导致精度损失。
    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多