Ich möchte eine einzelne Zeile in einer Konfigurationstabelle für meine Anwendung speichern. Ich möchte erzwingen, dass diese Tabelle nur eine Zeile enthalten kann.
Was ist der einfachste Weg, um die Einschränkung für einzelne Zeilen durchzusetzen?
Ich möchte eine einzelne Zeile in einer Konfigurationstabelle für meine Anwendung speichern. Ich möchte erzwingen, dass diese Tabelle nur eine Zeile enthalten kann.
Was ist der einfachste Weg, um die Einschränkung für einzelne Zeilen durchzusetzen?
Name
?
ar
s Kommentar war. Das Problem ist, wenn Sie nur Name / Wert-Paare speichern, muss der Wert ziemlich gut eine Zeichenfolge sein, und Sie haben keine Möglichkeit , die Validierung in der Datenbank zu erzwingen . Wenn Sie eine einzeilige Tabelle mit separaten Spalten für jede Einstellung verwenden (wie vom OP gewünscht), können Sie die Validierung für jede Konfigurationseinstellung einfach über Prüfbeschränkungen erzwingen.
Antworten:
Sie stellen sicher, dass eine der Spalten nur einen Wert enthalten kann, und legen diesen dann als Primärschlüssel fest (oder wenden eine Eindeutigkeitsbeschränkung an).
CREATE TABLE T1(
Lock char(1) not null,
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
Ich habe eine Reihe dieser Tabellen in verschiedenen Datenbanken, hauptsächlich zum Speichern der Konfiguration. Es ist viel schöner zu wissen, dass Sie, wenn das Konfigurationselement ein int sein sollte, immer nur ein int aus der Datenbank lesen.
comp.databases.theory
eine Usenet-Gruppe (sichtbar über Google-Gruppen), von der ich zugegebenermaßen in letzter Zeit nicht viel gelesen habe. Es war mehr auf relationale Theorie als auf SQL ausgerichtet - aber ich wusste zufällig, dass dportas / sqlvogel dieselbe Gruppe auch frequentierte. TTM war ein Verweis auf das Dritte Manifest , ein gutes Buch, das (wieder) eher über relationale Theorie als über SQL spricht.
Normalerweise verwende ich Damiens Ansatz, der für mich immer gut funktioniert hat, aber ich füge noch eines hinzu:
CREATE TABLE T1(
Lock char(1) not null DEFAULT 'X',
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
Wenn Sie das "DEFAULT 'X'" hinzufügen, müssen Sie sich nie mit der Spalte "Sperren" befassen und müssen sich nicht daran erinnern, welcher Sperrwert beim ersten Laden der Tabelle angegeben wurde.
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
Vielleicht möchten Sie diese Strategie überdenken. In ähnlichen Situationen fand ich es oft von unschätzbarem Wert, die alten Konfigurationszeilen für historische Informationen herumliegen zu lassen.
Zu diesem Zweck verfügen Sie über eine zusätzliche Spalte creation_date_time
(Datum / Uhrzeit des Einfügens oder Aktualisierens) und einen Auslöser zum Einfügen oder Einfügen / Aktualisieren, der das aktuelle Datum / die aktuelle Uhrzeit korrekt auffüllt.
Um Ihre aktuelle Konfiguration zu erhalten, verwenden Sie Folgendes:
select * from config_table order by creation_date_time desc fetch first row only
(abhängig von Ihrem DBMS-Geschmack).
Auf diese Weise können Sie den Verlauf weiterhin für Wiederherstellungszwecke verwalten (Sie können Bereinigungsverfahren einleiten, wenn die Tabelle zu groß wird, dies ist jedoch unwahrscheinlich), und Sie können weiterhin mit der neuesten Konfiguration arbeiten.
SELECT TOP 1 ... ORDER BY creation_date_time DESC
Sie können einen INSTEAD OF- Trigger implementieren , um diese Art von Geschäftslogik in der Datenbank zu erzwingen.
Der Trigger kann eine Logik enthalten, um zu überprüfen, ob bereits ein Datensatz in der Tabelle vorhanden ist, und in diesem Fall die Einfügung rückgängig zu machen.
Wenn Sie nun einen Schritt zurücktreten, um das Gesamtbild zu betrachten, frage ich mich, ob es möglicherweise eine alternative und geeignetere Möglichkeit gibt, diese Informationen zu speichern, beispielsweise in einer Konfigurationsdatei oder einer Umgebungsvariablen.
Ich benutze ein Bitfeld für den Primärschlüssel mit dem Namen IsActive. Es können also höchstens 2 Zeilen vorhanden sein, und der SQL-Code zum Abrufen der gültigen Zeile lautet: Wählen Sie * in den Einstellungen aus, wobei IsActive = 1 ist, wenn die Tabelle den Namen Einstellungen hat.
Hier ist eine Lösung, die ich für eine Sperrtabelle gefunden habe, die nur eine Zeile enthalten kann und ein Y oder N enthält (z. B. einen Anwendungssperrstatus).
Erstellen Sie die Tabelle mit einer Spalte. Ich habe der einen Spalte eine Prüfbedingung auferlegt, damit nur ein Y oder N eingefügt werden kann. (Oder 1 oder 0 oder was auch immer)
Fügen Sie eine Zeile mit dem "normalen" Zustand in die Tabelle ein (z. B. N bedeutet nicht gesperrt).
Erstellen Sie dann einen INSERT-Trigger für die Tabelle, die nur ein SIGNAL (DB2) oder RAISERROR (SQL Server) oder RAISE_APPLICATION_ERROR (Oracle) enthält. Dadurch kann der Anwendungscode die Tabelle aktualisieren, aber INSERT schlägt fehl.
DB2-Beispiel:
create table PRICE_LIST_LOCK
(
LOCKED_YN char(1) not null
constraint PRICE_LIST_LOCK_YN_CK check (LOCKED_YN in ('Y', 'N') )
);
--- do this insert when creating the table
insert into PRICE_LIST_LOCK
values ('N');
--- once there is one row in the table, create this trigger
CREATE TRIGGER ONLY_ONE_ROW_IN_PRICE_LIST_LOCK
NO CASCADE
BEFORE INSERT ON PRICE_LIST_LOCK
FOR EACH ROW
SIGNAL SQLSTATE '81000' -- arbitrary user-defined value
SET MESSAGE_TEXT='Only one row is allowed in this table';
Funktioniert bei mir.
Alte Frage, aber wie wäre es mit IDENTITY (MAX, 1) eines kleinen Spaltentyps?
CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
IF NOT EXISTS ( select * from table )
BEGIN
///Your insert statement
END
Hier können wir auch einen unsichtbaren Wert erstellen, der nach dem ersten Eintrag in der Datenbank identisch ist. Beispiel: Schülertabelle: ID: int Vorname: char Hier im Eingabefeld müssen wir denselben Wert für die ID-Spalte angeben, der einschränkt wie nach dem ersten Eintrag außer dem Schreiben von lock bla bla aufgrund der Primärschlüsseleinschränkung, so dass nur eine Zeile für immer vorhanden ist. Hoffe das hilft!
(Name, Value)
mit einem Primärschlüssel für Name. Dann können Sieselect Value from Table where Name = ?
mit Sicherheit feststellen , dass entweder keine oder nur eine Zeile zurückgegeben wird.