2012-06-12 8 views
38

Ich habe eine Tabelle mit mehreren Spalten, die den Primärschlüssel bilden. Die Art der gespeicherten Daten ermöglicht, dass einige dieser Felder NULL Werte haben. Ich habe meine Tabelle als solche entworfen:NULL-Wert im mehrspaltigen Primärschlüssel

CREATE TABLE `test` (
    `Field1` SMALLINT(5) UNSIGNED NOT NULL, 
    `Field2` DECIMAL(5,2) UNSIGNED NULL DEFAULT NULL, 
    PRIMARY KEY (`Field1`, `Field2`) 
) 
COLLATE='latin1_swedish_ci' 
ENGINE=InnoDB; 

Allerdings, wenn ich describe test laufen sie zeigt, wie folgt aus:

|| *Field* || *Type*    || *Null* || *Key* || *Default* || *Extra* 
|| Field1 || smallint(5) unsigned || NO  || PRI ||   ||   
|| Field2 || decimal(5,2) unsigned || NO  || PRI || 0.00  ||   

Und ich immer einen Fehler bekommen, wenn ein NULL Wert einfügen.

Spalte ‚Field2‘ kann nicht

Ist dies null sein, weil ein Feld, das Teil eines Primärschlüssels ist nicht null sein kann? Was sind meine Alternativen neben der Verwendung von "0" für NULL?

+2

Dank Link des vj Schah, macht @Tomalak den [ausgezeichneten Punkt] (http://stackoverflow.com/a/386061/673991), dass diese Einschränkung aus dem Grunde SQL folgt Grundsatz, dass, da die Teile eines PRIMARY-Schlüssels von jeder Zeile mit jeder anderen Zeile verglichen werden müssen und "** NULL nicht Teil eines Vergleichs sein kann - das Ergebnis eines solchen Vergleichs immer NULL **" wäre, was die Durchsetzung der PRIMÄREN Schlüsseleindeutigkeit erfordert Nicht-Null-Spalten. –

Antwort

34

Von der MySQL-Dokumentation:

ein Primärschlüssel ist ein eindeutiger Index, in der alle Schlüsselspalten als NOT NULL definiert werden müssen. Wenn sie
nicht explizit als NOT NULL deklariert sind, deklariert MySQL sie so implizit (und stillschweigend). Eine Tabelle kann nur einen PRIMÄRSCHLÜSSEL haben. Der Name eines PRIMARY KEY ist immer PRIMARY, dh kann nicht als Name für eine andere Art von Index verwendet werden.

http://dev.mysql.com/doc/refman/5.1/en/create-table.html

Wenn Field2 NULL sein kann, frage ich mich, warum Sie es als Teil des Primärschlüssels benötigen, da Sie dann Field1 müssen in allen Reihen verschieden sein. Also sollte Field1 allein als Primärschlüssel ausreichen. Sie könnten einen anderen Indextyp für Field2 erstellen.

+12

Überraschend, dass es einem ermöglicht, einen Primärschlüssel mit einer Spalte zu erstellen, die als Nullen akzeptiert wird. – Marvo

+1

Das ist die Definition, nach der ich suchte, aber nicht gefunden habe. Vielen Dank. Tatsächlich habe ich jetzt 12 Spalten, die den Primärschlüssel bilden. 5 dieser Werte sind nullfähig. Es handelt sich um eine Cache-Strategie, bei der nicht alle Werte in der gebuchten Anforderung benötigt werden. Meine Idee war, dass ein zusammengesetzter Primärschlüssel billiger wäre, als einen Autoinkrement-Wert als PK zu verwenden und einen eindeutigen Index über alle anderen hinzuzufügen. Sieht so aus, als müsste ich diesen Weg gehen. – simbabque

+7

@Girish Ich habe gerade auf dieses Problem und ich möchte auch ein NULL-Feld haben. In meinem Fall ist der PK zwei Felder, von denen eines Nullable sein kann, aber ich möchte höchstens eine Zeile mit dem 2. Feld NULL, so dass sollte eine gültige PK sein. IMHO, das ist eine fehlgeschlagene Spezifikation von MySQL. – Seb

7

Primärschlüssel Zustände, die Spalte nicht NULL Werte haben müssen. Spalten, die zum Definieren des zusammengesetzten Primärschlüssels verwendet werden, sind also nicht NULL.

Auch Oracle-Server vergleicht die Kombination aller Spalten in einer zusammengesetzten Primärschlüsseldefinition. Wenn Ihre alle Spalten vorhandenen Daten (z. B. x, y) mit der neu hinzugefügten Zeile übereinstimmen, wird der Fehler von Eindeutige Einschränkung verletzt ausgelöst.

Darüber hinaus sehen Sie sich diesen Thread: What's wrong with nullable columns in composite primary keys?.

Dieser Link bietet wertvolle Informationen über die Möglichkeit von NULLABLE Spalten in zusammengesetzten Schlüssel!

+3

Danke für Ihre Eingabe. Ich bin nicht auf Oracle, sondern auf MySQL. – simbabque

3

können Sie einzigartige verwenden Schlüssel wie folgt aus:

mysql> CREATE TABLE `test` (
    ->  `Field1` SMALLINT(5) UNSIGNED NOT NULL, 
    ->  `Field2` DECIMAL(5,2) UNSIGNED NULL DEFAULT NULL, 
    ->  UNIQUE KEY (`Field1`, `Field2`) 
    ->) 
    -> COLLATE='latin1_swedish_ci' 
    -> ENGINE=InnoDB; 
Query OK, 0 rows affected (0.03 sec) 

mysql> 
mysql> desc test 
    -> ; 
+--------+-----------------------+------+-----+---------+-------+ 
| Field | Type     | Null | Key | Default | Extra | 
+--------+-----------------------+------+-----+---------+-------+ 
| Field1 | smallint(5) unsigned | NO | MUL | NULL |  | 
| Field2 | decimal(5,2) unsigned | YES |  | NULL |  | 
+--------+-----------------------+------+-----+---------+-------+ 
2 rows in set (0.01 sec) 
18

Primärschlüssel verwendet werden, um die Spalte zu machen einzigartig und nicht null

Inorder Einsatz Nullwerte als machen field2 einfügen Unique

Eindeutige Einschränkung machen das Feld Entfernt Duplikate null Werte erlauben aber

+1

Dies beantwortet die Frage, danke. Die angenommene Antwort war falsch. – singe3

+1

@ singe3 Nun, die Frage war nicht _wie erstelle ich einen Index mit einem NULL-Wert_, aber _Warum kann ich keinen NULL-Wert im Primärschlüssel_ haben. Ich bin froh, dass die Information, dass ein eindeutiger Schlüssel ein NULL-Feld hat, Ihnen geholfen hat, beantwortet aber die Frage nicht. Die angenommene Antwort tut es. – simbabque