Инициализировать генератор существующим значением

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

set term #   
execute block    
as  
declare i int = 0;    
begin  
  i = (select max(some_col) from Table);  
  gen_id(some_gen,-(gen_id(some_gen,0))); ---set some_gen to 0  
  gen_id(some_gen,:i);  --- set to i
end #  
set term ;#

person Fero    schedule 21.07.2016    source источник
comment
Пожалуйста, опишите, что вы пытаетесь сделать, что вы ожидаете и что на самом деле происходит. Обратите внимание, что вмешательство в последовательности (генераторы) обычно является признаком плохого дизайна или злоупотребления ими в целях, для которых они не должны использоваться.   -  person Mark Rotteveel    schedule 21.07.2016
comment
Я просто пытаюсь установить значение генератора на максимальное значение некоторого столбца в таблице, как и этот вопрос stackoverflow.com/questions/16056556/ просто я получаю код ошибки SQL = -104 Неизвестный токен - строка 1, столбец 37 (   -  person Fero    schedule 21.07.2016


Ответы (2)


Проблема с вашим кодом в том, что вы не можете выполнить gen_id изолированно; синтаксический анализатор ожидает gen_id (или, точнее: вызов функции) только в том месте, где вы можете иметь значение (например, в операторе или присваивании). Вам нужно присвоить возвращаемое значение параметру, например:

set term #;
execute block    
as  
declare i int = 0;    
declare temp int = 0;
begin  
  i = (select max(id) from items);  
  temp = gen_id(GEN_ITEMS_ID, -(gen_id(GEN_ITEMS_ID, 0))); ---set some_gen to 0  
  temp = gen_id(GEN_ITEMS_ID, :i);  --- set to i
end #  
set term ;#

Имейте в виду, что изменение таких последовательностей является «рискованным»: если есть какие-либо чередующиеся действия, использующие одну и ту же последовательность, вы можете не получить ожидаемый результат (последовательность может оказаться со значением, отличным от i, и вы можете получить дубликат ключевые ошибки, когда другая транзакция использует последовательность после вычитания текущего значения (установленного в 0) и перед добавлением i.

Как также отмечено в комментариях, вы также можете заменить свой код на:

set term #;
execute block    
as  
declare i int = 0;    
declare temp int = 0;
begin  
  i = (select max(id) from items);  
  temp = gen_id(GEN_ITEMS_ID, :i - gen_id(GEN_ITEMS_ID, 0));
end #  
set term ;#

Выполнение этого в одном операторе уменьшит риск чередования операций (хотя и не устранит его полностью).

person Mark Rotteveel    schedule 21.07.2016
comment
Я также отредактировал ответ на другой вопрос, но обратите внимание, что фактическое решение уже упоминалось в комментарии Даниэля Путры к этому ответу. - person Mark Rotteveel; 21.07.2016
comment
Нужно ли сначала установить генератор в 0, а затем в какое-то значение? - person Val Marinov; 21.07.2016
comment
@ValMarinov Не совсем, вы также можете сделать gen_id(GEN_ITEMS_ID, :i - (gen_id(GEN_ITEMS_ID, 0))), это снижает риск чередования действий. - person Mark Rotteveel; 21.07.2016
comment
@MarkRotteveel Сейчас лучше. +1 за это. Хотя я бы предпочел сделать это без использования функции gen_id - person Val Marinov; 21.07.2016
comment
@ValMarinov Я знаю, но gen_id - единственное, что достаточно гибко, чтобы сделать это без необходимости прибегать к динамическому sql и execute statement - person Mark Rotteveel; 21.07.2016
comment
@MarkRotteveel просто ради интереса, есть ли альтернативное решение для достижения этого без использования оператора Execute? - person Fero; 21.07.2016
comment
@ Fero68 Нет, но опять же: вам все равно не следует этого делать. Не бойтесь пробелов в ваших идентификаторах. - person Mark Rotteveel; 21.07.2016

Если вы хотите использовать «блок выполнения», вы можете использовать что-то вроде:

execute block    
as  
declare i int = 0;    
begin  
  i = (select max(some_col) from some_table);
  execute statement ('set generator MY_GENERATOR to ' || :i);
end
person Val Marinov    schedule 21.07.2016