1

我有一个 Access 数据库,我正在使用 vb.net 中的 sqlbulkcopy 将其转换为 SQL 数据库。我们将货币值(最多 2 位小数)作为 Double 存储在 Access 中。当我将这些 Access 字段转换为类型为 [decimal] (19, 2) 的 SQL 字段时,存储在 Access 字段中的 81.6 之类的数字在转换时有时会在 SQL 字段中显示为 81.59。

如果我将 SQL 中的类型更改为 [decimal] (19,4),那么它将显示为 81.5999。Access 中的数字绝对是经过计算并存储到不超过两位小数的。有人可以向我解释为什么 SQL 会这样做吗?它不会一直发生……仅在某些记录中。

我已经查看了几乎所有我能找到的解释十进制类型的文章,并且我理解十进制是什么(我认为),但我不明白为什么数字有时会像这样转换。谢谢你的帮助。

编辑: 这是我在下面提到的代码,我用来循环遍历所有表和列,以将以“1Z”结尾的别名列重命名为其原始名称:

        Dim dtTbls As DataTable = cnnSQL.GetSchema("Tables")
    For Each drTbls As DataRow In dtTbls.Rows
        Dim sTableName As String = drTbls(2)
        Dim query As String = String.Concat("select * from [", sTableName, "] Where 0=1")
        Dim myCmd As SqlDataAdapter = New SqlDataAdapter(query, cnnSQL)
        Dim myData As New DataSet()
        myCmd.Fill(myData)
        For Each colu As DataColumn In myData.Tables(0).Columns
            If colu.ColumnName.EndsWith("1Z") = True Then
                Dim sNewColName As String = colu.ColumnName.Remove(colu.ColumnName.Length - 2, 2)
                dbSQL.ExecuteNonQuery(String.Concat("EXEC sp_rename '", sTableName, ".", colu.ColumnName, "', '", sNewColName, "', 'COLUMN'"))
            End If
        Next colu
    Next drTbls
4

1 回答 1

1

您的问题是,浮点类型Double通常无法准确存储数字,即使是对我们人类来说似乎是非常“简单”数字的值。这可以通过在 Access 中的 VBA 编辑器的即时窗口中键入以下内容来演示:

?(CDbl(81.60) * CDbl(100)) - CDbl(8160)

返回的结果是

-5.6843418860808E-13

您的经验表明,将 Access 直接传输Double到 SQL Serverdecimal将截断数字而不是四舍五入。因此,您需要做的是将 Access 中的值复制到单独的 SQL Server 类型的列中float,然后在 SQL Server 中使用 UPDATE 查询来填充该decimal(19,2)列,例如,

UPDATE TableName SET DecimalColumn = ROUND(FloatColumn, 2)

编辑

如果它使事情变得更容易,也应该可以在访问端进行舍入和转换。您可以为每个表创建一个 Select 查询,将货币值四舍五入并将其转换为Currency,如下所示...

SELECT ProductID, ProductName, CCur(Round([UnitPrice],2)) AS CurrUnitPrice
FROM Products;

...然后SqlBulkCopy是查询而不是表。

编辑

正如您可能已经发现的那样,尝试在保留原始列名的同时使用查询转换列...

SELECT ProductID, ProductName, CCur(Round([UnitPrice],2)) AS UnitPrice
FROM Products

...导致错误

查询定义的 SELECT 列表中别名“UnitPrice”引起的循环引用

该问题的解决方法是使用如下查询:

SELECT ProductID, ProductName, CurrUnitPrice AS UnitPrice
FROM
(
    SELECT ProductID, ProductName, CCur(Round([UnitPrice],2)) AS CurrUnitPrice
    FROM Products
)
于 2013-06-24T18:55:47.390 回答