Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   IBDAC: In der DB sind Leerstrings statt Null. Alternativen? (https://www.delphipraxis.net/155237-ibdac-der-db-sind-leerstrings-statt-null-alternativen.html)

BlueStarHH 14. Okt 2010 11:25

Datenbank: Firebird • Version: 2.x • Zugriff über: IBDAC

IBDAC: In der DB sind Leerstrings statt Null. Alternativen?
 
Hallo,

ich verwende die IBDAC-Komponenten von Devart um auf Firebird zuzugreifen. Leider habe ich erst jetzt gemerkt, dass leere Strings/Null-Werte nicht richtig behandelt werden. Wenn ich das hier verwende

Code:
IBCTable1.FieldByName('myField').AsString := '';
wird das Feld mit einem leeren String gefüllt. Ich möchte aber Null im Feld stehen haben. Das passiert auch wenn ein leeres DB-Edit gepostet wird. Alle mir bekannten Kompoenten z.B. BDE oder IBX schreiben in diesen Fällen Null in die DB. Darauf ist meine ganze Anwendung ausgelgegt (2 Mio Zeilen). Ich verwenden oft Code wie if IBCTable1.FieldByName('myField').isNull

Das funktioniert nun natürlich nicht mehr wie gewüscht, da IBDAC Leerstrings und nicht Null in die DB schreibt. Jetzt meine ganze App mit allen SQL-Statements zu ändern ist zu umständlich. Wer kennt Lösungen? Ich hab den Wunsch schon an IBDAC herangetragen, doch da passiert seit Monaten nichts in der Richtung.

Wer kennt eine gute Alternative zu IBDAC (Firebird 2.x, Unicode), die in den genannten Fällen Nullwerte schreibt?

mjustin 14. Okt 2010 11:43

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von BlueStarHH (Beitrag 1055722)
Code:
IBCTable1.FieldByName('myField').AsString := '';

Wird von IBDAC dieses nicht unterstützt? So würde man in dbExpress einen Null Wert zuweisen:

Code:
IBCTable1.FieldByName('myField').Clear;

Bummi 14. Okt 2010 11:44

AW: IBDAC Leerstring statt Null. Alternativen?
 
Ich kenne Deine Komponenten nicht aber IMHO sollte

IBCTable1.FieldByName('myField').Clear

auch bei Dir gehen

Sir Rufo 14. Okt 2010 11:48

AW: IBDAC Leerstring statt Null. Alternativen?
 
Ist mE auch eigentlich korrekt, da ein Leerstring in einer DB vorkommen darf.
Man kann ein Feld in der DB auch definieren, dass dort ein Leerstring nicht zugelassen ist, wäre möglich, dass IBDAC das auch berücksichtigt (Leerstring erlaubt -> '', nicht erlaubt -> NULL)

dataspider 14. Okt 2010 12:08

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von BlueStarHH (Beitrag 1055722)
Hallo,
ich verwende die IBDAC-Komponenten von Devart um auf Firebird zuzugreifen. Leider habe ich erst jetzt gemerkt, dass leere Strings/Null-Werte nicht richtig behandelt werden

Die Behandlung ist schon korrekt. Wenn man einen leeren String übergibt, soll dieser auch so in der DB erscheinen.
AsString ist für deinen Fall schlecht.
Code:
IBCTable1.FieldByName('myField').Value := Null;
wäre als Beispiel eine Möglichkeit. Und Clear (wie bereits erwähnt) sollte es auch tun.

Frank

Lemmy 14. Okt 2010 12:10

AW: IBDAC Leerstring statt Null. Alternativen?
 
Hi,

Zitat:

Zitat von BlueStarHH (Beitrag 1055722)
Code:
IBCTable1.FieldByName('myField').AsString := '';
wird das Feld mit einem leeren String gefüllt.

Würde ich aber auch so sehen, dass da ein leerer String und kein NULL stehen soll.

Zitat:

Zitat von BlueStarHH (Beitrag 1055722)
Wer kennt eine gute Alternative zu IBDAC (Firebird 2.x, Unicode), die in den genannten Fällen Nullwerte schreibt?

Blöde Idee: IBDac ist die mir bisher einzigste Komponentensammlung die über einen WIzard realtiv einfach einen Austausch ermöglicht. Willst Du von Hand alle deine Queries und Datasets ändern?
Vorschlag:
Code:
IBCTable1.FieldByName('myField').Clear;
funktioniert, also einfach nach ".AsString := '';" Suchen und durch ".Clear;" ersetzen. Wird schneller gehen, also die Bibliothek auszutauschen....


GRüße

mkinzler 15. Okt 2010 10:39

AW: IBDAC Leerstring statt Null. Alternativen?
 
Oder schreib dir einen Trigger, der '' durch NULL ersetzt vor dem Einfügen/Update setzt

dataspider 15. Okt 2010 14:09

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von mkinzler (Beitrag 1055907)
Oder schreib dir einen Trigger, der '' durch NULL ersetzt vor dem Einfügen/Update setzt

Nicht alles, was machbar ist, ist auch sinnvoll.
Wenn man anfängt, seine nachlässige Programmierung durch Trigger in der DB abzufangen, sträuben sich bei mir die Haare.
Man sollte bei allen Lösungen sich auch die Frage stellen, ob es die saubere Lösung ist.

Frank

Int3g3r 12. Sep 2019 14:29

AW: IBDAC Leerstring statt Null. Alternativen?
 
Guten Tag,

Ich stehe gerade vor dem selben Dilemma. Ich möchte keine Leerstrings in meiner DB. Entweder hat ein Feld ein Zeichen, was kein Leerzeichen ist, oder es ist auf Null gesetzt.

Ist es möglich im BeforPost die Leerstrings zu ersetzen ?
Es wir ja das DataSet mitgegeben ist es nicht möglich die Leerstrings mit Null zu ersetzen?

Freundliche Grüsse
Int3g3r

Uwe Raabe 12. Sep 2019 14:52

AW: IBDAC Leerstring statt Null. Alternativen?
 
Betrifft das auch IBDAC? Ich frage nur, weil FireDAC eine Option StrsEmpty2Null hat, die vermutlich genau diesen Effekt aktiviert.

Int3g3r 12. Sep 2019 15:06

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1445879)
Betrifft das auch IBDAC? Ich frage nur, weil FireDAC eine Option StrsEmpty2Null hat, die vermutlich genau diesen Effekt aktiviert.

Ja, leider. Ich muss dazu aber sagen das ich nicht die neuste version von IBDAC benutze.


EDIT: Hab hier ne mögliche Lösung. Also bei mir Funktionierts. :-D

Delphi-Quellcode:
procedure Tdm.qryTestBeforePost(DataSet: TDataSet);
var
   i: Integer;
begin
   for i := 0 to DataSet.FieldCount-1 do
   begin
      if (DataSet.FieldByName(DataSet.FieldList[i].DisplayName).ReadOnly) or
          (DataSet.FieldByName(DataSet.FieldList[i].DisplayName).IsNull) then
            Continue;

      if trim(DataSet.FieldByName(DataSet.FieldList[i].DisplayName).AsString) = '' then
            DataSet.FieldByName(DataSet.FieldList[i].DisplayName).Clear;
   end;
end;
end;

Uwe Raabe 12. Sep 2019 15:19

AW: IBDAC Leerstring statt Null. Alternativen?
 
Du solltest zum Einen überprüfen, ob du das Feld überhaupt beschreiben darfst, und zum Anderen, ob es nicht schon NULL ist. Auch ein NULL-Wert liefert einen Leerstring bei AsString.

Int3g3r 12. Sep 2019 15:30

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1445884)
Du solltest zum Einen überprüfen, ob du das Feld überhaupt beschreiben darfst, und zum Anderen, ob es nicht schon NULL ist. Auch ein NULL-Wert liefert einen Leerstring bei AsString.

Ahh, sehr gute Überlegung. Besten Dank an das hätte ich nicht gedacht!
Das hätte irgendwann ne Exception gegeben.:roll:
Wurde nun angepasst!

mkinzler 12. Sep 2019 15:32

AW: IBDAC Leerstring statt Null. Alternativen?
 
Alternativ könntre man dies auch mit einem Trigger lösen; wäre dann unabhängig von den Komponenten/Programm.

Uwe Raabe 12. Sep 2019 15:36

AW: IBDAC Leerstring statt Null. Alternativen?
 
