Обновление значения генератора
В настоящее время я работаю над модификацией базы данных 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);
Теперь есть ли обходной путь для этого, или я вынужден:
- создать генератор
- получить максимальный идентификатор
- обновить значение генератора
и повторить процесс для каждой таблицы?
Я также ожидал, что
SELECT
SELECT MAX(ID) AS ID_TABLENAME_1 FROM TABLENAME_1,
...
SELECT MAX(ID) AS ID_TABLENAME_N FROM TABLENAME_N
было бы обходным путем, чтобы получить максимальные идентификаторы из каждой таблицы в одной команде, но это не так.
3 ответа
Утверждение
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 вам придется довольствоваться долгим способом (одно утверждение для получить текущий максимум, затем еще один обновить генератор).
С помощью следующего трюка вы можете установить в качестве значения генератора максимальное значение идентификатора таблицы с одним оператором 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, а также в более новых версиях.
Вы можете создать хранимую процедуру и вызвать ее из 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
и избегайте создания хранимой процедуры.