Controllare questo semplice pezzo di codice che utilizza un generatore per creare chiavi primarie univoche in una tabella Firebird:Come faccio a non sprecare i valori del Generatore quando li utilizzo sul lato server con Firebird?
CREATE OR ALTER TRIGGER ON_BEFOREINSERT_PK_BOOKING_ITEM FOR BOOKING_ITEM BEFORE INSERT POSITION 0
AS
BEGIN
IF ((NEW.booking_item_id IS NULL) OR (NEW.booking_item_id = 0)) THEN BEGIN
SELECT GEN_ID(LastIdBookingItem, 1) FROM RDB$DATABASE INTO :NEW.booking_item_id;
END
END!
Questo trigger palio e incrementi assegna quindi un valore generato per l'elemento Prenotazione id creando così un auto-incrementato chiave per la tabella BOOKING_ITEM. Il trigger controlla anche che all'ID di prenotazione non sia già stato assegnato un valore.
Il problema è che il valore ad incremento automatico verrà perso (sprecato) se, per qualche motivo, il record BOOKING_ITEM non può essere registrato.
Ho un paio di idee su come evitare questo spreco ma ho preoccupazioni su ciascuno. Eccoli:
decrementare il contatore se si verifica un errore di invio. All'interno del trigger ho impostato un blocco try-except (provate, eccetto i blocchi che esistono anche in Firebird PSQL?) Ed eseguite un
SELECT GEN_ID(LastIdBookingItem, -1) FROM RDB$DATABASE
per le eccezioni dei post. Questo lavoro dovrebbe funzionare? Cosa succede se un'altra transazione si insinua e incrementa il generatore prima di decrementarlo? Questo farebbe davvero casino.Utilizzare un ID temporaneo. Impostare l'id su un valore temp univoco che modifico sul valore del generatore che voglio sul trigger AFTER INSERT. Questo metodo sembra un po 'forzato e richiede un modo che assicuri che l'id temp sia unico. Ma cosa succede se il booking_item_id è stato fornito lato client, come potrei distinguere da un id temp ?. Inoltre ho bisogno di un altro trigger
Utilizzare il controllo delle transazioni. È come l'opzione 1. tranne che per utilizzare il blocco try-except per reimpostare il generatore, avviare una transazione e quindi ripristinarla se il record non riesce a postare. Non conosco la sintassi per l'utilizzo del controllo delle transazioni. Ho pensato di leggere da qualche parte che SAVEPOINT/SET TRANSACTION non è consentito in PSQL. Inoltre, il rollback dovrebbe avvenire nel trigger AFTER INSERT, quindi ancora una volta ho bisogno di un altro trigger.
Sicuramente questo è un problema per tutti gli sviluppatori Firebird che vuole usare generatori. Altre idee? C'è qualcosa che mi manca?
La risposta è la stessa di tutti gli altri DBMS che utilizzano sequenze: non preoccuparti. Le sequenze non sono progettate per essere prive di spazio e il loro valore non ha senso. Il loro unico scopo è quello di servire come chiave primaria artificiale. Niente di più. Se la tua applicazione si basa su valori gapless, semplicemente non puoi usare una sequenza (cerca in questo sito "sequenza senza pause" per le alternative). –
Sto cercando questo sito per "sequenza senza pause" per le alternative. Grazie. Principalmente hai ragione "chi se ne frega" ma per alcune tabelle sto generando un numero di sequenza e usandolo come, diciamo, un numero di fattura. A volte i nostri revisori ci chiedono di produrre fatture da X a X + n. Certamente non tutte le fatture devono essere attive, alcune possono essere cancellate, ma si chiedono se mancano dei numeri. Fanno domande come "Dov'è la fattura 12345"? –
Esatto, per i numeri di fattura è necessario qualcosa di diverso. Una sequenza non è adatta a questo. –