Statt
Delphi-Quellcode:
TrimRight(TrimLeft(...
kannst du dich auch gleich
Delphi-Quellcode:
Trim(...
schreiben, oder?

Int3g3r 12. Sep 2019 15:39

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1445892)
Statt
Delphi-Quellcode:
TrimRight(TrimLeft(...
kannst du dich auch gleich
Delphi-Quellcode:
Trim(...
schreiben, oder?

Hast recht hab das nochmals nachgelesen.
Habe gedacht aus " Hallo Welt " würde danach "HalloWelt"

Zitat:

Alternativ könntre man dies auch mit einem Trigger lösen; wäre dann unabhängig von den Komponenten/Programm.
Hatte ich schon vorher gelesen. Da ich mich mit der FireBird-Syntax noch schlechter auskenne als in Delphi, habe ich mir gedacht ich lasse das lieber.

mkinzler 12. Sep 2019 15:51

AW: IBDAC Leerstring statt Null. Alternativen?
 
Hatte ich schon vorher gelesen. Da ich mich mit der FireBird-Syntax noch schlechter auskenne als in Delphi, habe ich mir gedacht ich lasse das lieber.

Ist einfach

SQL-Code:
SET TERM ^^ ;
CREATE TRIGGER <TABELLE>_BI FOR <TABELLE> ACTIVE BEFORE INSERT or UPDATE POSITION 0 AS
begin
  if ( new.<Feld> = '') then new.<Feld> = NULL;
end ^^
SET TERM ; ^^

Int3g3r 12. Sep 2019 16:31

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Ist einfach
Danke für das Beispiel. Werde es ggf. später benutzen.

hoika 12. Sep 2019 16:52

AW: IBDAC Leerstring statt Null. Alternativen?
 
Hallo,
Zitat:

Ich möchte keine Leerstrings in meiner DB
Es gibt doch da auch Unterschiede.

Null = Wert nicht bekannt
"" = Wert bekannt, ist aber leer.

Uwe Raabe 12. Sep 2019 16:57

AW: IBDAC Leerstring statt Null. Alternativen?
 
Es gibt noch eine Möglichkeit: Wert bekannt und kein Leerstring, besteht aber nur aus Leerzeichen.

So wie ich das verstanden habe, ist diese Vorgabe <Leerstring> => NULL hier anwendungsspezifisch.

Int3g3r 12. Sep 2019 17:17

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1445904)
Es gibt noch eine Möglichkeit: Wert bekannt und kein Leerstring, besteht aber nur aus Leerzeichen.

So wie ich das verstanden habe, ist diese Vorgabe <Leerstring> => NULL hier anwendungsspezifisch.

Genau genommen ist ja ein ("Leerstring" != NULL). Nur möchte ich solche Felder in der DB nicht haben. Es sieht einfach schäusslich wenn man Felder hat bei denen ist NULL eingetragen bei anderen wiederum sind "Leerstrings" drin. Am Benutzer ein "Leerstring" anzuzeigen oder einen "Leerstring" auszuwerden ergibt für mich keinen Sinn. Entweder hat ein Feld für mich erkennbare Daten oder es ist LEER = NULL.

Sicherlich kann es für andere Anwendungen Sinn machen wenn man wissen will ob je ein Eintrag gemacht wurde oder nicht. Für meine Anwendung ist dies aber nicht relevant.

hoika 12. Sep 2019 18:19

AW: IBDAC Leerstring statt Null. Alternativen?
 
Hallo,
Zitat:

bei denen ist NULL eingetragen bei anderen wiederum sind "Leerstrings" drin
Das liegt aber am Programmierer ;)

MyRealName 13. Sep 2019 07:11

AW: IBDAC Leerstring statt Null. Alternativen?
 
Man kann das Feld in Firebird ja auch mit einem Default belegen, der dann ein Leerstring ist.

haentschman 13. Sep 2019 07:22

AW: IBDAC Leerstring statt Null. Alternativen?
 
Moin...8-)
Zitat:

Ich möchte keine Leerstrings in meiner DB
...so scheiden sich die Geister. :P Ich mag NULL Werte in der Datenbank nicht. Für mich ist ein Datensatz eine "Einheit" ... und da gibt es keine "Null = Wert nicht bekannt" Felder. Ein Feld hat einen Wert, und wenn es '' ist. Zum Anderen hat man auch die Kontrolle, ob der Datensatz auch komplett geschrieben wurde. :wink:

mkinzler 13. Sep 2019 07:47

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von MyRealName (Beitrag 1445965)
Man kann das Feld in Firebird ja auch mit einem Default belegen, der dann ein Leerstring ist.

Das wäre dann geanu das Gegenteil von dem, was der TE will.

(Betreff des Threads ist etwas missverständlich)

Int3g3r 3. Okt 2019 09:42

AW: IBDAC Leerstring statt Null. Alternativen?
 
Ich versuche nun gerade auf der Datenbankseite dies zu realisieren.
Mir ist folgendes Beispiel zu umständlich, ich möchte nicht jedes Feld manuell im Trigger eintragen müssen:

SQL-Code:
SET TERM ^^ ;
CREATE TRIGGER <TABELLE>_BI FOR <TABELLE> ACTIVE BEFORE INSERT or UPDATE POSITION 0 AS
begin
  if ( new.<Feld> = '') then new.<Feld> = NULL;
end ^^
SET TERM ; ^^
Momentan habe ich im IBExpert einen "Parsing Error" den ich nicht weg bekomme.
Ich möchte das er automatisch die Felder der Tabelle holt und alle kontrolliert:

SQL-Code:
CREATE OR ALTER trigger "_TBTEST_BI0" for "_TBTEST"
active before insert position 0
AS
    declare variable field_name varchar(255);
begin
    for select rdb$field_name from rdb$relation_fields where rdb$relation_name=upper('_TBTEST') into :field_name
  do
  begin
    if (new.:field_name = '') then new.:field_name = NULL; --new.:field_name (Parsing error!)
  end
end
Gruss Int3g3r

dataspider 4. Okt 2019 08:02

AW: IBDAC: In der DB sind Leerstrings statt Null. Alternativen?
 
Der Doppelpunkt ist nicht so universell einsetzbar wie sich das mancher wünscht.
Der ist halt für Parameter - nicht zum Basteln eines Statements.

Du kannst IMO nur eine SP (als Beispiel: sp_check_emty_strings) schreiben, welche als Parameter den Tabellenname und den PrimaryKey-Wert bekommt.
In des SP baust du das Statement als string und führst das Statement mit execute statement ... aus.

In der Tabelle benötigst du dann einen AFTER INSERT OR UPDATE Trigger.

Im Trigger steht dann nur noch: execute procedure sp_check_emty_strings('TABELLENNAME', new.id)

Frank

jobo 4. Okt 2019 08:38

AW: IBDAC: In der DB sind Leerstrings statt Null. Alternativen?
 
Also, ich weiß nicht, ob es eine gute Idee ist, einen solchen generalisierten Trigger so einzusetzen.

Dynamisch alle Felder auf Null abzuklappern bedeutet in der Praxis:
- ignorieren von Key field Definitionen?
- schlechtere Performance
- Intransparenz

Die Verwendung optionaler Fremdschlüssel oder auch die Verwendung von PK und nicht optionalen FK erfolgt auf Basis allgemein verwendeter und notwendiger Vorgehen bei Modelierung und Datenverarbeitnug. NULL/ Not NULL ist fester Bestandteil im Umgabng mit Schlüsselfeldern und Fremdschlüsseln. Das sollte man nicht überformen.
Jedes Insert oder Update muss die Felder aus dem Dictionary auslesen, darüber loopen und mit den Eingangsdaten abgleichen. Das kostet Zeit.
Insertanweisungen werden intransparent "verbogen". Das ist mit Triggern leider immer so und man sieht es einem Tabellenfeld nicht an.

Wenn man sowas trotzdem machen möchte, wäre es vielleicht sinnvoller, statische Trigger herzunehmen, deren Code man meinetwegen anhand des Models generiert. Hier würde man gezielt alle Keyfields ausnehmen und auch alle Zahlenfelder, sowie alle not null Felder.
Außerdem könnte man Constraints einsetzen, die Leerstrings als Inhalt verbieten.

Frickler 7. Okt 2019 11:25

AW: IBDAC Leerstring statt Null. Alternativen?
 
Zitat:

Zitat von haentschman (Beitrag 1445966)
Moin...8-)
Zitat:

Ich möchte keine Leerstrings in meiner DB
...so scheiden sich die Geister. :P Ich mag NULL Werte in der Datenbank nicht. Für mich ist ein Datensatz eine "Einheit" ... und da gibt es keine "Null = Wert nicht bekannt" Felder. Ein Feld hat einen Wert, und wenn es '' ist. Zum Anderen hat man auch die Kontrolle, ob der Datensatz auch komplett geschrieben wurde. :wink:

Trotzdem muss man immer mit NULL rechnen. Jeder JOIN der kein INNER ist, kann NULL-Werte produzieren. Beispielsweise als Ergebnis eines Views oder einer Selectable Stored Procedure, das im Programm dann wie ein "Datensatz" aussieht - mit NULL-Werten drin.

Btw. Für
Code:
IF (feld = '') feld = NULL;
gibt es eine eigene Anweisung
Code:
feld = NULLIF(feld, '');
Ist quasi das Gegenstück zu COALESCE.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz