Выполнение нескольких вставок одновременно в Oracle с 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' даже я могу вручную выполнить сгенерированный запрос из sqldeveloper без проблем.

Я уже делал это в прошлом с sqlserver и sqlite, и у меня не было проблем.

почему это происходит? есть ли более чистый путь?


вот сгенерированный sql:

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

3 ответа

Решение

В случае 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)

Это не так, как вы должны это делать. Предпочтительный способ будет выглядеть так:

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();
}

почему это происходит?

Oracle не позволяет выполнять несколько операторов в одной команде.

Разработчик SQL разделит вашу строку на несколько операторов и выполнит каждый из них, выполняя их как несколько команд,

есть ли более чистый путь?

Используйте пакетную / объемную вставку:

Таким образом, вы можете использовать значения связывания и не создавать оператор вставки как одну огромную строку.

Другие вопросы по тегам