1

vb.net で sqlbulkcopy を使用して SQL データベースに変換している Access データベースがあります。Access に Double として格納されている通貨の値 (小数点以下第 2 位まで) があります。これらの Access フィールドを [decimal] (19, 2) 型の SQL フィールドに変換すると、Access フィールドに格納されている 81.6 のような数値が、変換時に SQL フィールドでは 81.59 として表示されることがあります。

SQL の型を [decimal] (19,4) に変更すると、81.5999 と表示されます。Access の数値は確実に計算され、小数点以下 2 桁まで格納されます。SQLがこれを行っている理由を誰かが説明できますか? 常に発生するわけではありません... 一部のレコードでのみ発生します。

10 進数の型を説明している記事はほぼすべてレビューしましたが、10 進数が何であるかは理解しています (私はそう思います) 。ご協力いただきありがとうございます。

編集: これは、すべてのテーブルと列をループして、「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

Doubleあなたの経験では、Accessを SQL Serverdecimalに直接転送すると、数値が丸められるのではなく切り捨てられることが示唆されています。したがって、値を Access から別の SQL Server の type 列にコピーし、SQL Serverfloatで UPDATE クエリを使用してdecimal(19,2)列にデータを入力する必要があります。

UPDATE TableName SET DecimalColumn = ROUND(FloatColumn, 2)

編集

物事が簡単になる場合は、アクセス側で丸めと変換を行うこともできるはずです。次のように、金額を丸めて に変換する各テーブルの選択クエリを作成できます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 に答える