AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

Ein Thema von berens · begonnen am 22. Mai 2020 · letzter Beitrag vom 27. Mai 2020
Antwort Antwort
Seite 1 von 2  1 2   
berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#1

MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 17:11
Datenbank: MS Access • Version: 2016 • Zugriff über: TAdoConnection
Hallo zusammen,
ich habe ein Problem mit einer Abfrage in meiner Anwendung. Ich konnte es soweit eingrenzen, dass das Problem nicht innerhalb von meinem Programm oder Delphi besteht, sondern alleine in der MS-Datenbank (.mdb), die wir verwenden [müssen]:

Ich benötige alle Zeilen einer Tabelle, bei denen [der String in] MyField leer ist. MyField ist ein String, hier konkret in dieser .mdb-Datei ein "Kurzer Text" (via SQ-Statement VARCHAR(255) angelegt). Der Standardwert soll leer sein, also "".

Über die SuFu hier im Forum konnte ich schon ermitteln, dass es für eine vergleichbare Abfrage ein riesen Unterschied ist, ob ein Feld den "Systemwert" NULL gespeichert hat, oder den leeren String "". Eine Abfrage, für Zeilen in denen bei MyField kein sichtbarer Text drinnen steht, scheint also nicht so ganz trivial.

Theoretisch müsste diese Abfrage immer die richtigen Werte liefern:
Code:
SELECT *
FROM Tabelle1
WHERE (((Myfield) Is Null)) or (MyField="");
Aber Access verhält sich heute sehr merkwürdig und ich traue dem Braten nicht. Auch besteht natürlich die Gefahr, dass dieser Filter an mehreren Stellen im Quelltext benötigt wird, und bei komplexen Ausdrücken nun doch irgendwas schief läuft, wenn ich da einfach die alte Abfrage MyField <> "" durch die o.g. ersetze...

Für vergleichbare Fälle lasse ich beim Programmstart eine Logikprüfung über meine Tabellen laufen (z.B. dass eine Warnmeldung ausgegeben wird, sollte der Zeitpunkt für das Ende ein Termins einmal vor dem Startzeitpunkt liegen etc.), wo ich nun auch gerne alle Einträge mit NULL in MyField auf "" setzen würde (=leeren String, aber halt nicht NULL).

Meine Abfrage dafür lautet.
Code:
UPDATE Tabelle1 SET MyField = ""
WHERE (MyField Is Null);
Diese habe ich zu Testzwecken in Access direkt ausgeführt und keine Fehlermeldung erhalten.
Leider gibt die Abfrage
Code:
SELECT *
FROM Tabelle1
WHERE (Myfield Is Null)
nun immer noch Datensätze zurück, die vorherige Änderungsabfrage war also scheinbar nicht erfolgreich.

Was mache ich falsch, was muss ich anders machen?

Kann ich evtl. die Einstellungen für die Spalte MyField (siehe Anhang) verändern, dass NULL automatisch als identisch mit "" interpretiert wird?
Scheinbar kann der Wert "Leere Zeichenfolge" angeben, ob eine leere Zeichenfolge gültig ist (Leerer String oder NULL???). Ich kann die verlinkte Dokumentation aber nicht soweit interpretieren, ob -wenn ich diesen Wert auf "Nein" stelle, dann alles NULL als "" interpretiert wird? Es gibt noch die Eigenschaft "Required" (Eingabe erforderlich), aber ich denke fast, diese Werte spielen nur innerhalb der Access-GUI eine Rolle?

Vielen Dank für Tips!
Miniaturansicht angehängter Grafiken
2020-05-22-16_57_31-window.png  
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
379 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 17:16
Kennt Access coalesce?

Dann wäre das eine Möglicghekit, dei Abfrage sicher auszuführen:

Code:
SELECT *
FROM Tabelle1
WHERE COALESCE(Myfield,'') ="";
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 17:21
Nope.

Zitat:
Undefinierte Funktion "COALESCE" in Ausdruck.
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
379 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 17:42
Hier wird NZ als Möglichkeit beschrieben:
https://www.techonthenet.com/access/...dvanced/nz.php

Dann müsste das so gehen:

Code:
SELECT *
FROM Tabelle1
WHERE Nz(Myfield,'') ="";
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.102 Beiträge
 
Delphi 12 Athens
 
#5

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 17:57
Sind im Access " und ' wirklich das Selbe?


Access hat aber nicht zufällig was drin, dass aus Leerstrings ein NULL macht, bzw. andersrum?

PS: In dem Bild steht bei Default/Standardwert was von "".
Aber eigentlich dachte ich der Default wird in allen DBMS nur dann verwendet, wenn man ein INSERT ausführt, und dabei dieses Feld nicht übergibt.

In PgDAC gibt es z.B. eine Option, die sowas bei einem Post macht. (zwar werden hier nur im DataSet die TField im BeforePost auf NULL gesetzt und nicht bei einem direkten UPDATE-Statement), aber vielleicht gibt es im Access sowas auch direkt in der Datenbank.



Bei Required/Erforderlich = True sollte jede explizite Zuweisung von NULL (und ein fehlendes DEFAULT beim INSERT) zu einer Fehlermeldung führen.
Wenn es nie NULL sein soll, wieso aktivierst du das dann nicht?
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (22. Mai 2020 um 18:03 Uhr)
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 19:07
Danke, @stifflersmom, das liefert [auch?] die Zeilen zurück, die NULL sind. Die Beschreibung auf der verlinkten Website ist schlüssig.
Code:
SELECT *
FROM Tabelle1
WHERE Nz(Myfield,'') ="";
Leider kann ich mit Access gerade keinen Eintrag erzeugen, der nur leeren Text drinnen hat, aber kein Null, aber ich hoffe einfach mal, wenn das NZ von vielen Leuten verwendet wird, dass es da auch zuverlässig arbeitet . Danke soweit.

@himitsu
> In dem Bild steht bei Default/Standardwert was von "".
Ja, das hat mich auch gewundert. Natürlich steht in meinem Quelltext:
q.SQL.Add('ALTER TABLE Tabelle1 ADD Myfield VARCHAR(255) DEFAULT "";'); Aber dass der das soooo wörtlich nimmt...
Es kann natürlich auch sein, dass die Zeilen bei/nach der Anpassung der Tabelle einmalig einen "leeren String" haben (z.B. \#0 oder wie auch immer das Zeichen dafür ist), und beim Abspeichern durch mein Programm, wenn der Wert "" dann über eine interne Routine den o.g. \#0 bekommen oder so.

> Wenn es nie NULL sein soll, wieso aktivierst du das dann nicht?
Eine fachlich richtige Antwort kann ich die hierfür nicht geben, dafür weiß ich, das Du ein x-Mal besserer Programmierer bist als ich; hast mir ja schon oft genug geholfen. Es gibt hier nur die "ehrliche" Antwort: aus Faulheit UND Unwissenheit. Long story short, bevor ich hier zu weit abdrifte: Ich habe mehrere Module die Einträge in dieser "Tabelle1" anlegen können. Diese sind nicht miteinander verkoppelt - was auch so bleiben soll(te). Wenn Modul1 -was den Wert "MyField" nicht kennt- nun eine Zeile schreibt, und NULL nicht mehr zugelassen ist, gibt es -denke ich mal- beim Post 'ne Exception. Modul1 kennt aber das Feld nicht. Ich müsste alle Module anpassen um (zusätzlich) ein Feld zu initialisieren, was in diesen Modulen 0% Relevanz hat. Mir als Mensch ist das echt sowas von egal ob da NULL oder "" drin steht, nur die Abfrage muss mir zuverlässig zurückgeben "ob da in dem Feld menschenlesbare Zeichen drinen sind, oder nicht". Hier ist die angepasste Abfrage von @stifflersmom einfacher an 7-8 Stellen einzupflegen, als in jedem Modul -imo "unnötigerweise"- das Feld "MyField" jedes Mal mit abspeichern zu lassen, NUR damit es keine Exception gibt. Natürlich wäre dein vorgeschlagenes Verfahren das Richtige - ToDo-Liste und Terminierungen sagen aber: geht nicht, nicht die "einfache" Lösung. Nicht professionell, aber ich kann mich leider nicht verreißen... Und ja: da muss von Grund auf eine andere Struktur rein. Stichwort: Historisch gewachsen.

Ich hoffe, dass die NZ Funktion alles perfekt abdeckt, ich denke, damit komme ich für den Moment ausreichend weiter.
Vielen Dank allen Antwortern , Thema beendet.
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.102 Beiträge
 
Delphi 12 Athens
 
#7

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 19:56
SQL-Code:
CREATE TABLE mytable (
  field1 VARCHAR(255),
  field2 VARCHAR(255) DEFAULT '',
  field3 VARCHAR(255) NOT NULL,
  field4 VARCHAR(255) NOT NULL DEFAULT ''
);

-- fehlt field3/4, dann wird dort der DEFAULT genommen
-- field3 muß also immer übergeben werden, da es keinen DEFAULT hat und somit einen Wert benötigt
INSERT INTO mytable (field1, field3) VALUES ...;

-- hier müssen alle Felder übergeben werden und bei field3/4 dürfen keine NULL drin stehen
INSERT INTO mytable VALUES ...;

-- bei einigen DBMS kann man im INSERT und UPDATE auch "DEFAULT" angeben, selbst wenn das Feld angegeben wird
-- bei field4 ein NULL zu übergeben knallt natürlich
INSERT INTO mytable (field3, field4) VALUES ('aa', DEFAULT);

-- hier in einem Dataset.Insert, werden field2/3 niemals übergeben (fehlen im automatisch generierten INSERT und UPDATE)
-- die field1 und field4 werden nach einem Dataset.Insert nur übergeben, wenn dort etwas eingetragen wurde (siehe fehlen dann also auch und bekommen ihren DEFAULT, wenn vorhanden)
-- bei field3 wird es also knallen, da es NOT NULL ist und keinen DEFAULT hat
-- field4 wird beim Dataset.Insert nicht knallen, da es im automatischen INSERT fehlt, wenn dort nichts zugewiesen wurde, und somit der DEFUALT benutzt wird
-- aber wird beim Dataset.Edit (UPDATE) das field4 auf NULL gesetzt (und vorher war es nicht NULL), dann knallt das natürlich auch
SELECT field1, field4 FROM mytable;
Wer ein Feld mit NUL NULL mit DEFAULT nicht kennt, dem ist das also im Normalfall egal.

ABER, wenn hier SELECT * verwendet wird und das Dataset auf die TField.Requiered (NOT NULL) reagiert (dieses Required von der DB füllen lässt),
dann gibt es ein Problem, denn auf den DEFAULT reagieren viele DB-Komponenten nicht (weil sie es nicht kennen und nicht wissen, dass es zwar Required ist, aber spätestens in der DB doch einen Wert bekommen kann).
Ebenso ist es mit NOT NULL, wo der Wert im Trigger gefüllt wird. TDataSet weiß nichts davon und reagiert entsprechend auf das Requiered.
Bei uns wird aus Diesem und einem anderen Grund im Dataset.AfterInsert der DEFAULT-Wert aus der DB abgerufen und eingefügt.
* einmal gibt es dann nach DataSet.Insert beim Post keine Fehlermeldung "Feld muß gefüllt sein"
* und der Benutzer sieht auch sofort, wo bereits Default-Daten vorhanden sind, die ja sonst eigentlich erstmal leer sind und erst beim Speichern (Post) von der Datenbank gefüllt werden.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (22. Mai 2020 um 20:21 Uhr)
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 22. Mai 2020, 20:14
Dass "NOT NULL" mit "DEFAULT ''" kombiniert werden kann, war jetzt zu offensichtlich (Wald und Bäume und so ...). Das löst natürlich alle Probleme. Ich muss jetzt natürlich nochmal irgendwie mit "ALTER TABLE" die bestehenden Datenbanken/Tabellen der Kunden zu aktualisieren.
field4 VARCHAR(255) NOT NULL DEFAULT '' Danke nochmal.
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.491 Beiträge
 
Delphi 7 Professional
 
#9

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 23. Mai 2020, 10:20
Alter table ändert aber keine vorhandenen Werte. Ein nachträgliches per Alter Table ergänztes Default '' führt nicht dazu, dass bis dahin mit NULL gefüllte Werte nun den Defaultwert erhalten. Hier musst Du ggfls. nochmal per Update "hinterhergehen".
  Mit Zitat antworten Zitat
DasWolf

Registriert seit: 7. Jun 2016
76 Beiträge
 
Delphi 10.1 Berlin Professional
 
#10

AW: MS-Access 2016: VARCHAR mit Inhalt "" oder NULL

  Alt 25. Mai 2020, 12:57
Dass "NOT NULL" mit "DEFAULT ''" kombiniert werden kann, war jetzt zu offensichtlich (Wald und Bäume und so ...). Das löst natürlich alle Probleme. Ich muss jetzt natürlich nochmal irgendwie mit "ALTER TABLE" die bestehenden Datenbanken/Tabellen der Kunden zu aktualisieren.
field4 VARCHAR(255) NOT NULL DEFAULT '' Danke nochmal.
Das ist ein absolutes No-Go!
Felder, die kein Primary-Key oder dergleichen sind, werden nicht über die Datenbank als NOT NULL definiert. Das wird über die Software geregelt.
Diesen Fehler habe ich einmal gemacht. Seitdem nie wieder.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:27 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