2

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 ;# 
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Daniel Putra
  • 33
  • 1
  • 5

5 Answers5

4

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).

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
3
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 ;#
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
rstrelba
  • 1,838
  • 15
  • 16
  • Thank you, this got me into the right direction. The fully working SQL looks like this:set term #; execute block as declare i int = 0; declare g int = 0; begin i = (select max(ID) from OrganizationType_OLU); g = (select gen_id(OrganizationType_OLU,-(gen_id(OrganizationType_OLU,0))) from RDB$DATABASE); g = (select gen_id(OrganizationType_OLU,(select max(ID) from OrganizationType_OLU)) from RDB$DATABASE); end # set term ;# – Daniel Putra Apr 18 '13 at 08:50
1

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);
ain
  • 22,394
  • 3
  • 54
  • 74
1
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;
Leo Bruno
  • 474
  • 3
  • 16
0

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.

Community
  • 1
  • 1
yonojoy
  • 5,486
  • 1
  • 31
  • 60