![]() |
Firebird : Tabelle erstellen mit AutoInc-Feld
Hallo zusammen,
ich erstelle mit folgenden Script eine Tabelle :
SQL-Code:
So wie muss ich jetzt den Insert-Befehl schreiben, damit das Feld ID mit dem AutoIncrementwert gefüllt wird ?
CREATE TABLE PRODUKTE (
ID INTEGER NOT NULL, PRODUCTID VARCHAR(100) NOT NULL, BEZEICHNUNG VARCHAR(255) NOT NULL); CREATE GENERATOR GEN_PRODUKTE_ID; SET TERM ^ ; create trigger produkte_bi for produkte active before insert position 0 as begin if (new.id is null) then new.id = gen_id(gen_produkte_id,1); end ^ SET TERM ; ^ SET TERM ^ ; create procedure sp_gen_produkte_id returns (id integer) as begin id = gen_id(gen_produkte_id, 1); suspend; end ^ SET TERM ; ^ |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Hallo,
wozu dient denn die SP? Na, egal, so sollte es gehen:
SQL-Code:
INSERT INTO Produkte(ProductId, Bezeichnung) VALUES('12345','Ein Produkt')
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Danke, wunderbar hat funktioniert.
|
DP-Maintenance
Dieses Thema wurde von "Phoenix" von "Programmieren allgemein" nach "Datenbanken" verschoben.
Das war ne Datenbank-Frage |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Du solltest im Trigger bedingungslos die ID aus dem Generator eintragen.
Warum? Es könnte sonst es zu Schlüsselverletzungen führen: Der Generator steht bei 3, aber User trägt selbst 3 ein. Beim nächsten Insert ohne dass der User eine Id angibt würde der Generator um eins erhöht und versucht eine weitere 3 einzufügen -> Kabumm Wie kriegst du die Id nach einem Insert? Bei einem Insert führst du das hier mit Query.Open aus (nicht ExecSql!):
SQL-Code:
In der "Ergebnismenge" findest du die neue ID in der ersten Spalte.
INSERT INTO Produkte
(ProductID ,Bezeichnung) VALUES (:ProductID ,:Bezeichnung) RETURNING Id |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Das Dumme ist, dass ich diesen Trigger auch schon in einer Doku gesehen habe (ob das jetzt auf firebirdsql.org oder ibphoenix.com oder sonstwo war, weiß ich leider nicht mehr). Ich stimme Dir zu, wenn schon "Auto_inc", dann richtig.
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Erst die neue Returning-Clause erlaubt es. Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Naja, zum Einen hatte ich diesen Begriff mit Absicht in Anführungszeichen gesetzt und zum Anderen bezog ich mich dabei auf den Titel dieses Threads :) .
Schönen Abend noch |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Wie funktioniert denn ein richtiger AutoInc von der SQL-Syntax bei Firebird ?
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Das steht in Deinem ersten Beitrag, sofern man die überflüssige SP weg lässt. Mehr ist es nicht. Es gilt allerdings, die ID nicht selber einzutragen. Das muss dann schon der Trigger machen, damit auch die MGA greift.
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Ich hätte noch 2 Fragen noch dazu :
1.) Verstehe ich das richtig, wenn ich diesen Teil weglasse
SQL-Code:
Dann kann ich dem Problem aus dem Weg gehen, welches Elvis angesprochen hat ?
SET TERM ^ ;
create procedure sp_gen_produkte_id returns (id integer) as begin id = gen_id(gen_produkte_id, 1); suspend; end ^ SET TERM ; ^ 2.) Und was ist zum Teufel eine Multi-Generationen-Architektur (MGA) ? |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Ja, wegen der MGA sollte gar kein Problem entstehen. Die SP ist ein Ersatz für einen vor FB 2.0 nicht vorhandenen Trigger, der auch Rückgabewerte liefert. Werden die überhaupt gebraucht ? Im Normalfall überlässt man die IDs der DB und basta.
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Der Trigger liefert immer noch keinen Rückgabewert, sondern das Insert-Statement. Man kann aber die ID auch vom Client setzen, solange man den Generator verwendet
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Hi,
Zitat:
Ich habe generell folgende Vorgehensweise: 1. Alle Tabellen haben ein PK-Feld "ID". 2. Diese ID wird ggf. durch einen Trigger, wie RWarnecke ihn schon verwendet, gesetzt
SQL-Code:
3. Wenn es das Programm noch vor dem Absetzen eines Statements eine neue ID erfordert, z.B. für ein Insert
create trigger produkte_bi for produkte
active before insert position 0 as begin if (new.id is null) then new.id = gen_id(GEN_PRODUKTE_ID,1); end bei Master-Detail Verknüpfungen, so wird diese neue ID vorher explizit durch das Programm geholt. Das kann mittels der verwendeten Komponenten (bei mir FIBPlus) erfolgen oder über eine eigene Query mit folgendem Statement (FIBPlus macht auch nichts anderes):
SQL-Code:
Ich brauche also keine extra SP und ein "konsistentes Handling von generator-basierten Pks"
select GEN_ID(GEN_PRODUKTE_ID, 1) from RDB$DATABASE
ist auch auch vor FB 2.0 gewährleistet. Unter FB2.x kann Rückgabe der ID wie Elvis schrieb mit "INSERT .. RETURNING ID" verfolgen. Damit entfällt der Punkt 3. Den Trigger würde ich aber immer beibehalten. alex |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Zitat:
Zitat:
Ansonsten schreibt einer eine 1000 rein und irgendwann, 3 Wochen später, will dein Programm über den friemeligen "Generator abfragen & Wert beim Insert mitgeben"-Weg einen Datensatz einfügen und es knallt! Nun, irgendwann musste der Generator ja die 1000 erreichen. :mrgreen: Zitat:
Hatte ich das wirklich so unverständlich geschrieben? :gruebel: |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Zitat:
SQL-Code:
erfolgt durch das Programm direkt vor dem Absetzen des Insert-Statements und ist in keinem Fall dem Benutzer überlassen.
select GEN_ID(GEN_..._ID, 1) from rdb$database
Da die neue ID durch den selben Generator erzeugt wird, der auch im Trigger Verwendung findet, kann es niemals vorkommen, dass die IDs doppelt vergeben werden. Der Vorgang der ID-Vergabe ist also in beiden Fällen (Trigger/select GEN_ID(..)) identisch, er wird nur falls notwendig in das Programm vorverlegt. Zitat:
Ich generiere eine NEUE Rechnung (Rech) mit Rechnungsposten (RPosten) im Formular. Da Rech- und RPosten-Daten in einer Transaktion gespeichert werden müssen, benötige ich vorher die ID der Rechnung, um diese in den RPosten-Daten als Link(FK) auf die Rech eintragen zu können. Ich hole mir, wie oben beschrieben, explizit eine neu ID, und gebe diese beim Insert sowohl der Rechnung als auch den RPosten mit. Fertig! Äh.., natürlich nur wenn der Trigger nicht einfach bedingungslos der Rechnung eine andere ID verpasst. Aber den Trigger habe ja ich angelegt und nicht Elvis :wink: Zitat:
Es ist also keine dunkle Ära, man muss nur die Augen aufmachen, damit es hell wird! :mrgreen: Schöne Pfingsten alex :cheers: |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
IMHO sind alle Lösungen, welche auf Generatoren aufsetzen gleich gut. Seien es jetzt durch Einsatz eines Triggers, einer SP, direkt im Statement oder dem Einsatz von clientseitiger Komponenten, welche darauf aufsetzen (TZSequence usw.)
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Zitat:
Pseudo code:
Delphi-Quellcode:
using transaction := deineConnection.BeginTransaction() do
begin using command := connection.CreateCommand() do begin command.CommandText := 'INSERT INTO Rechungen(blabla) VALUES(:Blabla) RETURINNG ID'; command.Parameters.Add('Blabla', 1); var rechungsId := command.ExecuteScalar() as Integer; command.CommandText := 'INSERT INTO RechungsPostenen(Rechung) VALUES(:Rechung) RETURNING ID'; command.Parameters.Add('Rechung', rechungsId); var rechungsPostenId := command.ExecuteScalar() as Integer; ... end; transaction.Commit(); end; Zitat:
Zitat:
Zitat:
Zitat:
Dann können nicht beide Lösungen gleich gut sein. ;) |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Er hat das klassische Bsp. der Rechnung erklärt. Genau so nuss es gemacht werden. Also wird Rückgabewert gebraucht. Der Trigger scheidet somit aus und die beiden Möglichkeiten bestehen dann darin eine SP zu verwenden oder eben FB 2.0. Beides ist für den Zweck gut und macht keine Probleme. |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Sorry Alex, "schöne Pfingsten" vergessen.
Und nun die quartalsmäßige Antwort an Hansa: Zitat:
Deine "Kompetenz" beginnt und endet bei Firebird, und selbst da hast du absolut keinen Plan. Kleiner Tipp an alle anderen, wenn es euch so wie mir gerade geht[1], versucht das was ich normalerweise auch mache: Versucht ihn zu ignoriert... [1] Hansa hat auf einen Beitrag von euch geantwortet |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Aber ich werte ich das einfach als Zustimmung zu meiner Darstellung. Überredet? ;) alex |
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
IOW, dein Einwand für das manuelle Generatorgefriemel und die Lücke im Trigger, die es ermöglicht eine ID in die Tabelle einzufügen, die als DeinGenerator.NextValue ist. Ich wollte zeigen dass es mit "Returning" auch in dem von dir geschilderten Fall einfacher ist. Wenn zusätzlich die Lücke aus dem Trigger entfernt werden kann ist's ja nur besser. :) Schließlich kannst du ja nur dann einen FK von Rechnungsposten auf Rechungen haben wenn der Rechungsdatensatz existiert, bevor du den Rechungsposten einfügst. Zitat:
|
Re: Firebird : Tabelle erstellen mit AutoInc-Feld
Zitat:
Zitat:
Diese Lücke ist aber nur theoretisch, da praktisch das Programm die ID vor dem Insert aus dem Generator holt. Allerdings bekommst du mit deinem "lückenslosen"-Trigger u.U. Probleme: z.B beim Import bestehender verlinkter Daten, der Trigger muß dann ggf. deaktiviert werden. von Zitat:
alex |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz