Entwickler-Ecke
Datenbanken - Neuen Datensatz anlegen in Firebird Datenbank
SmileySN - So 18.06.06 19:59
Titel: Neuen Datensatz anlegen in Firebird Datenbank
Es kann doch nicht so schwer seine, einen neuen Datensatz anzulegen, oder doch ?
Ich benutze Firebird 1.5 und die Zeos Komponenten.
In meiner DB habe ich die Tabelle Firma mit der PK ID.
Dazu einen Generator und einen Trigger der auf Insert reagiert.
Wenn ich jetzt einen neuen Datensatz anlegen will mache ich das folgendermassen:
Delphi-Quelltext
1: 2: 3: 4:
| DM.QFirma.SQL.Clear; DM.QFirma.SQL.Add('Insert into Firma (Name,Strasse) Values (''NeuName'',''NeuStrasse'')'); DM.QFirma.ExecSQL; |
Mit diesem Insert Befehl sollte doch der Trigger anspringen und eine eindeutige ID vergeben.
Stattdessen bekomme ich die Meldung:
'no 2 Tables can have duplicate collumn values'
Kann mir mal jemand sagen wie man einen neuen Datensatz anlegt (leer nur mit ID reicht mir schon)
mkinzler - So 18.06.06 20:02
Welchen wert hat der dazugehörige Generator?
SmileySN - So 18.06.06 20:11
Der Generator hat zur Zeit den Wert 13 und das ist auch die ID meines letzten Datensatzes.
mkinzler - So 18.06.06 20:14
Der Generator enthält aber den Wert des nächsten Datensatzes erhöhe den Generator, dann sollte es klappen.
SmileySN - So 18.06.06 20:21
Ok, das hab ich jetzt auch entdeckt, nachdem Du danach gefragt hast, hab den letzten datensatz gelöscht, dann geht es.
War ein Fehler beim Generatorwert.
Jetzt sagt er mir, dass er den Feldnamen 'Name' nicht finden kann, das ist aber eindeutig der Name des Feldes für den Firmennamen. was soll das jetzt ?
SmileySN - So 18.06.06 20:24
Der neue Datensatz wird auch mit den eingetragenen Werten 'Neuname' und NeueStrasse' angelegt
mkinzler - So 18.06.06 20:24
Welchen Namen hat das Feld; 'Name', 'NAME', 'name'?
SmileySN - So 18.06.06 20:36
In der Datenbank sind alle Felder groß geschrieben es heißt hier also 'NAME', das hab ich dann probiert indem ich geschrieben habe:
Delphi-Quelltext
1: 2: 3:
| DM.QFirma.SQL.Clear; DM.QFirma.SQL.Add('Insert into Firma (NAME,STRASSE) Values (''NeuName'',''NeuStrasse'')'); DM.QFirma.ExecSQL; |
Er bringt mir aber noch den gleichen Fehler.
QFirma: Das Feld 'Name' wurde nicht gefunden
mkinzler - So 18.06.06 20:40
Ich vermutete eher das es wirklich Name heißt, dann hätte man den feldname Quoten müssen.
Post mal die Metadaten der Tabelle.
Welche Komponenten verwendest du?
SmileySN - So 18.06.06 20:40
Jetzt bin ich etwas weiter, es passiert in der darauffolgenden Procedure DatenlesenFirma;
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure DatenLesenFirma; begin Form1.EdFirmaName.text := DM.QFirma.FieldByName('NAME').AsString; Form1.EdFirmaStrasse.Text := DM.QFirma.FieldByName('STRASSE').AsString; Form1.EdFirmaPLZ.Text := DM.QFirma.FieldByName('PLZ').AsString; Form1.EdFirmaOrt.Text := DM.QFirma.FieldByName('Ort').AsString; Form1.EdFirmaTel.Text := DM.QFirma.FieldByName('Tel').AsString; Form1.EdFirmaMail.Text := DM.QFirma.FieldByName('Mail').AsString; Form1.EdFirmaWeb.Text := DM.QFirma.FieldByName('Web').AsString; Form1.EdFirmaStatus.Text := DM.QFirma.FieldByName('Status').AsString; Form1.EdFirmaGruendung.Text := DM.QFirma.FieldByName('Gruendung').AsString; Form1.EdFirmaLiq.Text := DM.QFirma.FieldByName('Liq').AsString; Form1.EdFirmaInfo.Text := DM.QFirma.FieldByName('Memo').AsString; AktFirmaID := DM.QFirma.FieldByName('FirmaID').AsInteger; Form1.EdFirmaID.Text := DM.QFirma.FieldByName('FirmaID').AsString; SpracheLaden(AktSprache); end; |
mkinzler - So 18.06.06 20:42
Dann ist es ja klar, win DDL-Query hat keine Felder.
SmileySN - So 18.06.06 20:45
Kann es sein, dass die Query QFirma nicht mehr richtig geöffnet ist nach dem ExecSQL-Befehl ?
Hier mal die definition aus der Datenbank:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85:
| /******************************************************************************/ /*** Generated by IBExpert 18.06.2006 20:43:06 ***/ /******************************************************************************/
SET SQL DIALECT 3;
SET NAMES NONE;
/******************************************************************************/ /*** Tables ***/ /******************************************************************************/
CREATE GENERATOR GEN_FIRMA_ID;
CREATE TABLE FIRMA ( FIRMAID INTEGER NOT NULL, NAME VARCHAR(40), STRASSE VARCHAR(40), PLZ VARCHAR(10), ORT VARCHAR(40), TEL VARCHAR(40), MAIL VARCHAR(40), WEB VARCHAR(40), STATUS VARCHAR(20), GRUENDUNG DATE, LIQ DATE, MEMO BLOB SUB_TYPE 2 SEGMENT SIZE 16384 );
/******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/
ALTER TABLE FIRMA ADD CONSTRAINT PK_FIRMA PRIMARY KEY (FIRMAID);
/******************************************************************************/ /*** Indices ***/ /******************************************************************************/
CREATE INDEX IDX_FIRMA_NAME ON FIRMA (NAME);
/******************************************************************************/ /*** Triggers ***/ /******************************************************************************/
SET TERM ^ ;
/******************************************************************************/ /*** Triggers for tables ***/ /******************************************************************************/
/* Trigger: FIRMA_BI */ CREATE TRIGGER FIRMA_BI FOR FIRMA ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.FIRMAID IS NULL) THEN NEW.FIRMAID = GEN_ID(GEN_FIRMA_ID,1); END ^
SET TERM ; ^
/******************************************************************************/ /*** Privileges ***/ /******************************************************************************/
/* Privileges of users */ GRANT ALL ON FIRMA TO DBUSER; |
mkinzler - So 18.06.06 20:51
.ExecSQL liefert keinen Cursor. Ich würde in deinem Fall 2 Queries nehmen, Abfrage und DML getrennt.
SmileySN - So 18.06.06 20:52
Zitat: |
Dann ist es ja klar, win DDL-Query hat keine Felder. |
Das sagt mir jetzt nichts ?????
mkinzler - So 18.06.06 20:55
Eine Abfrage mit Select liefert ein Cursor mit feldern auf dene man mit .FieldByName o.ö. zugreifen kann, eine DML-Abfrage nicht; nach dem .ExecSQL ist der Query geschlössen.
SmileySN - So 18.06.06 20:56
Das hat sich jetzt etwas überschnitten.
Ich kann natürlich auch ein zweites Query für das Insert anlegen, aber wie wird es denn normalerweise gemacht.
Ich muss nach dem INSERT ja die Daten wieder am Bildschirm anzeigen lassen damit der Benutzer die Änderungen sieht.
Ist es wirklich so aufwendig ? Oder gehe ich hier einfach nur einen komplizierten Weg ??
mkinzler - So 18.06.06 21:00
Du kannst natürlich nur einen Query nehmen, ist aber dann nicht optimal, weil du ständig die Abfrage ändern mußt. Besser sind 2. Wobei nach dem Insert ein refresh auf den select-Query gemacht werden muß.
SmileySN - So 18.06.06 21:02
Ich kann auch einfach ein neues Select machen, nur brauche ich dazu die Datensatznummer des neuen Datensatzes und den kann ich ja noch nicht ansprechen.
Oder ich muss auf den letzten Datensatz springen und mir dort die ID holen.
SmileySN - So 18.06.06 21:19
Jetzt bin ich wieder an dem alten Problem mit der ID lesen.
Den letzten Datensatz lesen ist auch nicht so sicher, da könnte ein anderer User ja auch gerade einen Datensatz neu angelegt haben. Dann bekomme ich seinen Datensatz und nicht meinen gerade eingefügten.
Lässt sich das Problem doch nur mit einer StoredProcedure lösen ?
mkinzler - So 18.06.06 21:26
Ja, anstatt des Triggers. In der SP dann zuerst den Generator ermitteln/erhöhen, dann insert inkl ID, ID zurückgeben.
SmileySN - So 18.06.06 21:36
Wäre dies hier so richtig ?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| CREATE PROCEDURE INSERTFIRMA ( NAME VARCHAR(40), STRASSE VARCHAR(40)) RETURNS ( ID INTEGER) AS begin ID=GEN_ID(GEN_FIRMA_ID,1); INSERT INTO FIRMA (ID,NAME,STRASSE) values(:ID,:NAME,:STRASSE); suspend; end |
mkinzler - So 18.06.06 21:40
Müsste so gehen.
SmileySN - So 18.06.06 22:57
Ich hab die StoredProcedure jetzt in der Datenbank drin, übergebe keine Werte und bekomme nur ID zurück.
Kannst Du mir noch mal helfen, wie ich die Procedure INSERT_FIRMA aufrufe und die ID damit zurückbekomme ??
Ich weiß nicht wie man eine SP von Delphi aus anspricht und den Parameter übergibt.
mkinzler - So 18.06.06 22:59
SQL-Anweisung
1:
| Select ID from INSERTFIRMA( <Name>, <Strasse>); |
SmileySN - So 18.06.06 23:12
Das Select... ist doch sicher ein SQL-Befehl und muss so auch übergeben werden z.B.
Delphi-Quelltext
1: 2: 3:
| DM.QFirma.SQL.Clear; DM.QFirma.SQL.Add('Select ID from INSERT_FIRMA()'); DM.QFirma.Open; |
Wie kann ich jetzt den Wert ID auslesen ?
mkinzler - So 18.06.06 23:17
Delphi-Quelltext
1: 2: 3: 4:
| DM.QFirma.SQL.Clear; DM.QFirma.SQL.Add('Select ID from INSERT_FIRMA( <Name>, <strasse>)'); DM.QFirma.Open; ID := DM.QFirma.FieldByName('ID').Value; |
SmileySN - So 18.06.06 23:31
So hab ichs hinbekommen:
Delphi-Quelltext
1: 2: 3: 4: 5:
| DM.QFirma.SQL.Clear; DM.QFirma.SQL.Add('Select ID From INSERT_FIRMA'); DM.QFirma.Open;
AktFirmaID:= DM.QFirma.FieldByName('ID').AsInteger; |
Danke für die Kompetente Hilfe
SmileySN - So 18.06.06 23:48
Leider doch noch ein Problem:
Delphi-Quelltext
1:
| AktFirmaID:= DM.QFirma.FieldByName('ID').AsInteger; |
Hier bekomme ich immer nur 0 zurück
Delphi-Quelltext
1:
| AktFirmaID:= DM.QFirma.FieldByName('ID').Value; |
Hier bekomme ich die Meldung:
Variante des Typs (Null) konnte nicht in Typ (Integer) konvertiert werden
SmileySN - So 18.06.06 23:49
So sieht meine SP jetzt in der dB aus
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| CREATE PROCEDURE INSERT_FIRMA RETURNS ( ID INTEGER) AS begin ID=GEN_ID(GEN_FIRMA_ID,1); INSERT INTO FIRMA (FIRMAID) values(:ID); end^
SET TERM ; ^
GRANT INSERT ON FIRMA TO PROCEDURE INSERT_FIRMA; |
Den Trigger musste ich rausnehmen, da er mir sonst noch einen leeren Datensatz zusätzlich angefügt hat.
mkinzler - So 18.06.06 23:55
Zitat: |
Den Trigger musste ich rausnehmen, da er mir sonst noch einen leeren Datensatz zusätzlich angefügt hat. |
Ich hatte ja geschrieben anstatt des Triggers.
Es fehlt nun das
SUSPEND; welches die aktuellen werte der Out-Parameter ( in deinem Fall nur ID) in den Cursor schreibt.
SmileySN - Mo 19.06.06 00:02
Unglaublich, es funktioniert wirklich.
Jetzt weiß ich auch wozu das suspend gut ist.
Danke Du bist großartig.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!