none
Constraint nur wenn Attribute nicht NULL? RRS feed

  • Frage

  • Hallo,

    gegeben sei folgendes Schema:

    CREATE TABLE Organisation
    (
     idx int NOT NULL,
     ...
     PRIMARY KEY (idx)
    );

    CREATE TABLE Standort
    (
     organisation int 
    NOT NULL,
     idx int NOT NULL,
     ...
     PRIMARY KEY (organisation,idx)

    );

    CREATE TABLE Raum
    (
     idx 
     int NOT NULL,

     organisation int NOT  NULL,
     standort  int NOT NULL,
     ...
     PRIMARY KEY (organisation,idx),
     FOREIGN KEY (organisation,standort) REFERENCES standort (organisation,idx)

    );

    Ist es möglich, dass das Attribut standort in der Tabelle raum den Wert NULL annehmen darf und das FOREIGN KEY-Constraint nur dann gilt, wenn es nicht NULL ist?

    Wie könnte man es besser lösen?

    Danke
    Magnus

    Mittwoch, 14. Juni 2017 08:07

Antworten

  • Hallo Magnus,

    natürlich kann ein FK auch NULL sein. Wenn also z. B. ein Kunde noch keinen Ansprechpartner hat und diese in einer separaten Tabelle liegen.

    Hier ein mögliches Skript für Deinen Fall.

    CREATE TABLE Raum
    ( 
    	organisation         integer  NOT NULL ,
    	Standort             integer  NULL ,
    	idx                  integer  NOT NULL 
    )
    go
    
    ALTER TABLE Raum
    	ADD CONSTRAINT XPKRaum PRIMARY KEY  CLUSTERED (idx ASC,organisation ASC)
    go
    
    CREATE TABLE Standort
    ( 
    	organisation         integer  NOT NULL ,
    	idx                  integer  NOT NULL 
    )
    go
    
    ALTER TABLE Standort
    	ADD CONSTRAINT XPKStandort PRIMARY KEY  CLUSTERED (organisation ASC,idx ASC)
    go
    
    
    ALTER TABLE Raum
    	ADD CONSTRAINT R_1 FOREIGN KEY (organisation,Standort) REFERENCES Standort(organisation,idx)

    Beachte aber, dass die Spalten dann NULL als Wert zulassen müssen. Hier der Standort im Raum.

    Das könnte also passen, wenn keine der Spalten im PK der Tabelle wäre. Denn in dem Falle sind ja NULL-Werte nicht zugelassen.

    Also, so wie Du es beschreibst geht es nicht.


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Mittwoch, 14. Juni 2017 10:23

Alle Antworten

  • Hier (leider in Englisch) findest du eine gute Erklärung, warum ein Foreign Key nicht NULL sein kann:
    https://stackoverflow.com/questions/7573590/can-a-foreign-key-be-null-and-or-duplicate
    Mittwoch, 14. Juni 2017 08:11
  • Hallo Magnus,

    natürlich kann ein FK auch NULL sein. Wenn also z. B. ein Kunde noch keinen Ansprechpartner hat und diese in einer separaten Tabelle liegen.

    Hier ein mögliches Skript für Deinen Fall.

    CREATE TABLE Raum
    ( 
    	organisation         integer  NOT NULL ,
    	Standort             integer  NULL ,
    	idx                  integer  NOT NULL 
    )
    go
    
    ALTER TABLE Raum
    	ADD CONSTRAINT XPKRaum PRIMARY KEY  CLUSTERED (idx ASC,organisation ASC)
    go
    
    CREATE TABLE Standort
    ( 
    	organisation         integer  NOT NULL ,
    	idx                  integer  NOT NULL 
    )
    go
    
    ALTER TABLE Standort
    	ADD CONSTRAINT XPKStandort PRIMARY KEY  CLUSTERED (organisation ASC,idx ASC)
    go
    
    
    ALTER TABLE Raum
    	ADD CONSTRAINT R_1 FOREIGN KEY (organisation,Standort) REFERENCES Standort(organisation,idx)

    Beachte aber, dass die Spalten dann NULL als Wert zulassen müssen. Hier der Standort im Raum.

    Das könnte also passen, wenn keine der Spalten im PK der Tabelle wäre. Denn in dem Falle sind ja NULL-Werte nicht zugelassen.

    Also, so wie Du es beschreibst geht es nicht.


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Mittwoch, 14. Juni 2017 10:23
  • Hallo Christoph,

    danke für Deine Hinweise. Dann werde ich den Fremdschlüssel wohl ganz rausnehmen müssen.

    Die Idee war, dass jeder Raum einer Organisation zugewiesen werden muss, aber der Standort nicht zwingend angegeben werden muss. Wenn er aber angegeben wird, dass muss er gültig sein.

    Ich sehe jetzt noch zwei Möglichkeiten:

    • Standorte nur mit einem index als Primärschlüssel zu identifizieren, also nur mit einer Spalte anstatt mit zweien.
      Dann könnte nur der Standort NULL sein, aber die FK-Beziehung bestehen bleiben.
    • Gar keine Fremdschlüssen zu definieren und alles im Code zu prüfen...

    Ideen?

    Danke
    Magnus

    Mittwoch, 14. Juni 2017 15:12
  • Sowas lässt sich durchaus als Trigger realisieren.
    Wenn der Datensatz angelegt/geändert wird, prüft der Trigger ob der Standort NULL oder gültig in der Standorttabelle ist, bei ungültig wird eine Exception gesendet.
    Auch hier würde ich eine Standort-ID verwenden, so dass die Änderung des Namens eines Standortes automatisch in allen Verwendungen aktuell ist.
    Mittwoch, 14. Juni 2017 15:20
  • Die Idee war, dass jeder Raum einer Organisation zugewiesen werden muss, aber der Ich sehe jetzt noch zwei Möglichkeiten:
    • Standorte nur mit einem index als Primärschlüssel zu identifizieren, also nur mit einer Spalte anstatt mit zweien.
      Dann könnte nur der Standort NULL sein, aber die FK-Beziehung bestehen bleiben.
    • Gar keine Fremdschlüssen zu definieren und alles im Code zu prüfen...

    Ideen?


    Hallo Knorpi,

    eigentlich sollte es auch funktionieren, wenn du standort in Raum Nullabe machst.

    Den foregn key kannst Du so lassen.

    Die foreign - key Beziehung gilt nur, wenn beide Felder nicht null sind.

    Gruß

    Willi

    Dienstag, 20. Juni 2017 09:11