Oracle SQL: Как к чтению-и-инкременту поле

Я осуществляю рефакторинг процедуру импорта данных корпоративного приложения и столкнулся с отрывком, я хотел бы найти лучшее решение. При импорте данных мы должны создать уникальный объект для каждого набора данных и существует счетчик в поле, которое будет использоваться для присвоения этого идентификатора последовательно. Вы читаете поле, чтобы получить следующий бесплатный идентификатор и увеличить его впоследствии для подготовки в следующий раз.

В данный момент это сделано на двух шагах в исходном приложении, записанном в 'C':

   SELECT idnext FROM mytable;
   UPDATE mytable SET idnext = idnext + 1;

Очевидно, здесь существует состояние состязания, если несколько процессов делают то же самое.

Править: Важный corequisite: Я не могу коснуться базы данных/определения поля, это исключает последовательность.

Мы переписываем в жемчуге, и я хотел бы сделать то же самое, но лучше. Атомарное решение было бы хорошо. К сожалению, мои навыки SQL ограничены, таким образом, я обращаюсь к коллективной мудрости :-)

8
задан markus_b 8 January 2010 в 17:36
поделиться

4 ответа

В данном конкретном случае последовательность является правильным решением, как уже упоминалось. Но если в какой-то ситуации в будущем необходимо как что-то обновить, так и вернуть значение в одном и том же операторе, то можно воспользоваться выражением RETURNING:

UPDATE atable SET foo = do_something_with(foo) RETURNING foo INTO ?

Если код вызова - PL/SQL, замените ? на локальную переменную PL/SQL; в противном случае вы можете привязать ее в качестве выходного параметра в своей программе.

Правка: Так как вы упомянули Perl, что-то подобное должно работать (непроверено):

my $sth = $dbh->prepare('UPDATE mytable SET idnext = idnext + 1 returning idnext into ?');
my $idnext;
$sth->bind_param_inout(1, \$idnext, 8);
$sth->execute; # now $idnext should contain the value

См. DBI.

9
ответ дан 5 December 2019 в 11:25
поделиться

Используйте инструкцию SELECT FOR UPDATE. Он гарантирует взаимоисключающие права на запись:

"SELECT ДЛЯ ОБНОВЛЕНИЯ;

2
ответ дан 5 December 2019 в 11:25
поделиться

Почему бы не использовать последовательность ?

Создайте последовательность один раз, используя все, что начнется со значением, которое вы хотите:

CREATE SEQUENCE mysequence
  START WITH 1
  MAXVALUE 999999999999999999999999999
  MINVALUE 1
  NOCYCLE
  NOCACHE
  NOORDER;

Затем в вашем приложении при выполнении вы можете использовать это оператор для получения следующего значения:

SELECT mysequence.NEXTVAL
  INTO idnext
  FROM DUAL;

Обновление: Использование последовательности будет предпочтительным методом, но поскольку вы не можете изменить базу данных, я согласен, что используя возврат должен работать на вашу ситуацию:

   UPDATE mytable 
      SET idnext = idnext + 1 
RETURNING idnext 
     INTO mylocalvariable;
4
ответ дан 5 December 2019 в 11:25
поделиться

A последовательность будет выполнять работу, посмотреть на E.G. Oracle Sequences

0
ответ дан 5 December 2019 в 11:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: