*Markus: (MySQL) Obwohl Feld NOT NULL, einfügen möglich?

Hallo,

ich weiß nicht, ob ich eine falsche Vorstellung von NOT NULL habe, aber wenn ich in folgedner Tabelle...

+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| kdnr         | int(11)      | NO   | PRI | NULL    | auto_increment |
| b_id         | int(11)      | NO   | MUL | NULL    |                |
| status_id    | int(11)      | NO   | MUL | NULL    |                |
| plz          | int(11)      | NO   | MUL | NULL    |                |
| kundenname   | varchar(100) | NO   |     | NULL    |                |
| betriebsname | varchar(100) | YES  |     | NULL    |                |
| k_strasse    | varchar(100) | NO   |     | NULL    |                |
| k_telefon    | varchar(20)  | YES  |     | NULL    |                |
| k_email      | varchar(70)  | YES  |     | NULL    |                |
| k_fax        | varchar(30)  | YES  |     | NULL    |                |
| k_website    | varchar(200) | YES  |     | NULL    |                |
| k_checksum   | varchar(255) | NO   |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+

...einen Datensatz einfüge, indem k_checksum absichtlich nicht vorkommt, kann dieser Datensatz trotzdem gespeichert werden? Wieso?

Beipspiel:

  
INSERT INTO Kunde (b_id, status_id, plz, kundenname, betriebsname, k_strasse, k_telefon, k_email, k_fax, k_website)  
VALUES (1, 1, '1200', 'Thomas Müller', 'Müller GmbH', 'Hauptplatz', '23455353545','thomas@pinvalid.invalid', '1234356456','http://tester.invalid');  
  
führt zu...  
Query OK, 1 row affected, 1 warning (0.00 sec)  

Der Datensatz wird also eingefügt. Darüberhinaus frage ich mich, wo ich diese "warning" sehen kann?

Ein

tail /var/log/mysqld.log

ist leer.

