.csv
个文件有57列,其中一些值为空。例如,,Jane,Doe,,35
。假设自动ID密钥的第一个值(逗号之前)是每次导入数据库时递增的。问题是未导入空值,从而导致错误。我在这里理解的是SQL数据库无法读取空值,因此它会移动值,如下所示:Jane,Doe,35
,从而使Jane
成为ID
的值。另一个问题是.csv
文件'列与表不匹配。例如,表格中包含ID
列,而.csv
文件则以Name
列开头。有没有办法从特定列开始将其导入数据库?
注意:这只在一个表中。
问题:如果我创建一个与.csv
文件列匹配的单独表,然后将其与具有列ID
的表(在示例中)连接,是否更为可取?
我的代码到目前为止:
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[54] { new DataColumn("Delay_Code"), and so on... });
string csvData = File.ReadAllText(e.FullPath);
foreach (string row in csvData.Split('\n'))
{
if (!string.IsNullOrEmpty(row))
{
dt.Rows.Add();
int i = 0;
foreach (string cell in row.Split(','))
{
dt.Rows[dt.Rows.Count - 1][i] = cell;
i++;
}
}
}
string consString = @"Data Source="blahblah";
using (SqlConnection con = new SqlConnection(consString))
{
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con))
{
//Set the database table name
sqlBulkCopy.DestinationTableName = "owner.Table";
con.Open();
sqlBulkCopy.WriteToServer(dt);
con.Close();
}
}
对于上面的代码,我创建了另一个与.csv
文件的列匹配的表。最初,该表在.csv
文件中的列之前有三个前面的列。
最好的方法是什么?
答案 0 :(得分:1)
从某些角度来看,你的问题可能看起来过于宽泛,但我理解它并且我分享了一些对我有用的广泛(通用)方法,你可以将它作为灵感来使用:
编写一个高质量的CSV阅读器,它也可以像
一样处理CSV行Value1, Value2, "Value 3", "Value ""4""", "Value
5",, Value 7, "Value,8"
""
),这只停留在另一个单引号("
)< / LI>
,
,;
或制表符,十进制数字可以包含逗号.
或,
等等。请记住它通常是另一方谁生成CSV,你可能需要适应其格式[可选]逻辑步骤是具有可配置的导入定义,而不是硬连线定义,例如。
{ ExternalOrders = "Data From External Orders in CSV",
CsvFormat = { CsvHasHeaderRow = true,
CsvFieldSeparator = ",",
DecimalSeparator = ".",
DateFormat = "yyyy-MM-dd",
DateTimeFormat = "yyyy-MM-dd hh:mm:ss",
TimeFormat = "hh:mm:ss" },
ColumnMap = {
Column1 = { SourceColumnName = "OrderID",
SourceColumnType = "nvarchar(50)"
StagingColumn = 1 },
Column2 = { SourceColumnName = "OrderDate",
SourceColumnType = "date"
StagingColumn = 2 },
ColumnAmount = { SourceColumnPosition = 5,
SourceColumnType = "decimal(18,6)"
StagingColumn = 3 }
},
StagingImportSql = "INSERT INTO Orders (Number, OrdDate, Amount)
SELECT CAST(c1 AS navarchar(50),
CAST(c2 AS date),
CAST(c3 AS money)
FROM StagingTable
WHERE ImportID = {{ImportIDToken}};"
}
在SQL数据库中使用列
创建一个临时表ID int identity(1,1)
ImportID int
CsvRowNumber int
c1 sqlvariant
c2 sqlvariant
c3 sqlvariant
...
c64 sqlvariant
根据配置的CsvFormat
创建调用CSV导入(格式为ColumnMap
)的引擎以填充登台表。您的临时表中还有其他列,例如导入期间由引擎自动填充ImportID
或CsvRecordNumber
。为每个CSV发出SQL INSERT语句,以便将一条记录添加到临时表中。完成所有操作后,在您的SQL命令中将令牌{{ImportIDToken}}替换为您实际导入的编号后,启动StagingImportSql
。
您可以选择实施
如果您在导入后没有立即清除临时表,则清除临时表,例如
用户限制 - 谁可以查看和运行哪些导入
我没有分享特定代码,在我的情况下,它位于vb.net,并且在许多类中可能有6000行。我只是在分享想法。
关于解析的注意事项:
Integer.Parse()
,Decimal.Parse()
,Double.Parse()
等方法根据列数据类型解析简单值。在解析之前,您可能希望替换标准的自定义小数点分隔符或千位分隔符。DateTime.ParseExact()
System.Data.SqlDbType
是您的朋友