将大型插入作为表值参数或作为字符串插入语句传递给SQL Server是否更好?

时间:2012-05-25 15:27:18

标签: c# .net sql-server sql-server-2008 sql-server-2008-r2

我正在编写一个将数据写入SQL Server 2008r2的.NET应用程序。我有两个插入数据的选项,要么我可以创建一个大的字符串插入语句,并将其作为文本命令发送,或者我可以在.NET DataTable中收集数据,并将其作为表值参数传递。每种方法的好处和成本是什么?

(我省略了很多代码,因为我只是询问相关的好处,而不是具体的语法)

e.g:

选项1:

    string insert = @"insert into MyTable (id, val) values
        ( 1, 'a'),(2,'b'),(3,'c'),(4,'d');"

选项2:

    DataTable dt = new DataTable();
    dt.Columns.Add("id", typeof(int));
    dt.Columns.Add("val", typeof(string));
    ....
    create procedure uspMyProc 
                    @tt ttMyTableType readonly
                as
                begin
                    insert into TestTable1 (id, strValue)
                    select myId, myVal from @tt;
                end"

感谢您的帮助。

3 个答案:

答案 0 :(得分:7)

选项3:在第一个实例中,我将使用一个insert语句的参数填充插入存储过程,并在C#代码的循环中多次调用它:

选项4 :如果您确实要插入 批次 行,或许您需要查看SqlBulkCopy class。它会消耗DataTableDataRowIDataReader。你可以使用一些自定义代码从对象列表中创建IDataReader,这里有一个问题:

Get an IDataReader from a typed List


我认为这取决于。

如果您真的想以表格形式传递多行参数,无论出于何种原因,请使用表值参数 - 这就是它的用途。

我见过选项1 - 一些通用的DAL代码会编写SQL“批处理”命令来运行。它起作用,但没有对注射攻击提供任何防御。参数化SQL可以。


所有这一切,我倾向于从代码中插入每行一次调用插入sproc - 调用将完全参数化并且性能良好。如果性能成为问题,我会赞成选项4。

答案 1 :(得分:5)

有多大?如果它是巨大的,没有什么比SqlBulkCopy更好。我实际上发现TVP表现令人失望。对于查询计划的重用,我是参数化和大量重用语句的粉丝。 Dapper可以帮助您,允许您将对象列表传递给查询 - 然后它将按成员名称添加每个对象的命名参数,每秒数千次操作。例如:

conn.Execute(
    "insert foo (Id,Name) values (@Id,@Name)",
    listOfObjects);

这将迭代列表并依次使用每个对象的.Id.Name来执行查询。

答案 2 :(得分:4)

值限制为1000

值似乎存在一些性能问题

Insert Performance Issues With Multiple Values

我使用TVP插入数千行,这对我很有用。我使用List集合作为TVP源,因为DataTable有更多的开销。如果可以的话,插入按PK排序的行。

据说我会尝试Marc Gravell的答案。

JNK普遍不信任TVP。