Выполнение нескольких вставок одновременно в 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) если
- Вы должны вставить строки (SQL инъекция)
- У вас есть много записей для вставки (массовые операции работают быстрее)
- Вы часто выполняете вызов (жесткий анализ, см. 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 разделит вашу строку на несколько операторов и выполнит каждый из них, выполняя их как несколько команд,
есть ли более чистый путь?
Используйте пакетную / объемную вставку:
- Массовая вставка в Oracle с использованием.NET
- Ошибка ORA-00604 при пакетной вставке внутри TransactionScope
- OracleBulkCopy не вставляет записи в таблицу
Таким образом, вы можете использовать значения связывания и не создавать оператор вставки как одну огромную строку.