2011-12-13 30 views
5

我目前正在修改Firebird 1.5版數據庫。更新生成器值問題

數據庫結構將被修改從delphi應用程序使用interbase組件運行查詢,我面臨的問題是我需要運行很多查詢,其中一些包括創建生成器和更新生成器值,問題是,我需要在儘可能少的查詢儘可能地做到這一點,但它似乎(至少對我來說),這是不是真的有可能,我想要做的是以下幾點:

/* 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從每一個表中的一個命令,但事實並非如此。

+0

你在使用什麼組件? – rstrelba

+0

@rstrelba interbase – ComputerSaysNo

+0

我對delphi組件感興趣。 TIBDatabase? TIBQuery? TIBDataSet? – rstrelba

回答

6

聲明

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

混合DDL(SET GENERATOR)和DML(SELECT),AFAIK這不是普遍支持和Firebird不支持它肯定。

如果你可以升級到火鳥的最新版本,那麼你可以使用EXECUTE BLOCK和/或EXECUTE STATEMENT做這一切「在一個聲明」和服務器端,但與火鳥1.5你不得不接受的很長的路要走(一個語句來獲取當前最大值,然後另一個更新生成器)。

+0

+1謝謝你,我不能升級,因爲代碼基礎很大,測試所有功能的時間是有限的,因此升級是不可能的。我希望有一個更優雅的解決方案): – ComputerSaysNo

+0

我認爲我給了這個問題足夠的時間,你的答案更接近我的問題,不幸的是我必須用解決問題的「更長的路」去解決問題,這意味着多個查詢...,謝謝你的回答(: – ComputerSaysNo

4

您可以創建一個存儲過程,並從德爾福調用它:

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 statementsupported by Firebird 1.5了。 在Firebird 2.0及更高版本中,您也可以將代碼包裝在execute block中,並避免創建存儲過程。

+0

+1謝謝你TOndrej,你說得對,GEN_TABLENAME是約定,但我更喜歡更簡單的解決方案 – ComputerSaysNo

2

通過下面的技巧你可以到發電機值設置爲同一個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以及更新的版本中起作用。

+0

如果你知道生成器是0,這更簡單:'SELECT GEN_ID(GEN_TABLENAME,(SELECT MAX(ID)FROM TABLENAME))FROM RDB $ DATABASE;' – yonojoy