使用SQL大容量复制访问SQL小数的双精度



我有一个Access数据库,我正在使用vb.net中的sqlbulkcopy将其转换为SQL数据库。我们在Access中以Double形式存储货币值(最多2位小数)。当我将这些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

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

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

返回的结果是

-5.6843418860808E-13

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

UPDATE TableName SET DecimalColumn = ROUND(FloatColumn, 2)

编辑

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

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

然后CCD_ 7查询而不是表。

编辑

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

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
)

最新更新