Как предотвратить столбец b, содержащий то же значение, что и любой столбец в Oracle? - PullRequest
5 голосов
/ 23 апреля 2010

Что является хорошим способом предотвратить появление в таблице с 2 столбцами a (уникальной) и b любой записи, в которой столбец b равен любому значению в столбце a? Это будет использоваться для таблицы исправлений, подобной этой,

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

Я вижу, как это можно сделать с помощью триггера и подзапроса, не предполагающего одновременной активности, но предпочтительнее был бы более декларативный подход.

Это пример того, что следует предотвратить,

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

В идеале решение будет работать с одновременными вставками и обновлениями.

Ответы [ 2 ]

2 голосов
/ 24 апреля 2010

Вы можете использовать материализованное представление для обеспечения выполнения ваших требований (протестировано с 10.2.0.1).

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 

Уникальный индекс гарантирует, что вы не можете иметь одинаковое значение в обоих столбцах (в двух строках).

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)

Он будет сериализован во время фиксации, но только для значений столбцов A и B (т. Е. В общем случае он не должен предотвращать одновременную непересекающуюся активность).

Unicity будет проверяться только во время COMMIT, и некоторые инструменты не ожидают, что commit потерпит неудачу, и могут вести себя неадекватно. Также при сбое COMMIT вся транзакция откатывается, и вы теряете все незафиксированные изменения (вы не можете «повторить»).

0 голосов
/ 24 апреля 2010

Рассмотрим вставку сеанса A ('A', 'B'), но без фиксации, затем вставку сеанса B ('B', 'A') без фиксации. Ни один сеанс не может видеть запись, вставленную другим. Затем сессии фиксируют.

Вы можете сериализовать, заблокировав всю таблицу при вставке одного сеанса (триггер BEFORE INSERT) и выполнить проверку в триггере AFTER INSERT. Если в таблице есть содержимое, которое вы указали, оно не должно видеть большую активность, поэтому сериализация не будет проблемой.

...