更新生成器值问题

时间:2011-12-13 09:40:48

标签: 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;

所以我创建了一个生成器,现在我需要在表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);

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

  • 创建生成器
  • 获取最大ID
  • 更新生成器值

并为每个表重复处理?

我也期待

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

是一种解决方法,可以从一个命令中的每个表中获取最大ID,但它不会。

3 个答案:

答案 0 :(得分:6)

声明

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你必须坚持不懈(一个声明获得当前最大值,然后另一个声明更新发生器)。

答案 1 :(得分:4)

您可以创建一个存储过程并从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已经supported by Firebird 1.5了。 在Firebird 2.0及更高版本中,您还可以将代码包装在execute block中,并避免创建存储过程。

答案 2 :(得分:4)

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

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以及更新版本。