Markus

  1. Hi!

    +--------------+--------------+------+-----+---------+----------------+
    | Field        | Type         | Null | Key | Default | Extra          |
    +--------------+--------------+------+-----+---------+----------------+
    | kdnr         | int(11)      | NO   | PRI | NULL    | auto_increment |

    Ein Feld, das keine NULL-Werte erlaubt kann kein NULL als Default-Wert haben. Diese Tabelle schwindelt.

    ...einen Datensatz einfüge, indem k_checksum absichtlich nicht vorkommt, kann dieser Datensatz trotzdem gespeichert werden? Wieso?

    Der Defaultwert der tatsächlich aktiv ist, wird eingefügt.

    Query OK, 1 row affected, 1 warning (0.00 sec)
    Der Datensatz wird also eingefügt. Darüberhinaus frage ich mich, wo ich diese "warning" sehen kann?

    SHOW WARNINGS wäre eine Möglichkeit.

    Lo!

    1. Hallo,

      +--------------+--------------+------+-----+---------+----------------+
      | Field        | Type         | Null | Key | Default | Extra          |
      +--------------+--------------+------+-----+---------+----------------+
      | kdnr         | int(11)      | NO   | PRI | NULL    | auto_increment |

      Ein Feld, das keine NULL-Werte erlaubt kann kein NULL als Default-Wert haben. Diese Tabelle schwindelt.

      Ich verstehe nicht, wie man Tabellen sonst anlegen soll/kann. Bei create table habe ich mal alle NULL weggenommen, aber dennoch wird so eine gleichwertige Tabelle erzeugt:

        
      CREATE TABLE Kunde  
        
            (kdnr                  INTEGER NOT NULL AUTO_INCREMENT,  
        
             b_id                  INTEGER NOT NULL,  
        
             status_id             INTEGER NOT NULL,  
        
             plz                   INTEGER NOT NULL,  
        
             kundenname            VARCHAR(100) NOT NULL,  
        
             betriebsname          VARCHAR(100),  
        
             k_strasse             VARCHAR(100) NOT NULL,  
        
             k_telefon             VARCHAR(20),  
        
             k_email               VARCHAR(70),  
        
             k_fax                 VARCHAR(30),  
        
             k_website             VARCHAR(200),  
             k_checksum	     VARCHAR(255) NOT NULL,  
        
             PRIMARY KEY (kdnr)  
        
      ) ENGINE=INNODB;  
      
      

      ...einen Datensatz einfüge, indem k_checksum absichtlich nicht vorkommt, kann dieser Datensatz trotzdem gespeichert werden? Wieso?

      Der Defaultwert der tatsächlich aktiv ist, wird eingefügt.

      Da der Defaultwert ja NULL ist, wie kann er dann in ein Feld, das NOT NULL ist, eingefügt werden?

      Query OK, 1 row affected, 1 warning (0.00 sec)
      Der Datensatz wird also eingefügt. Darüberhinaus frage ich mich, wo ich diese "warning" sehen kann?

      SHOW WARNINGS wäre eine Möglichkeit.

      Ok, der Sinn der Meldung mit der o.g. create-table-Syntax ist mir auch nicht wirklich klar:

      +---------+------+-------------------------------------------------+
      | Level   | Code | Message                                         |
      +---------+------+-------------------------------------------------+
      | Warning | 1364 | Field 'k_checksum' doesn't have a default value |
      +---------+------+-------------------------------------------------+

      Somit ist die Verwirrung komplett. Ich habe angeblich keine Default-Values, diese werden jedoch bei "show fields" angezeigt und Datensätze darf ich darüberhinaus auch noch einfügen. Muss ich das jetzt verstehen? :)

      Markus

      1. Hi,

        Ich verstehe nicht, wie man Tabellen sonst anlegen soll/kann.

        Einen Default-Wert für eine Spalte kannst du in der column_definition mit dem Schlüsselwort DEFAULT gefolgt vom gewünschten Default-Wert angeben, aber -

        kundenname            VARCHAR(100) NOT NULL,

        • an dieser Stelle wirst du damit wohl auch kein Glück haben, denn

        Some attributes do not apply to all data types. [...] DEFAULT does not apply to the BLOB or TEXT types.

        • und da dürfte VARCHAR wohl auch drunter fallen.

        Ok, der Sinn der Meldung mit der o.g. create-table-Syntax ist mir auch nicht wirklich klar:

        +---------+------+-------------------------------------------------+
        | Level   | Code | Message                                         |
        +---------+------+-------------------------------------------------+
        | Warning | 1364 | Field 'k_checksum' doesn't have a default value |
        +---------+------+-------------------------------------------------+

        Da das bei dir VARCHAR ist, bin ich jetzt auch verwirrt. Sollte MySQL VARCHAR doch nicht zu den TEXT-Typen zählen, so das obiges hier nicht zutrifft?

        Was passiert, wenn du mal einen Defaultwert mit DEFAULT explizit angibst?

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
        1. Hi!

          Some attributes do not apply to all data types. [...] DEFAULT does not apply to the BLOB or TEXT types.

          • und da dürfte VARCHAR wohl auch drunter fallen.

          Nein, unter TEXT fallen nur die Typen TINYTEXT, TEXT, MEDIUMTEXT und LONGTEXT.

          Lo!

      2. Hi!

        +--------------+--------------+------+-----+---------+----------------+
        | Field        | Type         | Null | Key | Default | Extra          |
        +--------------+--------------+------+-----+---------+----------------+
        | kdnr         | int(11)      | NO   | PRI | NULL    | auto_increment |

        Ein Feld, das keine NULL-Werte erlaubt kann kein NULL als Default-Wert haben. Diese Tabelle schwindelt.

        Ich verstehe nicht, wie man Tabellen sonst anlegen soll/kann. Bei create table habe ich mal alle NULL weggenommen, aber dennoch wird so eine gleichwertige Tabelle erzeugt:

        Hmm, die Ausgabe wird tatsächlich von SHOW COLUMNS so erzeugt. Man muss dann das NULL in der Default-Spalte vermutlich so interpretieren, dass kein Default-Wert festgelegt wurde. Es wird dann wohl ein typspezifischer Default-Wert verwendet, wobei ich dazu auf die Schnelle keine Auflistung fand.

        ...einen Datensatz einfüge, indem k_checksum absichtlich nicht vorkommt, kann dieser Datensatz trotzdem gespeichert werden? Wieso?
        Der Defaultwert der tatsächlich aktiv ist, wird eingefügt.
        Da der Defaultwert ja NULL ist, wie kann er dann in ein Feld, das NOT NULL ist, eingefügt werden?

        Er ist nicht gesetzt und evaluiert augenscheinlich zu einem Leerstring.

        Ok, der Sinn der Meldung mit der o.g. create-table-Syntax ist mir auch nicht wirklich klar:
        +---------+------+-------------------------------------------------+
        | Level   | Code | Message                                         |
        +---------+------+-------------------------------------------------+
        | Warning | 1364 | Field 'k_checksum' doesn't have a default value |
        +---------+------+-------------------------------------------------+

        Ah, sieh an. Es ist kein Default-Wert explizit angegeben worden. Wenn man das tut (DEFAULT ''), dann zeigt SHOW COLUMNS auch kein NULL mehr in der Spalte Default an.

        Lo!

        1. Hi,

          Es wird dann wohl ein typspezifischer Default-Wert verwendet, wobei ich dazu auf die Schnelle keine Auflistung fand.

          http://dev.mysql.com/doc/refman/5.1/en/data-type-defaults.html sagt unten ein bisschen was dazu.

          MfG ChrisB

          --
          “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
          1. Hi!

            Es wird dann wohl ein typspezifischer Default-Wert verwendet, wobei ich dazu auf die Schnelle keine Auflistung fand.
            http://dev.mysql.com/doc/refman/5.1/en/data-type-defaults.html sagt unten ein bisschen was dazu.

            Ah, danke, da hat es sich versteckt. Wie ich vermutete, Leerstring (alles andere hätte mich auch stark gewundert).

            Lo!

        2. Hallo,

          ok dann wird die Sache schon mal klarer.
          wenn ich mir die CREATE-TABLE-SYNTAX ansehe, kann man hierbei gar kein Default angeben, zumindest nur bei den Table-Options, aber das ist wohl nicht, was ich suche.

          Laut http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html wird ein Leerstring als Default Value bei VARCHAR gesetzt, wenn explizit kein Default Value angegeben wurde, was auch erklärt, warum das Einfügen ständig funktioniert.

          Die Frage ist nun wie ich das am besten erreichen kann, dass ich ein Feld beschreibe, dass unbedingt befüllt werden muss?

          Markus

          1. Hi,

            wenn ich mir die CREATE-TABLE-SYNTAX ansehe, kann man hierbei gar kein Default angeben

            Natürlich kann man.

            Die Eigenschaften der Spalten gibst du über
            col_name column_definition
            an - und der Aufbau von column_definition wird auf der Seite auch noch mal explizit aufgeschlüsselt.

            MfG ChrisB

            --
            “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
            1. Hi,

              wenn ich mir die CREATE-TABLE-SYNTAX ansehe, kann man hierbei gar kein Default angeben

              Natürlich kann man.

              Die Eigenschaften der Spalten gibst du über
              col_name column_definition
              an - und der Aufbau von column_definition wird auf der Seite auch noch mal explizit aufgeschlüsselt.

              Ok stimmt. Dann hätte ich ja ohnehin bereits die richtige Syntax verwendet bei meinen Tests, aber dennoch scheint das so nicht zu klappen:

                
                     k_checksum VARCHAR(255) NOT NULL DEFAULT NOT NULL  
              
              

              oder ....

                
                     k_checksum VARCHAR(255) NOT NULL DEFAULT NULL  
              
              

              oder...

                
                     k_checksum VARCHAR(255) DEFAULT NOT NULL  
              
              

              scheinen nicht zu klappen.
              Beim Anlegen der Tabellen schlägt MySQL auf, hmm?

              Markus

              1. Hi,

                scheinen nicht zu klappen.
                Beim Anlegen der Tabellen schlägt MySQL auf, hmm?

                OMFG!
                </hilfe/charta.htm#tipps-fuer-fragende>

                MfG ChrisB

                --
                “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
              2. Hi!

                Die Eigenschaften der Spalten gibst du über
                col_name column_definition
                an - und der Aufbau von column_definition wird auf der Seite auch noch mal explizit aufgeschlüsselt.

                Ok stimmt. Dann hätte ich ja ohnehin bereits die richtige Syntax verwendet bei meinen Tests, aber dennoch scheint das so nicht zu klappen:

                k_checksum VARCHAR(255) NOT NULL DEFAULT NOT NULL

                NOT NULL ist kein Wert. Eigentlich bedeutet es die Negation von NULL. Da aber in so gut wie allen Ausdrücken, in denen NULL als Parameter vorkommt, als Ergebnis NULL entsteht, hast du quasi den Wert NULL angegeben, der aber bei einem NOT_NULL-Feld nicht erlaubt ist.

                k_checksum VARCHAR(255) NOT NULL DEFAULT NULL
                       k_checksum VARCHAR(255) DEFAULT NOT NULL
                Beim Anlegen der Tabellen schlägt MySQL auf, hmm?

                Es als Syntaxfehler abzulehnen ist auch eine Variante, denn als Default-Wert ist nur ein einzelner Wert und kaum ein Ausdruck sinnvoll.

                Was willst du eigentlich erreichen?

                Lo!

                1. Hallo,

                  Was willst du eigentlich erreichen?

                  Im Prinzip will ich, dass kein Datensatz gespeichert werden darf, wenn k_checksum keinen Wert hat, d.h. NULL ist. Ich dachte, dass dies mit NOT NULL so ohne weiteres möglich sein sollte.

                  Markus

                  1. Hi,

                    Im Prinzip will ich, dass kein Datensatz gespeichert werden darf, wenn k_checksum keinen Wert hat, d.h. NULL ist. Ich dachte, dass dies mit NOT NULL so ohne weiteres möglich sein sollte.

                    Übergibst du denn explizit NULL für die Spalte im INSERT-Statement?

                    Wenn nicht - http://dev.mysql.com/doc/refman/5.1/en/insert.html:

                    If you want an INSERT statement to generate an error unless you explicitly specify values for all columns that do not have a default value, you should use strict mode.

                    MfG ChrisB

                    --
                    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                    1. Hallo,

                      danke du hast recht. So klappt das gewünschte Verhalten:

                      ERROR 1364 (HY000) at line 11: Field 'k_checksum' doesn't have a default value

                      Problem ist somit gelöst.

                      Viele Grüße,
                      Markus

                  2. Hi!

                    Im Prinzip will ich, dass kein Datensatz gespeichert werden darf, wenn k_checksum keinen Wert hat, d.h. NULL ist. Ich dachte, dass dies mit NOT NULL so ohne weiteres möglich sein sollte.

                    Tja, geht so nicht. Wenn für ein Feld kein Wert in einem INSERT-Statement angegeben ist, dann wird der Default-Wert genommen, der ja seiner seinerseits Default-Werte je Feldtyp hat, wenn er beim Anlegen des Feldes nicht angegeben wurde. Es wird jedoch nicht versucht, NULL einzutragen und ein Default-Wert von NULL in einem NOT NULL-Feld wird nicht zugelasen. Wenn du allerdings explizit NULL einzutragen versuchst, dann wird das abgelehnt. Constraints, die anhand eines Ausdrucks den einzutragenden Wert prüfen, gibt es nicht und sind bis Version 6 auch nicht geplant.

                    Lo!

                    1. moin,

                      Tja, geht so nicht. Wenn für ein Feld kein Wert in einem INSERT-Statement angegeben ist, dann wird der Default-Wert genommen, der ja seiner seinerseits Default-Werte je Feldtyp hat, wenn er beim Anlegen des Feldes nicht angegeben wurde.

                      ist schon spät, aber da muss ich noch mal nachfragen. jeder datentyp bei mysql hat von hause aus einen default wert ? das wäre sehr unschön.....

                      Ilja

                      1. Hi,

                        ist schon spät, aber da muss ich noch mal nach
                        <del>fragen</del>

                        <ins>lesen</ins>

                        . jeder datentyp bei mysql hat von hause aus einen default wert ?

                        Nein, nicht jeder.

                        MfG ChrisB

                        --
                        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                      2. Hi!

                        ist schon spät, aber da muss ich noch mal nachfragen. jeder datentyp bei mysql hat von hause aus einen default wert ? das wäre sehr unschön.....

                        Das ist, wenn ich das richtig verstanden habe, einem Kompromiss geschuldet. Da MySQL abgesehen von der InnoDB-Engine keine Transaktionen bietet, über die man bei einem Fehler eine beispielsweise umfangreiche Einfügeaktion wieder komplett rückgängig machen könnte, wenn irgendwo in der Mitte was nicht gepasst hat, versucht MySQL den nächstgelegenen validen Wert zu finden und einzufügen. Ein überlanger String wird abgeschnitten, ein falsches Datum zu 0000-00-00, und so weiter. Es ist nicht die Aufgabe eines DBMS Eingabewerte zu validieren. Das muss die mit dem Endanwender agierenden Anwendung tun. Die zu speichernden Daten müssen nur plausibel gegenüber dem jeweiligen Feldtyp sein, wofür sie eben im Fehlerfall angepasst werden (in der Standardeinstellung).

                        Nun könntest du argumentieren: Scheiße gebaut, hätten sie mal gleich Transaktionen eingebaut - und hast das dabei aus deinem professionellen Auge betrachtet. - Jedoch, die Zielgruppe hatte und hat meist keine Transaktionen nötig und Geschwindigkeit auch auf geringer ausgestatteten Maschinen war und ist ein wichtigerer Punkt. Die Frage ist nun, was für den größten Teil der Zielgruppe wichtiger ist: absolute Strenge beim Einfügen gepaart mit Abbrüchen im Fehlerfall oder Anpassungen bei fehlerhaften Werten, dafür aber das Durchlaufen der Aktion. Seit Version 5.0.2 kann man sich das sogar selbst aussuchen (STRICT_TRANS_TABLES oder STRICT_ALL_TABLES).

                        Siehe How MySQL Deals with Constraints und das Unterkapitel Constraints on Invalid Data.

                        Lo!

                        1. yo,

                          Die Frage ist nun, was für den größten Teil der Zielgruppe wichtiger ist: absolute Strenge beim Einfügen gepaart mit Abbrüchen im Fehlerfall oder Anpassungen bei fehlerhaften Werten, dafür aber das Durchlaufen der Aktion.

                          aus meiner sicht der dinge würde ich eigentlich immer in richtung integere daten argumentieren. performance und andere eigenschaften sind wichtig. aber wenn wir nicht gerade von schätzwerte reden, so sehe ich das mit skeptischen augen. nicht umsonst lege ich constraints auf der datenbank an, damit notfalls eine anweisung nicht ausgeführt wird, wenn die integrität verletzt werden würde.

                          Ilja

                    2. Hallo,

                      ok danke für die Info. Ich prüfe die Eingabewerte ohnehin ab, aber wollte hiermit nur zusätzliche Sicherheit erreichen, aber offensichtlich ist das so ohne weiteres nicht möglich.

                      Viele Grüße,
                      Markus