2

我在 asp.net 3.5 和 C# 中使用 SQL Bulkcopy 有一个字符串到日期的转换问题

我读了一个大的 CSV 文件(使用CSV 阅读器)。读取的字符串之一应加载到 SQL Server 2008 日期列中。

例如,如果文本文件包含字符串“2010-12-31”,SQL Bulkcopy 会将它毫无问题地加载到日期列中。

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

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

SqlBulkcopy Columnmappings 等都可以。更改为 DateTime 也无济于事。

我试过

SET DATEFORMAT ymd;

但这无济于事。

任何想法如何告诉 SQL Server 接受这种格式?否则,我将在 CSV 阅读器中创建自定义修复,但我更喜欢 SQL 中的某些内容。

更新 跟进两个答案,我正在使用这样的 SQL bulkcopy(正如 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' 

它也有效,只是不适用于批量复制。

知道为什么吗?

感谢您的任何建议,普莱恩

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:将其解析到CSV 阅读器DateTimeDateTimeOffsetCSV 阅读器中(或 CSV 阅读器的输出),并且那样上传。那么你就不用担心字符串格式了。

于 2011-01-20T17:52:05.893 回答