Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   NULL Werte aus mySQL pro Feld entfernen (https://www.delphipraxis.net/160824-null-werte-aus-mysql-pro-feld-entfernen.html)

Joerginger 2. Jun 2011 13:56

Datenbank: mySQL • Version: 5.5 • Zugriff über: zu Fuss (Tutorial)

NULL Werte aus mySQL pro Feld entfernen
 
Hallo liebe mySQL / SQL Gurus,

ich hab einige Entwicklungen "draussen", die ich gerne von MS-SQL zu mySQL portieren würde. Man könnte fast sagen: Portieren muss... Mit dem DP-Tutorial zu mySQL ohne Controls habe ich mich so halbwegs angefreundet, da ich allerdings nicht gerade das große Licht des SQL bin scheitere ich bereits an einem relativ trivialen Problem:

Wenn ich auf die DB zugreife bekomme ich (logo) einen Satz mit vielen Feldern retour, welche bis auf wenige Ausnahmen natürlich auch NULL als Inhalt haben können. Ich denke dabei alleine schon mal an jede winzige Artikeldatei wo nicht in 10 VK-Preisen der Wert 0, sondern eben NULL drinsteht. Wenn ich jetzt (ohne vorher zu wissen, ob ein Wert oder eben NULL drinsteht) eine Typumwandlung versuche krachts... (Klar, könnte man mit try-except vielleicht sogar lösen...)

Anyway: bei M$-SQL habe ich (für jedes!!! Feld) ungefähr folgende Syntax einfließen lassen, um 100% eine Exception zu vermeiden, nämlich
Code:
if Not(varIsNull(dsADR.FieldValues['ADR_NAME1'])) then Form1.lstADR.Cells[1,iNR]:=dsADR.FieldValues['ADR_NAME1'];
if Not(varIsNull(dsADR.FieldValues['ADR_NAME2'])) then Form1.lstADR.Cells[2,iNR]:=dsADR.FieldValues['ADR_NAME2'];
if Not(varIsNull(dsADR.FieldValues['ADR_PLZ'])) then Form1.lstADR.Cells[3,iNR]:=dsADR.FieldValues['ADR_PLZ'];
mittels "if Not (varIsNull)" zu prüfen ob ein Wert drinsteht... Das klappt hervorragend. Zumindest in MS-SQL.

Mit mySQL habe ich (laut Tutorial von DP)
Code:
Exies[i].name1:=_myRow[1]; //NAME1
Exies[i].name2:=_myRow[2]; //NAME2
folgende Zuweisungen gebastelt, ok, hier zum Testen nur in ein Array hinein. Sobald ich aber ein Feld erwische - und derer gibt's Viele - die eben NULL behinhalten geht der Jammer los.

Mein erster Versuch wäre gewesen, das gleich wie im MS-SQL zu lösen
Code:
if not varIsNull(String(_myRow[3])) then Exies[i].birthday :=_myRow[3];          //GEBURTZELTAG
allerdings hängts da (scheinbar) daran, dass _myRow[3] - wie auch jedes andere Feld, das ich aus mySQL zurückbekomme - vom Typ PChar ist... jedenfalls: es kracht trotzdem. Die übliche "Zugriffsverletzung bei Adresse 0392814612348257812358"

Dann hab ich als Lösungsansatz gefunden, dass man unter mySQL IFNULL(FELD_NAME,'') sagen könnte... hm. Funktioniert zumindest

Jetzt meine eigentlichen Fragen:
- Wie gehe ich das am cleversten an? Ich meine, 100% dafür Sorge tragen dass alle Datensätze niemals irgendwo NULL in sich tragen kanns nich sein.
- Muss ich für jedes verwendete Feld im Select schon das erwähnte ISNULL(NAME,'') verwenden??? Sieht ja irgendwie nicht so dolle aus: SELECT IFNULL(ADR_NAME1,''''), IFNULL(ADR_NAME2,''''), ISNULL(ADR_STRASSE,'''')... Schreib das mal bei 30-50 Feldern :roll:
- ist das der "only way", muss ich mir da eine func schreiben die aus einem gegebenen Feldnamen das IFNULL(F_N,'''') bastelt und an's stringQUERY dranhängt???
- Oder gibts einen smooth-and-easy-Trick für meine Problemstellung?
- ist meine try-except-finally Idee möglicherweise doch nicht so blöde?

Bitte um Wortspenden/Codeschnipsel. Danke!

GLG, Mr. Joerginger

mkinzler 2. Jun 2011 14:04

AW: NULL Werte aus mySQL pro Feld entfernen
 
-Andere Komponenten verwenden
-DB-seitig Views verwenden

Joerginger 2. Jun 2011 14:13

AW: NULL Werte aus mySQL pro Feld entfernen
 
Herzlichen Dank für die rasche Antwort, leider bin ich - wie erwähnt - eher Anfänger und kenn mi jetzt erst recht nicht aus...

Was andere Komponenten sind ist mir klar, hast Du / hat jemand einen Tip Welche Komponenten ich da verwenden soll(te)?

Was um alles in der Welt (Newbie-Alarm!!!) sind "DB-seitig Views"?

GLG, Joerginger

mkinzler 2. Jun 2011 14:20

AW: NULL Werte aus mySQL pro Feld entfernen
 
Ein View ist eine Abfrage auf dem Server, auf dem man wie eine Tabelle zugreifen kann.

Komponenten gibt es Viele. Wie hast du auf MSSQL zugegriffen? ADO? Darf es etwas kosten?

Zeos, MyDAC, dbExpress, ...

Joerginger 2. Jun 2011 15:05

AW: NULL Werte aus mySQL pro Feld entfernen
 
Oh, danke für die Infos.

Meine Programmierphilosophie (und leider bin ich mit 46 Jahren schon seeeehr lange dabei) ist immer (noch): Was ich selber schreibe, kann ich auch selber korrigieren. MS-SQL greife ich via ADODB und DB zu, alles handgestrickt, keine Controls. ADOQUERY erzeugen, SQL-String absetzen, glücklich sein... Ich denke es ist zwar schwieriger als Klick Klick Programm fertig, aber eben auch wesentlich flexibler. Daher hab ich mich dann in das DP-Tutorial eingelesen "mySQL ohne Komponenten", dort greife ich dann auch über die mysql.pas direkt auf die DB zu, via libmysql.dll

Scheint mir sehr flott zu sein und wäre im Prinzip auch praktikabel. So exzessive G'schichten mach ich nicht. Bisschen Daten reinklopfen, Abfragen über 2,5 Millionen Adressen nach div. Kriterien. Oder in meiner Gastro-Lösung werden eben Zeilen mit Bestellungen und Abrechnungen gebucht.

Da MS-SQL bei 5 Usern in der Mini-Version sperrt, ich aber einige Kunden habe die zumindest 6-15 User benötigen... stehe ich vor der Entscheidung ob ich auf mySQL umsteige oder den Kunden (versuche) MS-SQL in "nicht gratis" umzuhängen...

Aber ich sehe grad wieder mal, dass ich um einen guten SQL-Kurs nicht herumkommen werde. Da fehlt mir einfach noch zu viel des Wissens...

GLG, Joerginger

mkinzler 2. Jun 2011 15:09

AW: NULL Werte aus mySQL pro Feld entfernen
 
Per ADO sollte der Zugriff auf MySQL auch möglich sein.

sx2008 2. Jun 2011 18:23

AW: NULL Werte aus mySQL pro Feld entfernen
 
Ich denke deinem Problem kann man mit einer supersimplen Funktion begegnen:
Delphi-Quellcode:
function Coalesce(Value:Variant; default:Variant):Variant;
begin
  if VarIsNull(Value) then
    result := default
  else
    result := Value;
end;
Damit kann du nun so arbeiten:
Delphi-Quellcode:
Exies[i].name1:= Coalesce(_myRow[1], ''); //NAME1
Exies[i].name2:= Coalesce(_myRow[2], ''); //NAME2 
Exies[i].Preis:= Coalesce(_myRow[3], 0.0); //VK Preis
Exies[i].Flag:= Coalesce(_myRow[4], False); //boolean Flag

mkinzler 2. Jun 2011 18:28

AW: NULL Werte aus mySQL pro Feld entfernen
 
Wenn ich richtig verstanden habe, knallt es aber schon beim Zugriff auf
Delphi-Quellcode:
_myRow[<index>]

omata 2. Jun 2011 18:32

AW: NULL Werte aus mySQL pro Feld entfernen
 
Zitat:

Zitat von Joerginger (Beitrag 1104322)
Da MS-SQL bei 5 Usern in der Mini-Version sperrt, ich aber einige Kunden habe die zumindest 6-15 User benötigen... stehe ich vor der Entscheidung ob ich auf mySQL umsteige...

Wenn schon Umstieg, warum nicht auf Firebird oder PostgreSQL? Mit MySQL handelst du dir da nur die Lizenzproblematik ein. Gerade wenn es um Geld geht -> Firebird oder PostgreSQL.

Joerginger 2. Jun 2011 18:42

AW: NULL Werte aus mySQL pro Feld entfernen
 
sx2008's Idee wäre durchaus gut, aber wie mkinzler schon richtig bemerkt hat, pfeffert es das Programm sofort auf, wenn ich versuche _myRow[<Index>] in irgendeiner Form abzufragen oder umzuwandeln, dieweil's vom Typ her PChar ist :shock: (Für die Lesbarkeit meines Codes ist's allerdings ein Segen, diese Prüfung als eigene function auszuführen und aufzurufen...)

@omata: hat natürlich auch andere Gründe, warum ich mySQL präferiere. Z.B: Du kannst eine NAS (von QNAP) hernehmen und schwupps, mySQL läuft drauf. Und auch 2 oder 3 Systeme, die ich zur Wartung übernehmen werde (darunter auch ein Ärztepaket / Ordiverwaltung) hat als Basis mySQL... Inwiefern meinst Du "wenn es um's Geld geht"???

Prinzipiell gefällt mir ja der Zugriff ohne Komponenten total gut und (sogar über's Netzwerk) geht das Teil extrem flott, mit genau einer solch erwähnten NAS :-D

GLG, Mr. Joerginger

sx2008 2. Jun 2011 18:45

AW: NULL Werte aus mySQL pro Feld entfernen
 
Zitat:

Zitat von mkinzler (Beitrag 1104331)
Wenn ich richtig verstanden habe, knallt es aber schon beim Zugriff auf
Delphi-Quellcode:
_myRow[<index>]

Stellt sich die Frage, welcher Datentyp steckt hinter
Delphi-Quellcode:
_myRow[<index>]
.
Ist das etwa wirklich ein PChar?
Und ist _myRow[<index>] = nil wenn das angesprochene Feld den Inhalt NULL hat?

Und warum muss man wirklich auf alles verzichten, was Delphi so einfach und genial macht?

PS: ich würde so ein "Ärztepaket" 5 mal schneller programmieren, einfach dadurch dass ich alles verwende
was mir Delphi zur Verfügung stellt.

mkinzler 2. Jun 2011 18:53

AW: NULL Werte aus mySQL pro Feld entfernen
 
Er spielt darauf an, dass MySQL beim kommerzeillen Einsatz nicht gerade wenig kostet. Die freie Version gibt es nur für OpenSource-Projekte.

Joerginger 2. Jun 2011 19:54

AW: NULL Werte aus mySQL pro Feld entfernen
 
Nö, myRow[<Index>] liefert $11305819 (schlagmichtot), zeigt also auf Nonsens...

Und btw: ich hab mal ein Ärztepaket (begonnen) zu entwickeln, da kommst Du niemals nicht nach... Da ist so viel zu tun, und was am allerschlimmsten ist: Du musst den Topfen mit der Abrechnung von der Krankenkasse prüfen lassen.

Btw: Es gibt scheints genau NULL Möglichkeiten, den PChar zu Variant zu machen (bzw. den Inhalt wo der Teifl hinzeigt...). Ich mutmaße jetzt mal: wenn ich alle Felder einer Tabelle mit mehr Feldern mit ISNULL(FN,'''') zusammenstellen lasse wird's wohl doch irgendwann auf die Performance des mySQL gehen :?:

Allerdings war ich der (scheint's irrigen) Meinung, dass die DB mySQL gratis verwendet werden darf :roll::shock:

GLG, Mr. Joerginger

mkinzler 2. Jun 2011 20:08

AW: NULL Werte aus mySQL pro Feld entfernen
 
Nein darfst du nicht. Und Oracle versteht da auch keinen Spass.

Sir Rufo 2. Jun 2011 20:09

AW: NULL Werte aus mySQL pro Feld entfernen
 
Die DB darf auch wohl gratis verwendet werden, aber die Benutzung der libmysql.DLL verursacht entweder Lizenzkosten oder zwingt dich zu OpenSource

Somit wäre der Griff zu nativen Komponenten (z.B. MyDAC, UniDAC) die ohne diese DLL auskommen angeraten.

mkinzler 2. Jun 2011 20:17

AW: NULL Werte aus mySQL pro Feld entfernen
 
Oder halt ein anderes DBMS

jobo 2. Jun 2011 20:28

AW: NULL Werte aus mySQL pro Feld entfernen
 
Zitat:

Zitat von mkinzler (Beitrag 1104347)
Nein darfst du nicht. Und Oracle versteht da auch keinen Spass.

Ich war etwas verwirrt, aber ich gewöhn mich noch dran mySQL ist ja seit einiger Zeit von Oracle.

Alternativ könnte man ja Oracle von Oracle nehmen. :)
Gibt's in der Expressedition geschenkt. Ich hab's aber noch nie benutzt, demnächst soll die 11er Express Edition kommen. (Warum jetzt erst, weiß ich nicht)
Die 10er ist angeblich ohne nennenswerte funktionale Einschränkungen, außer
Limit 1 CPU, 4GB Userdaten, 1 DB pro Maschine, Support nur via Forum, nur mit Registrierung,
Private oder kommerzielle Verwendung ist egal.
http://www.oracle.com/technetwork/da...iew/index.html

mkinzler 2. Jun 2011 20:33

AW: NULL Werte aus mySQL pro Feld entfernen
 
Oder die hier schon genannten freien DBMS

Sir Rufo 2. Jun 2011 20:39

AW: NULL Werte aus mySQL pro Feld entfernen
 
Zitat:

Zitat von mkinzler (Beitrag 1104351)
Oder die hier schon genannten freien DBMS

Er übernimmt aber zusätzlich noch Anwendungen die auf MySQL basieren ... Somit bleibt ihm da wohl keine Wahl

Jumpy 3. Jun 2011 07:42

AW: NULL Werte aus mySQL pro Feld entfernen
 
Kann man die Null-Felder nicht schon in der Query mit dem richtigen SQL-Statement abfangen? In Oracle gibts doch da sowas wie NVL, vllt. hats vergleichbares ja auch in MySQL?

mkinzler 3. Jun 2011 07:45

AW: NULL Werte aus mySQL pro Feld entfernen
 
Gibt es schon, will er aber umgehen ( siehe Ursprungsfrage)

Sir Rufo 3. Jun 2011 09:43

AW: NULL Werte aus mySQL pro Feld entfernen
 
Um jetzt mal auf den Ursprungsthread zu antworten :)
Zitat:

Zitat von Joerginger (Beitrag 1104297)
Jetzt meine eigentlichen Fragen:
- Wie gehe ich das am cleversten an? Ich meine, 100% dafür Sorge tragen dass alle Datensätze niemals irgendwo NULL in sich tragen kanns nich sein.

Nee, ist auch doof, vor allem weil es eine Weitere Information beinhaltet -> Es liegen keine Daten vor
Ist das absolut unerwünscht, dann eben NULL-Werte in der Tabelle verbieten
Zitat:

Zitat von Joerginger (Beitrag 1104297)
- Muss ich für jedes verwendete Feld im Select schon das erwähnte ISNULL(NAME,'') verwenden??? Sieht ja irgendwie nicht so dolle aus: SELECT IFNULL(ADR_NAME1,''''), IFNULL(ADR_NAME2,''''), ISNULL(ADR_STRASSE,'''')... Schreib das mal bei 30-50 Feldern :roll:


Zitat:

Zitat von Joerginger (Beitrag 1104297)
- ist das der "only way", muss ich mir da eine func schreiben die aus einem gegebenen Feldnamen das IFNULL(F_N,'''') bastelt und an's stringQUERY dranhängt???


Zitat:

Zitat von Joerginger (Beitrag 1104297)
- Oder gibts einen smooth-and-easy-Trick für meine Problemstellung?

Ja
Zitat:

Zitat von Joerginger (Beitrag 1104297)
- ist meine try-except-finally Idee möglicherweise doch nicht so blöde?

ähhm, die geht schon mal gar nicht ... Except (übers. Ausnahme) und sollte auch nur für Ausnahmen verwendet werden und nicht für den Regelbetrieb.

Aus den hier schon genannten Lizenzgründen würde ich an deiner Stelle Zugriffs-Komponenten verwenden, die ohne die libmysql.dll auskommen.

Weiterhin würde ich für die Darstellung der Werte eine generalisierte procedures schreiben ala
Delphi-Quellcode:
function FieldToStr( Field : TField ) : string;
begin
  if Assigned( Field ) then
    begin
      if VarIsNull( Field.Value ) then
        Result := '' // auch möglich Result := '(null)'
      else
        case Field.FieldType of
          ftInteger : Result :=
        end;
    end
  else
    Result := '';
end;

procedure DataSetShowInListView( DataSet : TDataSet; ListView : TListView; FieldList : array of string );
var
  idx : integer;
  valstr : string;
begin
  for idx := Low( FieldList ) to High( FieldList ) do
    begin
      valstr := FieldToStr( DataSet.FindField( FieldList[ idx ] ) );
      ...
    end;
end;
Ich würde aber in den meisten Fällen ein DBGrid (gut persönlich benutze ich ein cxGrid :wink:) für die Anzeige bemühen, denn da braucht es dieses Geraffel nicht.

Weiterhin kann man sich auch Objekte anlegen, wo diese Daten enthalten sind und dann an die Liste übergeben (ORM).
Das Objekt selber kümmert sich dann um die richtige Umwandlung der Daten
Delphi-Quellcode:
type
  TAdresse = class
  private
    FVorname : Variant;
    function GetVorname : string;
    procedure SetVorname( const Value : string );
    procedure SetRawVorname( const Value : Variant );
  public
    property Vorname : string read GetVorname write SetVorname;
    property RawVorname : Variant read FVorname write SetRawVorname;
  end;


function TAdresse.GetVorname : string;
begin
  Result := VarToStrDef( FVorname, '' );
end;
 
procedure TAdresse.SetVorname( const Value : string );
begin
  FVorname := Value;
end;
 
procedure TAdresse.SetRawVorname( const Value : Variant );
begin
  FVorname := Value;
end;

p80286 3. Jun 2011 10:34

AW: NULL Werte aus mySQL pro Feld entfernen
 
Zitat:

Zitat von Joerginger (Beitrag 1104297)
Jetzt meine eigentlichen Fragen:
- Wie gehe ich das am cleversten an? Ich meine, 100% dafür Sorge tragen dass alle Datensätze niemals irgendwo NULL in sich tragen kanns nich sein.

Wie wäre es, das gleich bei der Tabellendefinition zu erschlagen?
Create Table (
IDKEY NUMBER ( 38 ) NOT NULL,
Wert1 CHAR (1) DEFAULT '0' ,
Wert2 NUMBER (5,2) DEFAULT '0',
....)

Ausserdem wie schon oben erwähnt NULL ist nicht Null sondern Nix!
Wenn man das in Seinen Abfragen berücksichtigt ist diese Info sehr wertvoll.

Gruß
K-H

Joerginger 3. Jun 2011 22:40

AW: NULL Werte aus mySQL pro Feld entfernen
 
Ich bedank' mich an dieser Stelle mal für die vielen wertvollen Informationen!

Vor allem die Hinweise auf die Lizenzkosten waren wichtig, weil ich mySQL (scheinbar fälschlicherweise) für eine "Gratis-Datenbank" gehalten hätt'. Ich frage mich nur: ob das wohl alle Entwickler wissen und berücksichtigen???

Weiters nehme ich Sir Rufo's Codeschnipsel gerne mit, habe mir ferner - auch zwecks Testen - die myDAC Komponenten besorgt... Und die beiden erwähnten DBMS's...

GLG, Mr. Joerginger


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