| Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
| Все форумы / Oracle |
![]() |
||
|
dbms_photoshop Member Откуда: Ницца Сообщений: 2231 |
Добрый вечер! Вот стоит у меня задача проапдейтить дочернюю таблицу, записи которой ссылаются на определенный айдишник главной. И дело в том, что задан не этот самый айдишник главной, а уникальный код по которому он определяется. Это элементарно реализуется, используя скалярный подзапрос: UPDATE t_detail t SET val = null WHERE t.h_h_id = (SELECT h_id FROM t_header WHERE code = '666');Но в ранних версиях, когда не было скаляров можно заменить ч-з exists уже с падением производительности: UPDATE t_detail t SET val = null WHERE exists (SELECT h_id FROM t_header WHERE code = '666' and h_id = t.h_h_id); Интересуют такие вопросы: Когда появился exists? Можно ли реализовать апдейт одним выражением SQL отличным от указанных двух? Пост носит характер философских размышлений. Благодарю ответивших. |
| 19 окт 09, 20:04 [7808125] Ответить | Цитировать Сообщить модератору | |
|
Elic Member Откуда: 1984. Неким AI прозван 'быдлом'. Таки де-факто забанен Сообщений: 22762 |
То же и в 6-ке ![]()
|
||||||
| 19 окт 09, 20:30 [7808210] Ответить | Цитировать Сообщить модератору | |||||||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
Он был "испокон веков"... Не путайте с Scalar Subquery Expressions - это появилось много позже... :-)
В Oracle v6 - не помню и доки под рукой нет... :-( В Oracle7 (1992-1993) точно уже была! :-)
UPDATE (-- key preserned view
SELECT t.val AS t_val
FROM t_detail t, t_header H
WHERE H.h_id = t.h_h_id
AND H.code = '666')
SET val = null;
|
||||||||
| 19 окт 09, 20:30 [7808212] Ответить | Цитировать Сообщить модератору | |||||||||
|
Elic Member Откуда: 1984. Неким AI прозван 'быдлом'. Таки де-факто забанен Сообщений: 22762 |
|
||||
| 19 окт 09, 20:34 [7808237] Ответить | Цитировать Сообщить модератору | |||||
|
-2- Member Откуда: Сообщений: 9778 |
И еще merge можно использовать. |
||
| 19 окт 09, 20:35 [7808239] Ответить | Цитировать Сообщить модератору | |||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
|
||||||
| 19 окт 09, 20:36 [7808246] Ответить | Цитировать Сообщить модератору | |||||||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
|
||||||
| 19 окт 09, 20:41 [7808275] Ответить | Цитировать Сообщить модератору | |||||||
|
Elic Member Откуда: 1984. Неким AI прозван 'быдлом'. Таки де-факто забанен Сообщений: 22762 |
|
||||
| 19 окт 09, 20:42 [7808278] Ответить | Цитировать Сообщить модератору | |||||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
Не key preserved view.
|
||||
| 19 окт 09, 20:45 [7808290] Ответить | Цитировать Сообщить модератору | |||||
|
Elic Member Откуда: 1984. Неким AI прозван 'быдлом'. Таки де-факто забанен Сообщений: 22762 |
create table tmp_parent(id int primary key, x int); create table tmp_child(id int, parent_id int, y int); update (select c.y from tmp_parent p, tmp_child c where p.x = 1 and c.parent_id = p.id) set y = 2; 0 rows updated. |
||||
| 19 окт 09, 20:56 [7808319] Ответить | Цитировать Сообщить модератору | |||||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
Да, утверждая, что необходимо наличие Primary key в у T_DETAIL я ошибся. Спасибо за поправку. Я не на ручнике... :-))) "С толкача" заводят мотор, когда что-то не так с аакумулятором... :-)) Если же "с толкача" снимать с "ручника", то можно повредить тормозную систему, что есть вредно... :-))
Требуется обеспечить, чтобы значения, которые уникальны в реальной таблице, оставались уникальными во view. Да, это обеспечивается наличием Primary Key или Unique в таблице, с которой выполняется JOIN (В приведенном примере в TMP_PARENT). В этом примере у TMP_CHILD нет Primary Key, но TMP_CHILD.ROWID во VIEW будут уникальны. |
||||||||
| 19 окт 09, 21:34 [7808426] Ответить | Цитировать Сообщить модератору | |||||||||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
Неожиданный эффект:SQL*Plus: Release 10.2.0.4.0 - Production on Mon Oct 19 21:45:54 2009 Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production SQL> create table tmp_parent(id int primary key, x int); Table created. SQL> create table tmp_child(id int, parent_id int, y int); Table created. SQL> CREATE VIEW tmp_parent_child 2 AS 3 select c.y from tmp_parent p, tmp_child c where p.x = 1 and c.parent_id = p.id 4 ; View created. SQL> COLUMN owner FORMAT A6; SQL> COLUMN table_name FORMAT A18; SQL> COLUMN column_name FORMAT A12; SQL> COLUMN INSERTABLE FORMAT A10; SQL> COLUMN UPDATABLE FORMAT A10; SQL> COLUMN DELETABLE FORMAT A10; SQL> -- Первичный ключ включен UPDATABLE = YES SQL> select * from user_updatable_columns 2 WHERE table_name = 'TMP_PARENT_CHILD'; OWNER TABLE_NAME COLUMN_NAME UPDATABLE INSERTABLE DELETABLE ------ ------------------ ------------ ---------- ---------- ---------- SCOTT TMP_PARENT_CHILD Y YES YES YES SQL> -- Update выполняется без ошибок SQL> update tmp_parent_child set y = 2; 0 rows updated. SQL> -- ВЫключаем первичный ключ SQL> ALTER TABLE tmp_parent DISABLE PRIMARY KEY; Table altered. SQL> -- Первичный ключ выключен, однако UPDATABLE всё еще YES SQL> select * from user_updatable_columns 2 WHERE table_name = 'TMP_PARENT_CHILD'; OWNER TABLE_NAME COLUMN_NAME UPDATABLE INSERTABLE DELETABLE ------ ------------------ ------------ ---------- ---------- ---------- SCOTT TMP_PARENT_CHILD Y YES YES YES SQL> -- Попытка UPDATE вызывает ошибку SQL> -- ORA-01779: cannot modify a column which maps to a non key-preserved table SQL> update tmp_parent_child set y = 2; update tmp_parent_child set y = 2 * ERROR at line 1: ORA-01779: cannot modify a column which maps to a non key-preserved table SQL> -- Теперь UPDATABLE стало NO SQL> select * from user_updatable_columns 2 WHERE table_name = 'TMP_PARENT_CHILD'; OWNER TABLE_NAME COLUMN_NAME UPDATABLE INSERTABLE DELETABLE ------ ------------------ ------------ ---------- ---------- ---------- SCOTT TMP_PARENT_CHILD Y NO NO NOТо есть изменения в user_updatable_columns только после удачного/неудачного UPDATE Аналогичное поведение наблюдается при включении первичного ключа TMP_PARENT На других версиях Oracle сегодня проверить не успеваю... Как сие прокомментирует почтенная публика? |
| 19 окт 09, 21:54 [7808468] Ответить | Цитировать Сообщить модератору | |
|
-2- Member Откуда: Сообщений: 9778 |
|
||
| 19 окт 09, 23:05 [7808677] Ответить | Цитировать Сообщить модератору | |||
|
SQL*Plus Member Откуда: Россия, Москва Сообщений: 6951 |
Выключение первичного ключа инвалидировало VIEW.
SQL> -- Статус VIEW до выключения первичного ключа
SQL> SELECT object_name, object_type, status
2 FROM user_objects
3 WHERE object_name = 'TMP_PARENT_CHILD';
OBJECT_NAME OBJECT_TYPE STATUS
------------------ ------------ -------
TMP_PARENT_CHILD VIEW VALID
SQL> -- ВЫключаем первичный ключ
SQL> ALTER TABLE tmp_parent DISABLE PRIMARY KEY;
Table altered.
SQL> -- Статус VIEW после выключения первичного ключа
SQL> SELECT object_name, object_type, status
2 FROM user_objects
3 WHERE object_name = 'TMP_PARENT_CHILD';
OBJECT_NAME OBJECT_TYPE STATUS
------------------ ------------ -------
TMP_PARENT_CHILD VIEW INVALID
|
||||
| 20 окт 09, 11:14 [7810038] Ответить | Цитировать Сообщить модератору | |||||
|
dbms_photoshop Member Откуда: Ницца Сообщений: 2231 |
Спасибо за исчерпывающие ответы. Да, перепутал single row subquery & scalar subquery. Возник еще один вопрос по скалярам. Читаю в документации:
Выполняю: SQL> SELECT * FROM v$version WHERE rownum = 1;
BANNER
----------------------------------------------------------------
Oracle Database 10g Release 10.2.0.4.0 - 64bit Production
SQL> SELECT LEVEL, (SELECT 'hello world' FROM dual) val
2 FROM dual
3 START WITH 1 = (SELECT 1 id FROM dual)
4 CONNECT BY LEVEL <= (SELECT 3 id FROM dual);
LEVEL VAL
---------- -----------
1 hello world
2 hello world
3 hello worldНасколько я понимаю запрос выполняться не должен? Или опять где-то ошибся? :) |
||
| 20 окт 09, 13:32 [7811299] Ответить | Цитировать Сообщить модератору | |||
|
Elic Member Откуда: 1984. Неким AI прозван 'быдлом'. Таки де-факто забанен Сообщений: 22762 |
Радоваться надо, что работает больше, чем заявлено, а не меньше :) |
||
| 20 окт 09, 14:05 [7811594] Ответить | Цитировать Сообщить модератору | |||
| Все форумы / Oracle | ![]() |
|