2

C# を使用して asp.net 3.5 で SQL Bulkcopy を使用すると、文字列から日付への変換に問題があります。

大きな CSV ファイルを読みました ( CSV リーダーを使用)。読み取った文字列の 1 つを SQL Server 2008 の Date 列にロードする必要があります。

たとえば、テキスト ファイルに文字列 '2010-12-31' が含まれている場合、SQL Bulkcopy は問題なくそれを Date 列に読み込みます。

ただし、文字列が '20101231' の場合、エラーが発生します:
The given value of type String from the data source cannot be convert to type date of the specified target column

ファイルには 8000 万件のレコードが含まれているため、データテーブルを作成できません....

SqlBulkcopy カラムマッピングなどはすべて問題ありません。また、DateTime に変更しても役に立ちません。

私は試した

SET DATEFORMAT ymd;

しかし、それは役に立ちません。

この形式を受け入れるように SQL Server に指示する方法はありますか? それ以外の場合は、CSV リーダーでカスタム修正を作成しますが、SQL で修正することをお勧めします。

更新 2つの回答に続いて、私はこのようなSQLバルクコピーを使用しています(別の質問でStackoverflowで提案されているように):

CSV リーダー (上記の codeproject のリンクを参照) は文字列値を返します (厳密な型指定ではありません)。CSVreader は System.Data.IDataReader を実装しているので、次のようなことができます。

using (CsvReader reader = new CsvReader(path)) 
using (SqlBulkCopy bcp = new SqlBulkCopy(CONNECTION_STRING))
{ bcp.DestinationTableName = "SomeTable"; 
  // columnmappings
  bcp.WriteToServer(reader); } 

iDataReader からのすべてのフィールドは文字列であるため、CSVreader でかなり変更しない限り、C# のアプローチを使用できません。

したがって、私の質問はC#で修正する方法とは関係ありません。それはできますが、それを防ぎたいです。

in sql のようなものを実行すると奇妙です

 update set [somedatefield] = '20101231' 

バルクコピーでは機能しません。

理由はありますか?

アドバイスありがとう、プルン

4

3 に答える 3

2

C#自体で処理できる場合、このコードは、文字列内の日付を、直接渡すことができるDateTimeオブジェクトとして取得するのに役立ちます。

//datestring is the string read from CSV
DateTime thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null);

文字列としてフォーマットする場合は、次のようにします。

string thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null).ToString("yyyy-MM-dd");

幸運を。

アップデート

あなたのシナリオでは、日付が自動的にフォーマットされない理由はわかりませんが、C#からデータをWriteToServer() メソッドに渡すプロセスに参加して干渉する必要があります。(パフォーマンスを念頭に置いて)できると思う最善の方法は、DataRowアイテムのキャッシュを用意し、それらをWriteToServer()メソッドに渡すことです。サンプルコードをすぐに書きます...

//A sample code.. polish it before implementation
//A counter to track num of records read
long records_read = 0;
While(reader.Read())
{
    //We will take rows in a Buffer of 50 records
    int i = records_read;//initialize it with the num of records last read
    DataRow[] buffered_rows = new DataRow[50];
    for(;i<50 ;i++)
    {
        //Code to initialize each rows with the data in the reader
        //.....
        //Fill the column data with Date properly formatted
        records_read++;
        reader.Read();
    }
    bcp.WriteToServer(buffered_rows);
}

その完全なコードではありませんが、私はあなたがそれを解決できると思います...

于 2011-01-20T18:08:22.777 に答える
2

古い問題ですが、別のアプローチを追加したいと考えていました。

IDataReader からストリーミングするときに、SQLBulkLoader が列の DataType/culture 仕様を許可しないという同じ問題がありました。

ローカルでデータ行を構築する速度のオーバーヘッドを減らし、代わりにターゲットで解析を行うために、私が使用した簡単な方法は、一時的にスレッド カルチャを使用中の形式を定義するカルチャに設定することでした。この場合は米国形式の日付です。 .

私の問題について-入力のen-US日付(Powershell内):

[System.Threading.Thread]::CurrentThread.CurrentCulture = 'en-US'
<call SQLBulkCopy>

あなたの問題については、同じことを行うことができますが、日付形式はカルチャ固有ではないため、デフォルトのカルチャ オブジェクトを作成します (未テスト):

CultureInfo newCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "yyyyMMDD;
Thread.CurrentThread.CurrentCulture = newCulture;

特にスクリプト言語では、ローカルで解析を実行するよりも、SQLBulkCopy インターフェイスを通過した後にデータベース サーバーで型変換を実行できるようにする方がはるかに高速であることがわかりました。

于 2014-05-12T13:30:02.303 に答える
0

をどのように使用しているかは完全には明らかSqlBulkCopyではありませんが、理想的には、データを文字列形式で SQL Server にアップロードするべきではありません。そのようにアップロードします。そうすれば、文字列形式について心配する必要はありません。DateTimeDateTimeOffset

于 2011-01-20T17:52:05.893 に答える