SQL ВСТАВЬТЕ и ВЫБЕРИТЕ в Oracle, используя одну команду с. NET - PullRequest
2 голосов
/ 12 февраля 2020

Я пытаюсь выполнить команду SQL, которая вставляет запись в таблицу и возвращает сгенерированный первичный ключ.
Я использую. NET Core 3.1 и Oracle .ManagedDataAccess.Core package .

Это код C# для выполнения команды SQL (она использует некоторые методы расширения, но понятно, как она работает):

        private int PutSomethingInTheDatabase(string entity)
        {
            string sqlComamnd = File.ReadAllText("SQL//Insert Card.sql");

            using (var connection = new Oracle.ManagedDataAccess.Client.OracleConnection(connectionString))
            using (var command = connection.OpenAndUse().CreateTextCommand(sqlComamnd))
            {
                //var reader = command.ExecuteReader();
                //reader.Close();
                //var result = command.ExecuteScalar();
                //return (int)(decimal)result;

                return -1;
            }
        }

В идеале я получу один значение и читать его с ExecuteScalar().
Это итерационный тест (вот почему я прочитал SQL из файла).

SQL, который я хочу использовать, должен ВСТАВИТЬ новую запись и вернуть сгенерированную последовательность в той же области действия / транзакции, поэтому я использую Begin / End, но я не уверен, что это правильно способ.
Моя проблема в том, что я не могу найти правильный синтаксис для выполнения последнего SELECT для возврата сгенерированного sequence_id, я также попытался с помощью RETURN ...

Это SQL:

declare new_id number;

BEGIN
    select seq_stage_card.NEXTVAL into new_id from dual;

    INSERT INTO spin_d.stage_card (
        sequence_id,
        field_1,
        field_2
    )
    VALUES (
        new_id,
        'aaa'
        TO_DATE('2003/05/03 21:02:44', 'yyyy/mm/dd hh24:mi:ss')
    );

    select new_id from dual where 1 = 1 ;  -- not valid

END;

-- return new_id ;                   -- not valid 
-- select new_id from dual ;         -- not valid

Как изменить SQL для возврата new_id? Есть еще один (лучший) способ добиться того же результата? Это безопасно (изолированная область), или выбор вернет неправильный идентификатор при одновременной вставке?

[Обновить]
Кто-то предложил использовать ВОЗВРАТ (см. Здесь: Oracle - вернуть вновь вставленное значение ключа )
Я уже пытался использовать RETURN и RETURNING , но я не сделал найдите любой реальный пример использования с драйвером. NET (или другими платформами), например. OracleSqlCommand и правильный вызов для выполнения.
Возможно, это работает, но я все еще не могу понять, как его использовать.

1 Ответ

2 голосов
/ 12 февраля 2020

В общий случай (когда вам нужно реализовать некоторые логики в анонимном блоке, а когда returning не вариант) попробуйте связать переменные : сначала поверните new_id в :new_id в запросе :

BEGIN
    SELECT seq_stage_card.NEXTVAL 
      INTO :new_id -- bind variable to return back to c#
      FROM dual;

    INSERT INTO spin_d.Stage_Card (
        sequence_id,
        field_1,
        field_2
    )
    VALUES (
        :new_id,
        'aaa',
         TO_DATE('2003/05/03 21:02:44', 'yyyy/mm/dd hh24:mi:ss')
    );
END;

Затем используйте его в C# код:

...
using (var command = connection.OpenAndUse().CreateTextCommand(sqlComamnd))
{
  //TODO: check the syntax and RDBMS type
  command.Parameters.Add(
    ":new_id", 
     OracleDbType.Int32).Direction = ParameterDirection.Output;

  // Execute query 
  command.ExecuteNonQuery();

  // Bind variable reading
  return Convert.ToInt32(command.Parameters[0].Value);
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...