如何批量调用存储过程?我想做一些类似批量复制的事情。
存储过程所做的只是 8 次选择唯一约束和 8 次插入。没有返回值。
你不能这样做。
大容量复制是将数据转储到表中,您不能调用 sprocs 或其他任何东西,而只能将其转储到现有表中。
但是,您可以做的是使用批量复制将数据转储到具有正确结构的临时表中,然后调用您的 sproc 将该数据移动到真实表中,可能通过修改现有数据而不是插入它,或者诸如此类.
如果您使用的是 SQL Server 2008,那么表值参数是一个可行的选择。
首先,在 SQL Server 端创建一个包含所有预期列和数据类型的用户定义表类型:
create type dbo.MyTableType as table
(
foo int,
bar varchar(100)
);
然后使用上面的作为存储过程的表类型参数:
create procedure uspInsertMyBulkData
(
@myTable dbo.MyTableType readonly
)
as
/* now in here you can use the multi-row data from the passed-in table
parameter, @myTable, to do your selects and inserts*/
然后,在 C#/.NET 客户端,通过 ADO.NET 调用此存储过程并传入 a DataTable
、继承自DbDataReader
(例如DataTableReader
)的对象或类型为 的对象IEnumerable<SqlDataRecord>
:
// create my source DataTable
object [] row1 = {1, "a"};
object [] row2 = {2, "b"};
var myDataTable = new DataTable();
myDataTable.Columns.Add(new DataColumn("foo"));
myDataTable.Columns.Add(new DataColumn("bar"));
myDataTable.LoadDataRow(row1, true);
myDataTable.LoadDataRow(row2, true);
// bulk send data to database
var conn = new SqlConnection(connectionString);
var cmd = new SqlCommand("uspInsertMyBulkData", conn)
{
CommandType = CommandType.StoredProcedure
};
SqlParameter param = cmd.Parameters.AddWithValue("@myTable", myDataTable);
param.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();
If you want to bulk load data into a table (inserts), the SqlBulkCopy class is the way to go.
Alternatively, you can use the SqlDataAdapter. Set the InsertCommand to the stored procedure that will perform an insert, and map the datatable fields to the sproc parameters. If you have updated records in the datatable, you can also specify an UpdateCommand which will be fired for each updated row. Then call the Update method on the SqlDataAdapter passing it the datatable. You can set the UpdateBatchSize property to define how many records to send to the db in each roundtrip.
SqlServer 存储过程可以接受 xml,因此您可以将批量数据准备为 xml 文件并将其传递给专用存储过程,然后该存储过程将为每一行调用您的原始存储过程。您需要OPENXML函数。
我犹豫是否推荐 SqlServer 的 xml 功能,但这可能是它们合适的情况。
我并不是说我推荐它,但您可以在要批量复制的表上放置一个插入触发器,该表插入到这 8 个单独的表中,而不是原始表中。您可能需要一个足够大的 tempdb 来存储所有数据......
CREATE TRIGGER TRG_REPLACETRIGGER
ON BULK_TABLE
INSTEAD OF INSERT
AS BEGIN
INSERT TABLE1 (ID, VALUE) SELECT ID, VALUE1 FROM INSERTED
INSERT TABLE2 (ID, VALUE) SELECT ID, VALUE2 FROM INSERTED
-- ... TABLE3-7
INSERT TABLE8 (ID, VALUE) SELECT ID, VALUE8 FROM INSERTED
END