2011-12-13 19 views
5

Attualmente sto lavorando alla modifica di un database Firebird 1.5.Aggiornamento problema valore generatore

La struttura del database verrà modificata eseguendo query da un'applicazione delphi utilizzando componenti interbase, il problema che sto affrontando è che ho bisogno di eseguire molte query, alcune delle quali includono la creazione di generatori e l'aggiornamento del valore del generatore, il problema è che ho bisogno di raggiungere questo obiettivo nel minor numero di domande possibili, ma sembra (almeno per me) che questo non è davvero possibile, quello che sto cercando di fare è la seguente:

/* this command creates a generator to be used for table TABLENAME */ 
CREATE GENERATOR GEN_TABLENAME; 

Così Ho creato un generatore, ora ho bisogno di impostare il valore al max id corrente dalla tabella TABLENAME, in questo modo:

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

Ora, c'è qualche soluzione per questo, o sto costretto a:

  • creare il generatore
  • ottenere l'ID massimo
  • aggiornamento del valore del generatore

e ripetere processo per ogni tavolo?

Ho anche previsto che

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

sarebbe una soluzione per ottenere il massimo id da ogni tavolo in un unico comando, ma non è così.

+0

quali componenti stai usando? – rstrelba

+0

@rstrelba interbase – ComputerSaysNo

+0

Ho nomi interessati di componenti delphi. TIBDatabase? TIBQuery? TIBDataSet? – rstrelba

risposta

6

Normativa

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

mescola DDL (SET GENERATOR) e DML (SELECT), AFAIK questo non è generalmente supportato e Firebird non supporta di sicuro.

Se è possibile eseguire l'aggiornamento all'ultima versione di Firebird allora si potrebbe utilizzare EXECUTE BLOCK e/o EXECUTE STATEMENT per fare tutto "in una dichiarazione" e lato server, ma con Firebird 1.5 si deve accontentare del lungo cammino (uno dichiarazione per ottenere il massimo corrente, poi un altro aggiorna il generatore).

+0

+1 grazie, non posso aggiornare, perché il codice è abbastanza grande e il tempo di testare tutte le funzionalità è limitato, quindi l'aggiornamento è fuori questione. Speravo ci fosse una soluzione più elegante): – ComputerSaysNo

+0

Penso di aver dato abbastanza tempo a questa domanda, la tua risposta è più vicina alla mia domanda, purtroppo devo andare con il "modo più lungo" di risolvere il problema, che significa più query ..., grazie per la risposta (: – ComputerSaysNo

4

è possibile creare una stored procedure e chiamare da 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^ 

Sembra execute statement è supported by Firebird 1.5 già. In Firebird 2.0 e versioni successive, è possibile anche racchiudere il codice in un execute block ed evitare di creare una stored procedure.

+0

+1 grazie TOndrej, avevi ragione, GEN_TABLENAME è la convenzione, ma preferisco una soluzione più semplice – ComputerSaysNo

2

Con il seguente trucco si può per impostare il valore del generatore al valore massimo ID di una tabella con un'istruzione SQL in Firebird:

SELECT GEN_ID(GEN_TABLENAME, 
    (SELECT MAX(ID) FROM TABLENAME) - GEN_ID(GEN_TABLENAME, 0)) FROM RDB$DATABASE; 

che funziona, perché GEN_ID(<GeneratorName>, <increment>) ottiene il valore del generatore e l'incrementa di <increment>. Questo dovrebbe funzionare in Firebird 1.5 e nelle versioni più recenti.

+0

Se sai che il generatore è 0, questo è ancora più semplice: 'SELECT GEN_ID (GEN_TABLENAME, (SELECT MAX (ID) FROM TABLENAME)) da DATABASE $ RDB; ' – yonojoy

Problemi correlati