How to set initial generator value?

随声附和 提交于 2019-12-24 14:33:14

问题


I need to initialise a new Firebird generator / sequence to the max primary key value of an existing, 'old' table. I tried the following but it is not working, I get the error "Token unknown - line 6, column 8 select". I cannot do this manually as it must be executed on many different DBs. I am using Firebird 2.5.1.

According to http://www.firebirdsql.org/file/documentation/reference_manuals/reference_material/html/langrefupd25-execblock.html this should work - what am I doing wrong?

set term #;  
execute block  
as  
declare i int = 0;  
begin  
   i = select max(ID) from OrganizationType_OLU;  
    alter sequence OrganizationType_OLU restart with :i;  
end  
#  
set term ;# 

回答1:


set term #;
execute block    
as  
declare i int = 0;    
declare temp int = 0;
begin  
  i = (select max(id) from items);  
  temp = gen_id(GEN_ITEMS_ID,-(gen_id(GEN_ITEMS_ID,0))); ---set some_gen to 0  
  temp = gen_id(GEN_ITEMS_ID,:i);  --- set to i
end #  
set term ;#



回答2:


In general you can use ALTER SEQUENCE:

ALTER SEQUENCE sequence-name RESTART WITH <newval>

Or the legacy option SET GENERATOR

SET GENERATOR generator-name TO <new-value>

However you want to do this from an EXECUTE BLOCK and you can't as executing DDL from PSQL code isn't allowed in Firebird. So I guess the answer of rstrelba is probably the only option available.

Be aware though that sequences are outside of transaction control in Firebird (they are atomic), so make sure you only run it if you are the only active transaction, otherwise you might reset the sequence to an invalid value.

I strongly suggest to make sure the ID for OrganizationType_OLU is always generated by sequence, and never allow user specified values for these columns. This ensures that the sequence value is always valid (ie: not too low, causing primary key constraint violations).




回答3:


The error you got (Token unknown - line 6, column 8 select) is because if you want to use select as an expression you have to enclose it into parenthesis like

i = (select max(ID) from OrganizationType_OLU);



回答4:


If you do not want to use EXECUTE BLOCK or if you still use an older Firebird version (<2.0), try this:

Given, that GEN_ITEMS_ID is your generator name, you can set the initial generator value by the following DML statement:

SELECT GEN_ID(GEN_ITEMS_ID, 
  (select max(ID) from OrganizationType_OLU) 
  - GEN_ID(GEN_ITEMS_ID, 0)) FROM RDB$DATABASE;

Explanation here.




回答5:


EXECUTE BLOCK
AS
DECLARE VARIABLE fMaxID INTEGER;
BEGIN
    SELECT COALESCE(MAX(id),0)
    FROM yourtable
    INTO :fMaxID ;

    EXECUTE STATEMENT('CREATE SEQUENCE YourSequence');
    EXECUTE STATEMENT('ALTER SEQUENCE YourSequence RESTART WITH '||CAST(:fMaxID AS VARCHAR(16)));
END;


来源:https://stackoverflow.com/questions/16056556/how-to-set-initial-generator-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!