Wie erstelle ich einen ENUM-Typ in SQLite?


103

Ich muss eine Tabelle von MySQL nach SQLite konvertieren, kann aber nicht herausfinden, wie ein Aufzählungsfeld konvertiert wird, da ich ENUMin SQLite keinen Typ finden kann .

Das oben genannte Feld befindet sich pTypein der folgenden Tabelle:

CREATE TABLE `prices` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `pName` VARCHAR(100) NOT NULL DEFAULT '',
    `pType` ENUM('M','R','H') NOT NULL DEFAULT 'M',
    `pField` VARCHAR(50) NULL DEFAULT NULL,
    `pFieldExt` VARCHAR(50) NULL DEFAULT NULL,
    `cmp_id` INT(11) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
ENGINE=MyISAM
ROW_FORMAT=DEFAULT

Ich benötige ein Feld mit nur drei Werten, die der Benutzer auswählen kann, und ich möchte dies in der Datenbank erzwingen, nicht nur in meiner Anwendung.

Antworten:


80

In SQLite gibt es keinen Aufzählungstyp, nur den folgenden:

  • NULL
  • GANZE ZAHL
  • REAL
  • TEXT
  • KLECKS

Quelle: http://www.sqlite.org/datatype3.html

Ich befürchte, dass in Ihrem Fall eine kleine, benutzerdefinierte Aufzählungstabelle erforderlich sein wird.


26
Tatsächlich ist "eine benutzerdefinierte Aufzählungstabelle" ein viel saubereres Design, das echte Aufzählungen verwendet
— a_horse_with_no_name

19
Warum nicht die CHECK () - Einschränkung verwenden, um nur drei mögliche Zeichenfolgen zuzulassen?
— Mateusza

1
@Wideshanks Ich glaube nicht, dass CHECK()es zu dem Zeitpunkt, als ich diese Antwort schrieb, existiert hat. Wenn die Saite nicht wirklich kurz ist, bin ich total dagegen. Maximal 1 oder 2 Zeichen.
— MPelletier

Ich kann VARCHARin meiner SQLite-Version verwenden. Ist das ein neuer Typzusatz?
— Hamman Samuel

3
@ HammanSamuel Es ist nicht neu, es ist als Bedeutung gelöst TEXT. Auf der von mir angegebenen Quellseite siehe Punkt 2.1 zur Bestimmung der Spaltenaffinität.
— MPelletier

104

SQLite-Methode ist die Verwendung einer CHECK-Einschränkung .

Einige Beispiele:

CREATE TABLE prices (
 id         INTEGER                                PRIMARY KEY,
 pName      TEXT CHECK( LENGTH(pName) <= 100 )     NOT NULL DEFAULT '',
 pType      TEXT CHECK( pType IN ('M','R','H') )   NOT NULL DEFAULT 'M',
 pField     TEXT CHECK( LENGTH(pField) <= 50 )     NULL DEFAULT NULL,
 pFieldExt  TEXT CHECK( LENGTH(pFieldExt) <= 50 )  NULL DEFAULT NULL,
 cmp_id     INTEGER                                NOT NULL DEFAULT '0'
)

Dadurch wird die pTypeSpalte nur auf die Werte beschränkt M, Rund Hgenau wie enum("M", "R", "H")bei einigen anderen SQL-Engines.


2
Welp, tatsächlich wird diese Implementierung nicht vollständig emuliert, enumda es unmöglich ist, nach dem ganzzahligen Index der Werte zu sortieren (was mit einem tatsächlichen enumFeld möglich ist). Denken Sie daran.
— Boris D. Teoharov

53

Um die Antwort von MPelletier zu erweitern, können Sie die Tabellen folgendermaßen erstellen:

CREATE TABLE Price (
  PriceId INTEGER       PRIMARY KEY AUTOINCREMENT NOT NULL,
  Name    VARCHAR(100)  NOT NULL,
  Type    CHAR(1)       NOT NULL DEFAULT ('M') REFERENCES PriceType(Type)
);

CREATE TABLE PriceType (
  Type    CHAR(1)       PRIMARY KEY NOT NULL,
  Seq     INTEGER
);
INSERT INTO PriceType(Type, Seq) VALUES ('M',1);
INSERT INTO PriceType(Type, Seq) VALUES ('R',2);
INSERT INTO PriceType(Type, Seq) VALUES ('H',3);

Jetzt sind die Aufzählungswerte direkt in der Preistabelle verfügbar, da sie eine ENUM verwenden würden: Sie müssen sich nicht mit der PriceType-Tabelle verbinden, um die Typwerte zu erhalten. Sie müssen sie nur verwenden, wenn Sie die Reihenfolge von bestimmen möchten die ENUMs.

In SQLite Version 3.6.19 wurden Fremdschlüsseleinschränkungen eingeführt.


3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Sollte Ihnen einen Syntaxfehler bringen. "Das erste Formular (mit dem Schlüsselwort" VALUES ") erstellt eine einzelne neue Zeile in einer vorhandenen Tabelle." : sqlite.org/lang_insert.html . Brechen Sie es auf, vermeiden Sie INSERT INTO PriceType(Type, Seq) VALUES ('M',1); INSERT INTO PriceType(Type, Seq) VALUES ('R',2); INSERT INTO PriceType(Type, Seq) VALUES ('H',3);
— Folgendes

9
Vergessen Sie nicht, PRAGMA foreign_keys = ON;für jede Sitzung - da fkeys in sqlite3 standardmäßig deaktiviert sind
— smathy

3
Wenn Sie nicht vergessen möchten, PRAGMA foreign_keys = ON;können Sie dies in Ihrer .sqliterc-Datei in Ihrem Home-Verzeichnis einrichten.
— Eradicatore

1
Möglicherweise möchten Sie auch die UNIQUEEinschränkung für Seq. So etwas wieCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
— Eradicatore

1
Warum sollten Sie eine separate ' Seq'-Spalte erstellen, anstatt nur die Standard- Rowid-Spalte zu verwenden ?
— Parthian Shot
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.