2010-04-23 5 views
5

Was ein guter Weg ist, eine Tabelle mit zwei Spalten, ein (einmaliger) und b aus, die jeden Datensatz zu verhindern, in Spalte b auf einem beliebigen Wert in der Spalte einer gleich? Dies würde für eine Tabelle von Korrekturen wie folgt verwendet werden,Wie verhindert man, dass Spalte b den gleichen Wert wie eine Spalte in Oracle enthält?

MR -> Mr 
Prf. -> Prof. 
MRs -> Mrs 

Ich kann sehen, wie es mit einem Auslöser und einer Unterabfrage unter der Annahme, keine gleichzeitige Aktivität, sondern ein deklarativen Ansatz vorzuzuziehen wäre getan werden könnte.

Dies ist ein Beispiel dafür, was verhindert werden soll,

Wing Commdr. -> Wing Cdr. 
Wing Cdr. -> Wing Commander 

Idealerweise würde die Lösung bei gleichzeitigen Einsätzen und Updates.

+0

Ist es, dass die Spalte A in der Tabelle eindeutig sein sollte? – dpbradley

+0

Ja, in Spalte A sollte die Eindeutigkeit gelten. –

Antwort

2

Sie könnten eine materialisierte Ansicht verwenden, um Ihre Anforderungen (getestet mit 10.2.0.1) zu erzwingen.

SQL> CREATE TABLE t (a VARCHAR2(20) NOT NULL PRIMARY KEY, 
    2     b VARCHAR2(20) NOT NULL); 
Table created 

SQL> CREATE MATERIALIZED VIEW LOG ON t WITH (b), ROWID INCLUDING NEW VALUES;  
Materialized view log created 

SQL> CREATE MATERIALIZED VIEW mv 
    2  REFRESH FAST ON COMMIT 
    3 AS 
    4 SELECT 1 umarker, COUNT(*) c, count(a) cc, a val_col 
    5 FROM t 
    6 GROUP BY a 
    7 UNION ALL 
    8 SELECT 2 umarker, COUNT(*), COUNT(b), b 
    9 FROM t 
10 GROUP BY b;  
Materialized view created 

SQL> CREATE UNIQUE INDEX idx ON mv (val_col);  
Index created 

Der eindeutige Index stellt sicher, dass Sie nicht denselben Wert in beiden Spalten (in zwei Zeilen) haben können.

SQL> INSERT INTO t VALUES ('Wing Commdr.', 'Wing Cdr.');  
1 row inserted 

SQL> COMMIT;  
Commit complete 

SQL> INSERT INTO t VALUES ('Wing Cdr.', 'Wing Commander');  
1 row inserted 

SQL> COMMIT;  

ORA-12008: erreur dans le chemin de régénération de la vue matérialisée 
ORA-00001: violation de contrainte unique (VNZ.IDX) 

SQL> INSERT INTO t VALUES ('X', 'Wing Commdr.');  
1 row inserted 

SQL> COMMIT; 

ORA-12008: erreur dans le chemin de régénération de la vue matérialisée 
ORA-00001: violation de contrainte unique (VNZ.IDX) 

Es wird serialisiert während begehen, sondern nur auf den Werten der Spalten A und B (dh in der Regel sollte es nicht gleichzeitig disjoint Aktivität verhindern).

Die Einzigkeit wird nur bei COMMIT Zeit und einige Werkzeuge Erwarten Sie nicht unangemessen zu versagen und kann verhalten geprüft werden begehen. Auch wenn das COMMIT fehlschlägt, wird die gesamte Transaktion zurückgesetzt und Sie verlieren nicht ausgeführte Änderungen (Sie können nicht "wiederholen").

+0

Ich mag diese Lösung, weil sie die Verantwortung für die Integrität nach unten in einen Index drückt. –

0

Betrachten Sitzung Ein Einfügen ('A', 'B'), aber nicht zu begehen, dann Session B Einsätze ('B', 'A') ohne zu begehen. Keine Sitzung kann den Datensatz sehen, der von dem anderen eingefügt wurde. Dann verpflichten sich die Sitzungen.

Sie können serialisieren, indem Sie die gesamte Tabelle sperren, wenn eine Sitzung eingefügt wird (BEFORE INSERT-Trigger), und den Check in einen AFTER INSERT-Trigger durchführen. Wenn die Tabelle den von Ihnen angegebenen Inhalt enthält, sollte sie nicht sehr aktiv sein, sodass die Serialisierung kein Problem darstellt.

Verwandte Themen