Обновление значения генератора - PullRequest
5 голосов
/ 13 декабря 2011

В настоящее время я работаю над модификацией базы данных Firebird v. 1.5.

Структура базы данных будет изменяться при выполнении запросов из приложения delphi с использованием компонентов interbase, проблема, с которой я сталкиваюсь, заключается в том, что мне нужновыполнить много запросов, некоторые из которых включают создание генераторов и обновление значения генератора, проблема в том, что мне нужно добиться этого за как можно меньшее количество запросов, но мне кажется (по крайней мере мне), что это на самом деле невозможно,я пытаюсь сделать следующее:

 /* this command creates a generator to be used for table TABLENAME */
CREATE GENERATOR GEN_TABLENAME;

Итак, я создал генератор, теперь мне нужно установить его значение на текущий максимальный идентификатор из таблицы TABLENAME, например:

/* one would expect that the following command would work, well it doesn't */
SET GENERATOR GEN_TABLENAME TO (SELECT MAX(ID) FROM TABLENAME);

Теперь, есть ли обходной путь для этого, или я вынужден:

  • создать генератор
  • получить обновление max ID
  • значение генератора

и повторение процесса для каждой таблицы?

Я также ожидал, что

SELECT
  SELECT MAX(ID) AS ID_TABLENAME_1 FROM TABLENAME_1,
  ...
  SELECT MAX(ID) AS ID_TABLENAME_N FROM TABLENAME_N

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

Ответы [ 3 ]

6 голосов
/ 13 декабря 2011

Заявление

SET GENERATOR GEN_TABLENAME TO (SELECT MAX(ID) FROM TABLENAME);

смешивает DDL (SET GENERATOR) и DML (SELECT), AFAIK это обычно не поддерживается, и Firebird не поддерживает его наверняка.

Если вы можете обновить до последней версии Firebird, то вы можете использовать EXECUTE BLOCK и / или EXECUTE STATEMENT , чтобы делать все это «в одном выражении» и на стороне сервера, но с Firebird 1.5Вы должны согласиться на долгий путь (один оператор, чтобы получить текущий максимум, затем другой обновить генератор).

4 голосов
/ 03 мая 2016

С помощью следующего трюка вы можете установить в качестве значения генератора максимальное значение идентификатора таблицы с одним оператором SQL в Firebird:

SELECT GEN_ID( GEN_TABLENAME, 
  (SELECT MAX(ID) FROM TABLENAME) - GEN_ID(GEN_TABLENAME, 0)) FROM RDB$DATABASE;

Это работает, потому что GEN_ID( <GeneratorName>, <increment>) получает значение генератора и увеличивает его на <increment>. Это должно работать в Firebird 1.5, а также в более новых версиях.

4 голосов
/ 13 декабря 2011

Вы можете создать хранимую процедуру и вызвать ее из Delphi:

create procedure update_generators
as
  declare variable max_id integer;
  declare variable table_name char(31);
  declare variable generator_name char(31);
begin
  /* assuming generator naming convention GEN_XXX -> table name XXX */
  for select
    trim(g.rdb$generator_name),
    substring(trim(g.rdb$generator_name) from 5)
  from rdb$generators g
  where (coalesce(g.rdb$system_flag, 0) = 0)
  into
    :generator_name,
    :table_name
  do
  begin
    /* assuming that the field name is always ID */
    execute statement 'select max(id) from ' || :table_name into :max_id;
    execute statement 'set generator ' || :generator_name || ' to ' || :max_id;
  end
end^

Похоже, execute statement уже поддерживается Firebird 1.5 . В Firebird 2.0 и более поздних версиях вы также можете заключить код в execute block и избежать создания хранимой процедуры.

...