Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi In einer Existierenden Firebird Table ein feld ergänzen (https://www.delphipraxis.net/163144-einer-existierenden-firebird-table-ein-feld-ergaenzen.html)

joehd1 17. Sep 2011 00:28

Datenbank: Firebird • Version: 2.5 • Zugriff über: IBQUERY

In einer Existierenden Firebird Table ein feld ergänzen
 
Hallo
Also meine Idee ist ich möchte schauen ob meine SQl Tabellen auch alle Felder haben

Da hatte ich folgende Idee

Ich schreibe einen Funktion mit folgendem Inhalt
Code:
Function tsqldbform.Checkdatab_field(Tabelle:TIBQuery;Tabname:String;Feldname:String;feldtyp:String;Feldsize:integer;notwendig:Boolean):Boolean;
var _feldtyp :tfieldtype;
    sqlbastel : String;
Begin
   if Feldtyp = 'Integer'  then _feldtyp := ftInteger;
   if Feldtyp = 'String'   then _feldtyp := ftString;
   if Feldtyp = 'Boolean'  then _feldtyp := ftBoolean;
   if Feldtyp = 'TimeStamp' then _feldtyp := ftdatetime;
   if Feldtyp = 'Unbekannt' then _feldtyp := ftunknown;
   if Feldtyp = 'Float'    then _feldtyp := ftfloat ;


// Das ist meine neue Check routine aber hat ja nix mit dem Fehler zu tun
  if Tabelle.FindField(Feldname)=nil then
     begin
      Showmessage('Feld nicht vorhanden !');
     end;
 try

  // schauen nach dem Typ des Feldes mit dem Feldnamen Feldname
 if  tabelle.FieldDefs.Find(Feldname).DataType = _feldtyp then
      Result := true;
 Except
  on EDatabaseError do
  Begin // Das Datenbankfeld neu erzeugen
      showmessage('Datenbank Feld:'+Feldname + ' nicht vorhanden ! / Wird erzeugt ! ');
      tabelle.FieldDefs.Add(Feldname,_feldtyp,feldsize,notwendig);
      sqlbastel := 'alter table ' + Trim(Tabname) +  ' add ' + Trim(Feldname) + ' ' + Trim(Feldtyp);
      Tabelle.SQL.Text := sqlbastel; // Hier kommt dann der Fehler ! :-( 
      Tabelle.ExecSQL; // 
      TAbelle.SQL.Clear;
      ibmaintransaction.CommitRetaining;
   end;
So nun kommt beim SQL Monitor folgendes

00:06:05 |
[Application: test ]
testtabelle: [Execute] alter table TEST add FELD4 Integer

00:06:05 |
[Application: test ]
[Error] -607 335544351 unsuccessful metadata update
STORE RDB$RELATION_FIELDS failed


Ich gehe davon aus das der SQl String stimmt a sieht er hier gut aus und wenn ich ihn in interbase Konsole eingebe dann geht er auch !

Aber was ist falsch ... das ich die Prüfung auf exist des Feldes besser machen kann ist mir bekannt. Aber daran liegt es ja nicht

Kann mir jemand helfen ? :roll: :?

mikhal 17. Sep 2011 09:08

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Zuerst: Firebird kennt kein STRING (VARCHAR wäre die Entsprechung) und kein Boolean (INTEGER mit 0 und 1 oder ein CHAR mit 'T' und 'F' als Ersatz).

Zum Anderen: warum wählst du IBQuery? IBScript wäre eigentlich für sowas die richtige Wahl.

Es kann sein, dass du sowohl den Tabellennamen als auch den Feldnamen in Double-Quotes (") bei DDL aufführen musst (Achtung: auf korrekte Schreibweise groß/klein achten). Bin ich auch schon mal drauf reingefallen.

Ansonsten solltest du eine DDL Anweisung mit einem Semikolon abschließen (oder was sonst als Terminierungszeichen definiert ist).

Grüße
Mikhal

Sir Rufo 17. Sep 2011 10:35

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Ich tippe mal darauf, dass der Fehler kommt, weil hier bei einer verm. geöffneten Abfrage der SQL.Text geändert wird.

Stimmt das mit dem Delphi 2 ???

Nersgatt 17. Sep 2011 10:46

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Zitat:

Zitat von mikhal (Beitrag 1124967)
Es kann sein, dass du sowohl den Tabellennamen als auch den Feldnamen in Double-Quotes (") bei DDL aufführen musst (Achtung: auf korrekte Schreibweise groß/klein achten). Bin ich auch schon mal drauf reingefallen

Muss man bei Firebird nicht, solange man keine reservierten Namen als Spaltenbezeichner haben möchte (was ich aber sowieso tunlichst vermeiden würde)

DeddyH 17. Sep 2011 10:50

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Wieso wird Feldtyp eigentlich als String übergeben und dann nach TFieldType geparsed? Wäre es anders herum nicht sinniger?

Sir Rufo 17. Sep 2011 10:59

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Um eine Tabelle zu erweitern würde ich direkt auf die Struktur-Informationen zugreifen.
Diese sollten auf bei Firebird in einer System-Tabelle abgelegt sein.

Findet man das Feld dort nicht, dann per Script die Änderung an die Datenbank schicken.

Jetzt muss man alle Tabellen und Queries die diese Tabelle referenzieren einmal neu laden.
(Worst Case: Close - Open)

Zitat:

Zitat von DeddyH (Beitrag 1124980)
Wieso wird Feldtyp eigentlich als String übergeben und dann nach TFieldType geparsed? Wäre es anders herum nicht sinniger?

Vermutlich, weil die Informationen als Text vorliegen.
Sinnigerweise sollte man diese Umwandlung aber in einer eigenen Funktion erledigen.

DeddyH 17. Sep 2011 11:09

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Welche Informationen wo wie vorliegen ist mir in diesem Zusammenhang wumpe, IMO sollte die Übergabe als TFieldType erfolgen (zur Not eben, wie Du schon sagst, vorher umwandeln). Aber so wie jetzt ist die ganze Sache unnötig fehleranfällig.

joehd1 18. Sep 2011 16:16

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Hallo
erst mal DANKE !
Also das mit dem parsen das wird ausgelagert kommt wie richtig vermutet aus einem anderen Script.
Probiert habe ich das mit einem Integer was in den Filteyp Integer richtig gewandelt wird.
Eigentlich wäre mir lieber ich bastle den SQL String zusammen und los geht es.. Der Tip mit dem Script jepp das werde ich mal angehen das query war nur Hilfsweise aber jepp nicht das richtige ;-)

Das mit den Hochkommas habe ich probiert aber wie man an dem SQL Monitor sieht wurde der String ja richtig übergeben und verstanden...

Ich denke wirklich das wie Sir Rufo vermutet, da wird einfach was sein, was in dem Moment nicht erlaubt das Feld zu ergänzen ... Ich versuche das mal mit ibScript ..Das ibQuery war in dem Moment aber auch nur für das genutzt.

Das mit dem Zugriff direkt auf die Strukturtabelle ... das muss ich mir erst mal anschauen...

Lieber wäre mir ein ganz normaler SQL String ;-)

Das mit dem Case sensitive das ist auch finde ich eine komische Sache, manchmal ist das bei der Datenbank so das es tatsächlich case sensitive ist und manchmal nicht.
Ich schreibe jetzt einfach alles groß.. :roll:
Da hat aber anscheinend die "ibconsole" auch so ihre Probleme damit...

P.s. das mit dem Feldtyp hat sich dann auch erledigt wenn ich meine andere Prüfroutine nutze denn wenn ich ein Feld habe stelle ich sicher das es auch der richtige Typ ist somit brauche ich das nicht testen. mich hatte am Test eh nur interessiert ob es eine exception gibt damit ich weiß das Feld ist nicht da ...

Neumann 18. Sep 2011 17:55

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Ich würde das ganze möglichst vereinfachen. Da man ja seine Datenbank kennt, prüft man auf das Feld was man ergänzt hat etwa so:

Delphi-Quellcode:
   IBSQLUpdate.close; //IBSQL
   IBSQLUpdate.SQL.Add('Select * from TabelleA');
   if not ibsqlupdate.transaction.active then
   ibsqlupdate.transaction.starttransaction;
   IBSQLUpdate.ExecQuery;
   bfiliale:= dm.IBSQLUpdate.FieldIndex['filiale']>=0 ; //bfiliale:boolean
   IBSQLUpdate.Close;
    if not filiale then
    begin
      dm.IBSQLUpdate.Close;
      dm.ibsqlupdate.SQL.Clear;
      dm.IBSQLUpdate.SQL.Add('ALTER TABLE TabelleA Add Filiale integer');
      moddatabase; // Führt die Query aus mit Transaktionssteuerung
    end;
Die Idee, das mit einer allgemeinen Funktion zu machen ist aber grundsätzlich gut. Man muss dabei dann aber auch an die verschiedenen Datentypen (VarChar, Numeric, Blob) die weitere Parameter brauchen denken oder noch besser diese als Domains anlegen.

joehd1 18. Sep 2011 20:22

AW: In einer Existierenden Firebird Table ein feld ergänzen
 
Also ich habe das ganze nun auf Script umgestellt aber das gleiche Problem. Muss ich dabei alle anderen Query und tables abmelden Close machen ?
Ja ich denke mit einer extra function kann ich im Fall eines Updates einfach ein Prüfscript mitgeben und dann wird die Datenbank aktuell ...

Ich kann aber das script auch genauso in der Console ausführen und es geht ... ich verstehe das nicht.
Script oder query kein unterschied ...
:cry:

Jetzt kommt
20:30:46 |
[Application: Test]
: [Start transaction]
20:30:46 |
[Application: Test]
: [Execute] alter table TEST add FELD4 Integer

20:30:46 |
[Application: Test]
[Error] -607 335544351 unsuccessful metadata update
STORE RDB$RELATION_FIELDS failed
20:30:46 |
[Application: Test]
: [Rollback]

Delphi-Quellcode:
Function tsqldbform.Checkdatab_field(Tabelle:TIBQuery;Tabname:String;Feldname:String;feldtyp:String;Feldsize:integer;notwendig:Boolean):Boolean;
var _feldtyp :tfieldtype;
    sqlbastel : String;
Begin
  // schauen ob das Datenfeld existiert
  if Tabelle.FindField(Feldname)=nil then
     begin
//      Showmessage('Feld nicht vorhanden !');
      showmessage('Datenbank Feld:'+Feldname + ' nicht vorhanden ! / Wird erzeugt ! ');
      sqlbastel := 'alter table ' + Trim(Tabname) +  ' add ' + Trim(Feldname) + ' ' + Trim(Feldtyp) +';';

      ibscript1.Script.Text := sqlbastel;
      // Tabelle.SQL.add(sqlbastel);
      ibscript1.ExecuteScript; // Open ; //  ExecSQL;  // SQL.BeginUpdate;
      // ibscript1.Script.Clear; //  SQL.Clear;
      ibmaintransaction.CommitRetaining;
      showmessage(ibscript1.script.text );

     end;
end;
warum kann das Script was ja richtig ankommt nicht ausgeführt werden ?
das muss irgend einen Grund haben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:49 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