Вы знаете, что дублирования нет, но когда синтаксический анализ оператора выполняется, оптимизатор не знает, что его нет, и, что более важно, не может быть , любое дублирование. Парсер смотрит на статистику, чтобы решить, как работать, но в целом не смотрит на данные. Оператор обновления может быть кэширован и использован повторно, поэтому, даже если бы он посмотрел и увидел, что сейчас нет дубликатов, данные могли бы измениться, если этот же оператор снова будет выполнен позже из кэша.
Представьте, что вы добавили дополнительную строку:
insert into taby values(2,222);
тогда ваш запрос получит:
select x2,y2 from tabx,taby where tabx.x1=taby.y1;
X2 Y2
---------- ----------
11 21
12 22
12 222
Теперь в обновлении есть два возможных значения для установки обоих значений x2=12
; Должны ли они оба быть 22, или оба 222, или один из каждого? У Oracle нет возможности узнать, что правильно, и он не может выбрать, какой из первых двух вариантов следует использовать (и уж точно не может использовать третий).
Теперь это не ваша настоящая ситуация, но вы должны сказать Oracle, что ситуация не может возникнуть. Формулировка ошибки здесь подсказка; для сохранения ключа должен быть ключ. Если вы определите tabY
с помощью первичного или уникального ключа:
create table tabY (y1 number primary key, y2 number);
insert into taby values(1,21);
insert into taby values(2,22);
тогда моя готовая третья вставка не разрешена, Oracle знает об этом и может применить эти знания к обновлению:
update (select x2,y2 from tabx,taby where tabx.x1=taby.y1) set x2=y2;
2 rows updated.
select x2,y2 from tabx,taby where tabx.x1=taby.y1;
X2 Y2
---------- ----------
21 21
22 22
Неважно, сколько у вас строк с x1=2
, вы хотите, чтобы все они были обновлены до x2=22
. Так что x1
не обязательно должно быть уникальным, и вам не нужен UK / Pk для этого. Но y1
должен быть уникальным, чтобы вы знали, какое одиночное значение y2
использовать для всех из этих x1=2
строк.
Что я не понимаю, так это то, становится ли представление сохраненным на основе ключа, если включенные столбцы объявляются уникальными, или фактические значения, которые обновляются.
Это столбцы, а не значения. Но мне кажется, что я не очень хорошо объяснил, что, поскольку вы делаете set x2=y2
, он может видеть, что только таблица tabx
фактически обновляется; поэтому он должен иметь возможность определить, какие строки в таблице tabx
затронуты, а затем он должен работать для каждой из этих строк , какой соответствует строке taby
, чтобы получить y2
значения из - которые он получает из условия соединения.
Для каждого обновляемого x2
он должен идентифицировать одно значение y2
для использования, что он делает, ища строку taby
, где taby.y1
- * этой строки tabx.x1
, Если в taby
было (или могло быть просто) несколько строк, соответствующих этому условию, то он не знал бы, какие из этих опций использовать - 22 или 222 в моем примере. В taby
должно быть одно совпадение, поэтому y1
должно быть уникальным и должно быть объявлено как уникальное через Великобританию или PK.
Может быть много разных значений x2
, которые обновляются до одного и того же значения y2
; Вы также можете иметь
insert into tabx values(2,13);
insert into tabx values(2,14);
etc.
и все они будут обновлены до того же значения - 22 - потому что неуникальное значение x1
во всех этих строках по-прежнему отображается в одну строку ytab
с этими таблицами UK / PK через соединение состояние.