在foreach循环中一次又一次地调用存储过程以将数据插入Oracle表是一种好习惯吗?或者有另一种方法可以做到这一点吗?
我有以下程序:
procedure proc1 (id in varchar2,
level in varchar2,
title in varchar2,
p_id in varchar2,
url in varchar2)
这是调用它的代码:
foreach (var c in xDoc.Descendants("cat"))
{
// call store procedure provide all values
foreach (var a in xDoc.Descendants("abc"))
{
// call store procedure provide values
foreach (var d in xDoc.Descendants("def"))
{
// call stored procedure provide values
}
}
}
有更好的方法吗?
答案 0 :(得分:4)
我会亲自设计存储过程,为您提供所需的表,以便您只需调用一次。像这样多次调用该过程是非常低效的,因为数据库多次生成结果集并且您有网络开销。如果创建过程以返回所需的表,而不是它的一些部分,则可以调用该过程一次并使用光标遍历该表。
答案 1 :(得分:2)
假设您使用的是ODP.NET,您可以使用array binding在单个数据库往返期间多次调用您的过程。除了将数组(而不是一个值)分配给OracleParameter.Value
并相应地设置OracleCommand.ArrayBindCount
之外,您几乎可以像往常一样绑定参数。
让我举一个简单的例子,我相信你不会在适应你的需要方面遇到麻烦......
甲骨文:
CREATE TABLE TEST (
ID INT PRIMARY KEY
);
CREATE OR REPLACE PROCEDURE TEST_INSERT (ID IN NUMBER) AS
BEGIN
INSERT INTO TEST VALUES(ID);
END TEST_INSERT;
C#:
using (var conn = new OracleConnection("your connection string")) {
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "TEST_INSERT";
var param = cmd.Parameters.Add("ID", OracleDbType.Int32, System.Data.ParameterDirection.Input);
int[] arr = { 1, 2, 3, 4, 5, 6 };
param.Value = arr;
cmd.ArrayBindCount = arr.Length;
cmd.ExecuteNonQuery();
}
执行此代码后,TEST表将包含arr
中的所有六个值。
因此,不是在每次迭代中调用您的过程,只需记住数组中的值,然后在最后一次大调用中将其传递给您的过程。