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

本文关键字:插入 SQL 语句 Server 更好 大型 值参 参数 字符串 | 更新日期: 2023-09-27 18:35:31

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

(我省略了大量代码,因为我只是在询问相对的好处,而不是具体的语法)

例如:

选项 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"

感谢您的任何帮助。

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

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

选项 4:如果您确实有很多行要插入,也许您需要查看 SqlBulkCopy 类。它消耗DataTableDataRowIDataReader。您可以使用一些自定义代码从对象列表中进行IDataReader,这里提出了一个类似的问题:

从键入的列表中获取 IDataReader


我会说这取决于。

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

我已经看到了选项 1 - 一些通用的 DAL 代码会编写出要运行的 SQL"批量"命令。它奏效了,但没有对注射攻击提供任何防御。参数化 SQL 可以。


综上所述,我倾向于为要从代码插入的每一行调用插入 sproc 一次 - 调用将被完全参数化并且性能很好。如果性能成为一个问题,我会赞成选项4。

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

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

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

值限制为 1000

值似乎存在一些性能问题

插入具有多个值的性能问题

我使用 TVP 插入数千行,它对我来说非常有用。 我使用列表集合作为 TVP 源,因为数据表的开销更大。 如果可以,插入按PK排序的行。

话虽如此,我将尝试Marc Gravell的答案。

JNK对TVP普遍不信任。