Обновление таблицы на основе зависимой таблицы - PullRequest
0 голосов
/ 29 ноября 2011

Настройка


У меня есть две таблицы, USERS и PETS.

у каждого пользователя есть ID, NAME и флаг HAS_PETS, который равен 1, если у пользователя есть хотя бы один питомец, и 0 в противном случае.

Каждый pet имеет ID, NAME и OWNER_ID. Вот сценарий создания:

create table USERS(
ID NUMBER(*,0),
NAME VARCHAR2(50 BYTE),
HAS_PETS NUMBER(1,0),
CONSTRAINT "XPKUSERS" PRIMARY KEY ("ID")
);

create table PETS(
ID NUMBER(*,0),
NAME VARCHAR2(50 BYTE),
OWNER_ID NUMBER(*,0),
CONSTRAINT "XPKPETS" PRIMARY KEY ("ID")
);

insert into USERS values(0, 'Alice', 0);
insert into USERS values(1, 'Bob', 1);
insert into USERS values(2, 'Carol', 0);

insert into PETS values(0, 'Fido', 1);
insert into PETS values(1, 'Spot', 1);
insert into PETS values(2, 'Xerxes', 2);

Проблема


В какой-то момент многие домашние животные были добавлены в PETS, но флаг OWNER таблицы *1024* не был обновлен. В приведенных выше примерах данных Кэрол владеет Ксерксом, но ее флаг равен 0.

Я хочу написать заявление, которое установит HAS_PETS в true, если у владельца есть домашнее животное. С учетом приведенных выше данных он должен установить флаг Кэрол HAS_PETS на 1. Я попробовал это:

update (
select * 
from USERS a join PETS b 
on a.HAS_PETS = 0 and a.ID = b.OWNER_ID
)
set HAS_PETS = 1 

но выдает ошибку, cannot modify a column which maps to a non key-preserved table. Oracle рекомендует, чтобы я Modify the underlying base tables directly, но я не могу определить, какие строки необходимо обновить, если я не сделаю это соединение.

Поиск в Google побудил меня попробовать этот альтернативный синтаксис:

update a
set a.HAS_PETS = 1
from USERS a join PETS b 
on a.HAS_PETS = 0 and a.ID = b.OWNER_ID

но выдает ошибку, SQL command not properly ended, и Википедия говорит: «Некоторые базы данных допускают нестандартное использование предложения FROM», из-за чего я полагаю, что это не поддерживается Oracle.

Вопросы

  • Что означает первая ошибка? HAS_PETS принадлежит ПОЛЬЗОВАТЕЛЯМ, который имеет первичный ключ. Я не вижу здесь таблиц без сохранения ключей.
  • Как я могу изменить свое утверждение так, чтобы оно выполнялось так, как я ожидаю?

Ответы [ 2 ]

3 голосов
/ 29 ноября 2011

Вы можете попробовать

UPDATE a SET HAS_PETS = 1
WHERE ID IN 
    (SELECT DISTINCT OWNER_ID FROM b) p

Это может быть быстрее при использовании вашего дополнительного условия (спасибо @ jadarnel27, заметившему это)

UPDATE a SET HAS_PETS = 1
WHERE HAS_PETS = 0 
  AND ID IN 
    (SELECT DISTINCT OWNER_ID FROM b) p
2 голосов
/ 29 ноября 2011

В соответствии с документацией Oracle , таблица с сохранением ключа - это та, где ключ таблицы сохраняется в объединении.

В этом примере таблица PETS является ключом сохранения, а таблица USERS - нет. Это связано с тем, что у каждого пользователя USER может быть несколько PET, и поэтому первичный ключ таблицы USERS может встречаться несколько раз в наборе результатов.

Поскольку таблица PETS сохраняется с ключом, вы можете использовать синтаксис обновления соединения, чтобы (например) обновить таблицу PETS с именем пользователя, но не можете обновить таблицу USERS информацией из PETS.

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