本文介绍了SQL大容量复制截断十进制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用批量复制从C#DataTable将十进制值插入Sql Server 2005时,值将被截断而不是四舍五入。

When I insert decimal values into Sql Server 2005 from a C# DataTable using bulk copy the values get truncated instead of rounded.


  • DataTable中的数据类型为Decimal。

  • 数据库中的数据类型为Decimal(19,3)

  • DataTable中的值为1.0005

  • 在数据库中插入的值是1.000(我期望1.001)

  • The data type in the DataTable is Decimal.
  • The data type in the database is Decimal(19,3)
  • The value in the DataTable is 1.0005
  • The value insert in the database is 1.000 (I expected 1.001)

我使用的代码非常简单:

The code I'm using is pretty simple:

var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, null) { DestinationTableName = tableName};
bulkCopy.WriteToServer(dataTable);

有人知道如何解决此问题吗?

Does anyone know how to fix this?

推荐答案

根据参考源总是截断十进制值而不是四舍五入,不幸的是,它与BULK INSERT语句的行为不同。

According to the reference source, SqlBulkCopy always truncates decimal values instead of rounding, which unfortunately differs from the behavior of the BULK INSERT statement.

私有方法调用,如果源值的大小与目标列的大小不同:

The private ConvertValue method calls TdsParser.AdjustSqlDecimalScale if the scale of the source value differs from the scale of the destination column:

switch(type.NullableType) {
    case TdsEnums.SQLNUMERICN:
    case TdsEnums.SQLDECIMALN:
        // ...

        if (sqlValue.Scale != metadata.scale) {
            sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, metadata.scale);
        }

AdjustSqlDecimalScale 调用,为 fRound 传递 false

static internal SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale) {
    if (d.Scale != newScale) {
        return SqlDecimal.AdjustScale(d, newScale - d.Scale, false /* Don't round, truncate.  MDAC 69229 */);
    }

    return d;
}

显然没有办法覆盖此行为并传递 true AdjustScale ,因此,如果要使用 SqlBulkCopy ,则需要取整 DataTable 中的值,然后调用 WriteToServer

There's apparently no way to override this behavior and pass true to AdjustScale, so if you want to use SqlBulkCopy, you will need to round the values in the DataTable yourself before calling WriteToServer.

或者,您也可以将数据写入文件并直接执行BULK INSERT,而放弃 SqlBulkCopy

Alternatively, you could write the data to a file and execute BULK INSERT directly, forgoing SqlBulkCopy.

这篇关于SQL大容量复制截断十进制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 03:02