使用SQL批量复制访问SQL到十进制的两倍

时间:2013-06-24 16:34:30

标签: sql vb.net ms-access sqlbulkcopy

我有一个Access数据库,我在vb.net中使用sqlbulkcopy转换为SQL数据库。我们在Access as 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

1 个答案:

答案 0 :(得分:1)

你的问题是像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;

...然后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
)