更新生成器值问题

Com*_*sNo 5 firebird auto-increment firebird1.5

我目前正在修改Firebird v.1.5数据库.

数据库结构将被修改为使用interbase组件从delphi应用程序运行查询,我面临的问题是我需要运行大量查询,其中一些包括创建生成器和更新生成器值,问题在于我需要在尽可能少的查询中实现这一点,但似乎(至少对我而言)这不可能实现,我正在尝试做的是以下内容:

 /* this command creates a generator to be used for table TABLENAME */
CREATE GENERATOR GEN_TABLENAME;
Run Code Online (Sandbox Code Playgroud)

所以我创建了一个生成器,现在我需要在表TABLENAME的当前最大id处设置它的值,如下所示:

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

现在,有没有解决方法,或者我被迫:

  • 创建发电机
  • 获得最大ID
  • 更新生成器值

并重复每个表的过程?

我也期待着

SELECT
  SELECT MAX(ID) AS ID_TABLENAME_1 FROM TABLENAME_1,
  ...
  SELECT MAX(ID) AS ID_TABLENAME_N FROM TABLENAME_N
Run Code Online (Sandbox Code Playgroud)

将是一个解决方法,从一个命令中的每个表中获取最大ID,但它没有.

ain*_*ain 7

声明

SET GENERATOR GEN_TABLENAME TO (SELECT MAX(ID) FROM TABLENAME);
Run Code Online (Sandbox Code Playgroud)

混合DDL(SET GENERATOR)和DML(SELECT),AFAIK通常不支持,Firebird肯定不支持它.

如果你可以升级到Firebird的最新版本,那么你可以使用EXECUTE BLOCK和/或EXECUTE STATEMENT来"在一个语句"和服务器端完成所有操作,但是使用Firebird 1.5你必须解决很长的问题(一个声明到得到当前的最大值,然后另一个更新发电机).


Ond*_*lle 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^
Run Code Online (Sandbox Code Playgroud)

看起来Firebird 1.5 已经支持execute statement了。在 Firebird 2.0 及更高版本中,您还可以将代码包装在 a 中并避免创建存储过程。execute block


yon*_*joy 5

使用以下技巧,您可以在 Firebird 中使用一条 SQL 语句将生成器值设置为表的最大 ID 值:

SELECT GEN_ID( GEN_TABLENAME, 
  (SELECT MAX(ID) FROM TABLENAME) - GEN_ID(GEN_TABLENAME, 0)) FROM RDB$DATABASE;
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为GEN_ID( <GeneratorName>, <increment>)获取生成器值并将其增加<increment>. 这应该适用于 Firebird 1.5 以及更新的版本。