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.

onedevteam.com
quelle

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.

MPelletier
quelle
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.

mateusza
quelle
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.

ChrisV
quelle
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