使用 ExecuteNonQuery 在 oracle 中一次执行多个插入

Performing multiple inserts at once in oracle with ExecuteNonQuery

我正在尝试像这样一次执行多个插入

var mydict =  new Dictionary<int, int> { { 1, 2 }, { 3, 4 } };

var query = string.Join("; ", mydict.Select(x => $"insert into myTable (colA, colB) values ({x.Key},{x.Value})"));

using(var connection = new new OracleConnection(dbConnectionString))
{
    var command = connection.CreateCommand();
    command.CommandText = query;
    command.ExecuteNonQuery();
}     

但我 Oracle.ManagedDataAccess.Client.OracleException: 'ORA-00911: invalid character' 即使我可以手动执行来自 sql 开发人员的生成的查询也没有问题。

我以前用 sqlserver 和 sqlite 做过这个,我没有遇到任何问题。

为什么会这样?有没有更干净的方法?


这里是生成的sql:

insert into myTable (colA, colB) values (72520,2452); insert into myTable (colA, colB) values (73293,2453)

Oracle 的情况下,您应该生成 匿名块 ,例如:

 begin -- wrap in begin .. end
   insert into myTable (colA, colB) values (72520, 2452); 
   insert into myTable (colA, colB) values (73293, 2453); -- do not forget last ;
 end;

你的情况

var query = 
  "begin " + 
     string.Join("; ", mydict
       .Select(x => $"insert into myTable (colA, colB) values ({x.Key},{x.Value})")) + 
  "; end;";

免责声明:不要这样做(但要执行 bulk insert,请参阅 MT0 答案)如果

  1. 你必须插入字符串(SQL注入)
  2. 您有很多记录要插入(批量操作工作 更快
  3. 您经常调用(硬解析,参见https://blogs.oracle.com/sql/improve-sql-query-performance-by-using-bind-variables

why this happens?

Oracle 不允许在一个命令中执行多个语句。

SQL 开发人员会将您的字符串拆分为多个语句并依次执行每个语句 运行 它们作为多个命令,

is there a cleaner way?

使用 batch/bulk 插入:

  • Bulk Insert to Oracle using .NET
  • OracleBulkCopy does not insert entries to table

这样您就可以使用绑定值,而不是将您的插入语句构建为一个巨大的字符串。

这不是你应该做的。首选方式是这样的:

var command = connection.CreateCommand();
command.CommandText = "insert into myTable (colA, colB) values (:ColA, :ColB)";
command.Parameters.Add("ColA", OracleDbType.Int64, ParameterDirection.Input);
command.Parameters.Add("ColB", OracleDbType.Int64, ParameterDirection.Input);

foreach ( var entry in mydict ) {
   command.Parameters["ColA"].Value = entry.Key;
   command.Parameters["ColA"].Value = entry.Value;
   command.ExecuteNonQuery();
}