SQL Bulkcopy YYYYMMDD问题

时间:2011-01-20 17:49:40

标签: c# date sqlbulkcopy

我在使用C#

的asp.net 3.5中使用SQL Bulkcopy进行了String to Date转换问题

我读了一个大的CSV文件(CSV reader)。其中一个读取的字符串应该加载到SQL Server 2008 Date列中。

如果文本文件包含例如字符串'2010-12-31',则SQL Bulkcopy会将其毫无问题地加载到Date列中。

但是,如果字符串是'20101231',我会收到错误:
数据源中String类型的给定值无法转换为指定目标列的类型日期

该文件包含8000万条记录,因此我无法创建数据表....

SqlBulkcopy Columnmappings等都可以。也改为DateTime没有帮助。

我试过

SET DATEFORMAT ymd;

但这没有用。

有关如何告诉SQL Server接受此格式的任何想法?否则我将在CSV阅读器中创建一个自定义修复程序,但我更喜欢SQL中的一些东西。

更新的 关注这两个答案,我正在使用像这样的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的所有字段都是字符串,所以我不能使用c#方法,除非我在CSVreader中改变了很多

因此我的问题与如何在C#中修复无关,我可以这样做,但我想阻止它。

很奇怪,因为如果你在sql中做了类似

的事情
 update set [somedatefield] = '20101231' 

它也有效,只是没有使用批量复制。

知道为什么吗?

感谢您的任何建议, Pleun

3 个答案:

答案 0 :(得分: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);
}

它不是完整的代码,但我认为你可以解决它...

答案 1 :(得分:1)

旧版本,但想添加替代方法。

我遇到了同样的问题,SQLBulkLoader在从IDataReader流式传输时不允许列的数据类型/文化规范。

为了降低在本地构建数据行的速度开销,而不是在目标上进行解析,我使用的一个简单方法是将线程文化临时设置为定义正在使用的格式的文化 - 在本例中为美国格式日期。

对于我的问题 - 输入中的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接口后执行类型转换比在本地执行解析要快得多,特别是在脚本语言中。

答案 2 :(得分:0)

目前还不完全清楚你是如何使用SqlBulkCopy的,但理想情况下你根本不应该以字符串格式将数据上传到SQL Server:将其解析为DateTime或{{1在您的CSV阅读器中(或在CSV阅读器的输出上),并以这种方式上传。那你就不用担心字符串格式了。