这似乎是一个重复的问题。但是当我搜索和查看了相关问题&答案,我仍然找不到答案。
我正在编写一个加载程序,它将CSV文件中的数据记录导入数据库表。这是演示。
数据库表如下:
use Test;
create table BoolTest (Name varchar(20) not null, IsValid bit not null);
insert into BoolTest (Name, IsValid) values('xx', 1);
insert into BoolTest (Name, IsValid) values('yy', 0);
加载程序就像:
class Program
{
static void Main(string[] args)
{
var csvFileContent = "Name,IsValid\r\naa,true\r\nbb,false";
var csvLines = csvFileContent.Split(new String[] { "\r\n" }, StringSplitOptions.None);
var columnNames = csvLines[0].Split(',');
var table = new DataTable();
foreach (var columnName in columnNames)
{
table.Columns.Add(new DataColumn(columnName));
}
for (var n = 1; n < csvLines.Length; ++n)
{
var line = csvLines[n];
var values = line.Split(',');
table.Rows.Add(values);
}
var connectionString = "Data Source=localhost;Initial Catalog=Test;Integrated Security=True";
using (var bulkCopy = new SqlBulkCopy(connectionString)) {
bulkCopy.DestinationTableName = "BoolTest";
bulkCopy.ColumnMappings.Add("Name", "Name");
bulkCopy.ColumnMappings.Add("IsValid", "IsValid");
bulkCopy.WriteToServer(table);
}
Console.WriteLine("Done");
Console.Read();
}
}
上面的一切都很好。
但问题是CSV文件来自第三方,列'IsValid'的值是0或1,如下所示
Name,IsValid
aa,1
bb,0
当加载程序尝试加载此CSV文件时,bulkCopy.WriteToServer(table)将抛出异常
我使用的sql server是Sql server 2014.
任何帮助将不胜感激。感谢。
---更新---
谢谢大家的解决方案。我将尝试在加载程序中手动将0/1更改为false / true。但是仍然想知道这个问题是否有简单的修复(比如在SQL Server或SqlBulkCopy中更改设置)。
我也在Sql Server Management Studio中尝试了sql,如
insert into BoolTest (Name, IsValid) values('aa', 1); -- this works as we expected
insert into BoolTest (Name, IsValid) values('aa', '1'); -- this also works to my surprise
两者都运作良好。但是当IsValid值为0或1时,不确定为什么SQL服务器拒绝批量复制。当我们用'select'显示表数据时,IsValid的值实际上是0或1.
答案 0 :(得分:2)
这是因为布尔值被insert上的位值替换,为了让我们的生活更容易解决这个问题,你只需要创建一个将bit转换为bool的解析方法,这很简单。应该工作
答案 1 :(得分:1)
以下INSERT
声明适用于SQL
级别:
INSERT INTO BoolTest (Name, IsValid) VALUES ('xx', 1);
INSERT INTO BoolTest (Name, IsValid) VALUES ('yy', 0);
但是当您将值传递给存储过程或SQL语句时,您不能通过0或1,因为它将作为0或1(并接受为)。它将需要是一个真实的或错误的将被传递。
我认为这是你分割线值的地方:
var values = line.Split(',');
你需要做的就是测试0和1,然后分别用false或true替换它们。
答案 2 :(得分:1)
我认为错误是由于尝试将String(DataTable中的单元格值)推入BIT列而导致的,因为批量插入无法执行隐式转换(“0”和“1”值为0/1 BIT值)。
一种方法是手动定义列及其实际类型:
table.Columns.Add(new DataColumn("Name", typeof(String)));
table.Columns.Add(new DataColumn("IsValid", typeof(bool)));
并将细胞构造成这样的东西:
for (var n = 1; n < csvLines.Length; ++n)
{
var line = csvLines[n];
var values = line.Split(',');
var rowValues = new object[values.Length];
rowValues[0] = values[0];
// conversion to integer is required as Boolean will not accept the string
rowValues[1] = Convert.ToBoolean(Convert.ToInt32(rowValues[1]));
}