Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi INSERT - Statement wird nicht ausgeführt (https://www.delphipraxis.net/138143-insert-statement-wird-nicht-ausgefuehrt.html)

Mithrandir 4. Aug 2009 10:13

Datenbank: Firebird • Version: 2.1 • Zugriff über: ZEOS

INSERT - Statement wird nicht ausgeführt
 
*seufz*

Dieser Code

Delphi-Quellcode:
  procedure TDGHBDatabase.AddEntry(Entry: TDGHBEntry);
  var
    InsertEntryQuery : TZQuery;
    GetUserIDQuery: TZQuery;
    GetCategoryIDQuery: TZQuery;

    I,
    UserID: Integer;
    CategoryID: Integer;

    CurrDay,
    CurrMonth,
    CurrYear: Word;

    EntryID: Integer;
  begin

    InsertEntryQuery := TZQuery.Create(nil);
    GetUserIDQuery := TZQuery.Create(nil);
    GetCategoryIDQuery := TZQuery.Create(nil);

    if not fIgUser then
    begin
      with GetUserIDQuery do
      begin
        Connection := fConnection;
        ParamCheck := true;
        SQL.Text := 'SELECT ID FROM USERS WHERE USER_NAME = :user';
        ParamByName('user').AsString := Entry.User;
        Open;
        UserID := FieldByName('ID').AsInteger;
      end;
    end
    else
      UserID := -1;

    with GetCategoryIDQuery do
    begin
      Connection := fConnection;
      ParamCheck := true;
      SQL.Text := 'SELECT ID FROM CATEGORIES WHERE CATEGORIE_NAME = :cat';
      ParamByName('cat').AsString := Entry.Categorie;
      Open;
      CategoryID := FieldByName('ID').AsInteger;
    end;

    with InsertEntryQuery do
      begin
        Connection := fConnection;
        ParamCheck := true;
        SQL.Text := 'INSERT INTO EXPENSES (ID, EXP_TYPE, EXP_VALUE, EXP_CATEGORY, EXP_COMMENT, EXP_USER, EXP_DAY, EXP_MONTH, EXP_YEAR, EXP_LUX)' +
                    ' VALUES (:id, :exp_type, :exp_value, :exp_category, :exp_comment, :exp_user, :exp_day, :exp_month, :exp_year, :exp_lux) RETURNING "ID";';
        ParamByName('exp_type').AsInteger := Integer(Entry.EntryType);
        ParamByName('exp_value').AsFloat := Entry.Value;
        ParamByName('exp_category').AsInteger := CategoryID;
        ParamByName('exp_comment').AsString := '';
        ParamByName('exp_user').AsInteger := UserID;
        DecodeDate(Entry.Date, CurrYear, CurrMonth, CurrDay);
        ParamByName('exp_day').AsInteger := CurrDay;
        ParamByName('exp_month').AsInteger := CurrMonth;
        ParamByName('exp_year').AsInteger := CurrYear;
        ParamByName('exp_lux').AsInteger := BoolToInt(Entry.Luxury);
        Open;
        EntryID := FieldByName('ID').AsInteger;
      end;

    for i := 0 to Entry.Tags.Count - 1 do
      begin
       AddTermRelation(GetTermNameToID(Entry.Tags[i]), EntryID);
      end;

    InsertEntryQuery.Free;
    GetUserIDQuery.Free;
    GetCategoryIDQuery.Free;
  end;
beinhaltet dieses SQL-Statement:

SQL-Code:
INSERT INTO EXPENSES (ID, EXP_TYPE, EXP_VALUE, EXP_CATEGORY, EXP_COMMENT, EXP_USER, EXP_DAY, EXP_MONTH, EXP_YEAR, EXP_LUX) VALUES (:id, :exp_type, :exp_value, :exp_category, :exp_comment, :exp_user, :exp_day, :exp_month, :exp_year, :exp_lux) RETURNING "ID";
Die Funktion wird ohne murren durchlaufen, nur am Ende wird kein Eintrag der DB hinzugefügt. Ich habe das Statement schon durch einen Validator gejagt, in der Hoffnung, dass Zeos einfach nur eine Felermeldung verschluckt. Aber das Statement ist gültig. Und ich bin der festen Überzeugung, dass es auch schonmal funktionierte. Aber jetzt geht es nicht mehr, und ich habe keine Ahnung, warum. :wall:

Die Tabelle wird so erstellt:
SQL-Code:
CREATE TABLE EXPENSES (ID INTEGER, EXP_TYPE INTEGER, EXP_VALUE FLOAT, EXP_CATEGORY INTEGER, EXP_COMMENT CHAR(255) CHARACTER SET NONE, EXP_USER INTEGER, EXP_DAY INTEGER, EXP_MONTH INTEGER, EXP_YEAR INTEGER, EXP_LUX INTEGER);
Und mithilfe dieser Funktion wird auf "ID" ein Auto Inc gesetzt:
Delphi-Quellcode:
  procedure TDGHBDatabase.FireBirdAutoInc(const zConnection: TZConnection; Table, forField: string; IsGlobal: Boolean = false);
var
  zQuery: TZQuery;
begin
  zQuery := TZQuery.Create(nil);
  try
    with zQuery do
    begin
      // Verbindung festlegen und prüfen
      Connection := zConnection;
      if Assigned(Connection) and Connection.Connected then
      begin
        // Generator erzeugen
        SQL.Text := 'CREATE GENERATOR ' + Table + '_AUTOINC;';
        ExecSQL;
        // Generator mit Spalte verbinden
        SQL.Text := 'SET GENERATOR ' + Table + '_AUTOINC TO 0';
        ExecSQL;
        // Trigger definieren
        SQL.Clear;
        SQL.Add('CREATE TRIGGER ' + Table + '_AUTOINC_TRG for ' + Table);
        SQL.Add('active before insert position 0');
        SQL.Add('as');
        SQL.Add('begin');
        SQL.Add(' new.' + forField + ' = gen_id( ' + Table + '_AUTOINC, 1 );');
        SQL.Add('end');
        ExecSQL;
      end; // if Assigned...
    end; // with zQuery do
  finally
    zQuery.Free;
  end;
end;

FireBirdAutoInc(fConnection, 'EXPENSES', 'ID');
Der Rückgabewert von ID ist übrigens 1. INSERT-Statements im Allgemeinen funktionieren, nur dieses spezielle halt nicht... Hat jemand eine Idee/Anregungen, wo ich noch gucken kann bzw. was das Problem sein kann?

mkinzler 4. Aug 2009 10:15

Re: INSERT - Statement wird nicht ausgeführt
 
Wenn der Trigger greifen soll, lass ID im Insert weg
SQL-Code:
INSERT INTO EXPENSES ( EXP_TYPE, EXP_VALUE, EXP_CATEGORY, EXP_COMMENT, EXP_USER, EXP_DAY, EXP_MONTH, EXP_YEAR, EXP_LUX) VALUES (:exp_type, :exp_value, :exp_category, :exp_comment, :exp_user, :exp_day, :exp_month, :exp_year, :exp_lux) RETURNING ID;

Mithrandir 4. Aug 2009 10:18

Re: INSERT - Statement wird nicht ausgeführt
 
Moin Markus,

ok, das ist dann wieder mein Ursprungsstatement, da ich dachte, es könnte daran liegen. Danke für den Hinweis, aber das Problem löst es leider nicht. :(

hoika 4. Aug 2009 10:19

Re: INSERT - Statement wird nicht ausgeführt
 
Hallo,

du schreibst ja auch Open statt ExecSQL.

Der Trigger greift hier übrigens immer,
ob die ID mit angibst oder nicht.
Das liegt aber am Trigger-Code.

Sollte das geändert werden (nicht empfehlenswert, weil ja schon ein Generator da ist),
muss sowas im Trigger stehen.

SQL-Code:
if old.id is null

Heiko

Mithrandir 4. Aug 2009 10:23

Re: INSERT - Statement wird nicht ausgeführt
 
Ja, aber wie komme ich dann sonst an den Rückgabewert ("ID")? Hast übrigens Recht, dann funktioniert es. Aber dann ist das Feld "ID" nicht bekannt in der nächsten Zeile.

Und ich hatte das so verstanden, dass, wenn man einen Rückgabewert erwartet, man Open; nutzen muss.

mkinzler 4. Aug 2009 10:27

Re: INSERT - Statement wird nicht ausgeführt
 
Den Rückgabewert bekommst du auch ohne .Open. Hole einfach den ersten Parameter, den der Name ist meist kryptisch.

Blup 4. Aug 2009 10:30

Re: INSERT - Statement wird nicht ausgeführt
 
Eventuell hilft "RequestLive := True" oder "StartTransaction/Commit".

hoika 4. Aug 2009 10:37

Re: INSERT - Statement wird nicht ausgeführt
 
Hallo,

ab FB2 gibt es returning
Es sollte hier schon Beispiele geben.

ah, hattest du ja schon.
Die Id steht bei den Parametern drin.


1


Heiko

DeddyH 4. Aug 2009 10:38

Re: INSERT - Statement wird nicht ausgeführt
 
Und genau dieses Returning steht im Insert-Statement :zwinker:

Mithrandir 4. Aug 2009 10:51

Re: INSERT - Statement wird nicht ausgeführt
 
Hmm... Nee, das wird immer noch nix bei mir...

Zitat:

Die Id steht bei den Parametern drin.
Und wie kann ich darauf zugreifen?

Delphi-Quellcode:
EntryID := InsertEntryQuery.ParamByName('ID').AsInteger;
und

Delphi-Quellcode:
EntryID := InsertEntryQuery.Params[0].AsInteger;
funktionieren beide nicht.

Beim ersten existiert der Parameter nicht, beim zweiten bekomme ich eine 0.

@hoika:

RETURNING ZEOS liefert mir z.B. diesen Thread:

http://www.delphipraxis.net/internal...t.php?t=132648

Und der bringt mich erstmal nicht weiter... :(

Der von dir verlinkte Thread löst mein Problem leider auch nicht, "RET_ID" ist unbekannt... :?

hoika 4. Aug 2009 11:00

Re: INSERT - Statement wird nicht ausgeführt
 
Hallo,

mit dem Thread wollte ich nur zeigen,
dass u.U. ParamByName('ID') nicht klappt.

1. Was bringt denn

ShowMessage(InsertEntryQuery.Params[0].Name)

als Namen überhaupt ?

2. Hast du jetzt ExecSQL oder Open genommen ?

3. Welche ZEOS-Version ?


Heiko

Mithrandir 4. Aug 2009 11:11

Re: INSERT - Statement wird nicht ausgeführt
 
Hi hoika,

Zitat:

mit dem Thread wollte ich nur zeigen,
dass u.U. ParamByName('ID') nicht klappt.
Ach so, ok. :)
Zitat:

1. Was bringt denn

ShowMessage(InsertEntryQuery.Params[0].Name)

als Namen überhaupt ?
"exp_type"

Ich habe daraufhin in das INSERT-STATEMENT "ID" und :id wieder eingefügt. Dann steht dort "id", der Rückgabewert ist aber 0. So kann das also nicht gehen.

Zitat:

2. Hast du jetzt ExecSQL oder Open genommen ?
ExecSQL;

Zitat:

3. Welche ZEOS-Version ?
Die ZEOSDBO 6.6.5 vom 25.5.09

mkinzler 4. Aug 2009 11:13

Re: INSERT - Statement wird nicht ausgeführt
 
Wenn du In-Parameter hast, ist der Rückgabeparamter natürlich der erste nach den Input-Parametern

Mithrandir 4. Aug 2009 11:20

Re: INSERT - Statement wird nicht ausgeführt
 
Ich hab deine Aussage jetzt so interpretiert:

Delphi-Quellcode:
EntryID := InsertEntryQuery.Params[9].AsInteger; //8 In-Parameter
und bin damit auf die Nase gefallen:

Code:
---------------------------
dgHaushaltsbuch
---------------------------
Listenindex überschreitet das Maximum (9)
---------------------------
OK  
---------------------------
:gruebel:

mkinzler 4. Aug 2009 11:21

Re: INSERT - Statement wird nicht ausgeführt
 
Achtung 0-indiziert
Delphi-Quellcode:
EntryID := InsertEntryQuery.Params[8].AsInteger; //8 In-Parameter

Mithrandir 4. Aug 2009 11:24

Re: INSERT - Statement wird nicht ausgeführt
 
Dann bekomme ich aber für

Delphi-Quellcode:
ShowMessage(InsertEntryQuery.Params[8].Name);
den Wert "exp_lux". Und der Rückgabewert ist 0. Das Showmessage wird nach dem ExecSQL; ausgeführt.

mkinzler 4. Aug 2009 11:25

Re: INSERT - Statement wird nicht ausgeführt
 
Dann scheint es ein Problem von Zeos zu sein.

Mithrandir 4. Aug 2009 11:27

Re: INSERT - Statement wird nicht ausgeführt
 
Zitat:

Zitat von mkinzler
Dann scheint es ein Problem von Zeos zu sein.

Argh... :wall:

Hmm, naja, einem geschenkten Gaul... Dann muss ich mir die ID halt über ein separates SELECT-Statement holen. Nicht schön, aber funktioniert hoffentlich...

nahpets 4. Aug 2009 11:28

Re: INSERT - Statement wird nicht ausgeführt
 
Hallo,

was für ein Wert steht denn nach dem Insert in RowsAffected? Sprich: Wurde das Insert überhaupt ausgeführt?

Habe gerade mal in den Sourcen von Zeos nach ExecSQL gesucht. Dort kann ich keine Stelle finden, an der ein von der Datenbank gelieferter Rückgabewert irgendwie an die Komponente zurückgegeben wird.
Habe nur kurz und oberflächlich gesucht, könnte daher was übersehen haben.
Prüf' doch bitte zuerst einmal, ob die Rückgabemöglichkeit von Werten der Firebirddatenbank mit den Zeoskomponenten überhaupt zu realisieren ist.

Bei TZStoredProc.ExecProc scheint es eine entsprechende Möglichkeit zu geben.
Eventuell eröffnet das Dir ja eine Hintertür, indem Du das Insert per Stored Procedure machst und der Prozedur die Parameter übergibst.

mkinzler 4. Aug 2009 11:30

Re: INSERT - Statement wird nicht ausgeführt
 
Oder Notfalls als Execution block in einem normalen Statement, dann als Ergebnis

Mithrandir 4. Aug 2009 11:33

Re: INSERT - Statement wird nicht ausgeführt
 
Hi Stephan,

ich bin immer noch recht unbedarft, was Datenbanken angeht, insofern verstehe ich in deinem letzten Absatz nur Bahnhof. (Edit: Gilt auch für den Beitrag von Markus. :mrgreen: ).

Zitat:

was für ein Wert steht denn nach dem Insert in RowsAffected? Sprich: Wurde das Insert überhaupt ausgeführt?
Ja, das Insert wird ausgeführt, ich kann die Daten anschließend aus der DB holen und auch IBExpert zeigt mir die Werte an.

Zitat:

Prüf' doch bitte zuerst einmal, ob die Rückgabemöglichkeit von Werten der Firebirddatenbank mit den Zeoskomponenten überhaupt zu realisieren ist.
Naja, generell bekommt man ja was zurück, allerdings muss man dafür Open; nutzen. Das wiederum geht aber nur mit SELECT und Co. (glaub ich...). Oder hab ich dich falsch verstanden?

Edit2: Ich denke einfach mal, dass das Feature von den ZEOS noch nicht unterstützt wird. Vielleicht kommts ja irgendwann mal rein...

mkinzler 4. Aug 2009 11:39

Re: INSERT - Statement wird nicht ausgeführt
 
Er meinte, das du das Insert Statement in eine SP packst, in der du den Rückgabewert dann als Ausgabefeld zurückgibst. Statt einer SP kann man den PL-Block auch direkt in einer Abfrage ausführen

PL=Procedure Language

hoika 4. Aug 2009 12:22

Re: INSERT - Statement wird nicht ausgeführt
 
Hallo,

also ich mache das immer (noch) so.

- SP aufrufen, per Gen_Id + Generator nächste ID abholen
- die ID dem Insert übergeben
im Trigger steht dann noch
if Old.ID is NULL
damit nicht noch ne ID geholt wird

Vorteil:
Funktioniert mit allen FB-Versionen
gerade bei Massenimports reicht ein gen_id(gen_name, 100)
um 100 ID'S zu belegen

Nachteil:
Ein zusätzlicher Aufruf bei jedem Insert

weitere Infos dazu hier

1
Dort nach Key Generators suchen


Heiko

PS:
Welche ZEOS-Version hast du denn nun ?
Ev. ist ja eine neue Version draussen, die das returning auswertet ?

Mithrandir 4. Aug 2009 12:27

Re: INSERT - Statement wird nicht ausgeführt
 
Hi,

Das mit den SP gucke ich mir nochmal genauer an. Ich habe jetzt erstmal ein zusätzliches SELECT Statement genommen und dann einfach die ID Spalte abwärts sortiert. Da das Programm für den Eigenbedarf ist und heute fertig werden sollte muss, geht das erstmal Q'n'D. :)

Zitat:

PS:
Welche ZEOS-Version hast du denn nun ?
Ev. ist ja eine neue Version draussen, die das returning auswertet ?
Na,

Hab ich doch geschrieben. ;)

Danke für eure Hilfe. :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:47 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-2025 by Thomas Breitkreuz