设置
我有两个表,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
表的HAS_PETS
标记未更新。在上面的示例数据中,Carol拥有Xerxes,但她的旗帜为0。
我想写一个声明,如果主人有宠物,会将HAS_PETS
设置为true。根据上述数据,它应将Carol的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
,但除非我这样做,否则我无法确定哪些行需要更新。
谷歌搜索提示我尝试这种替代语法:
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不支持它。
答案 0 :(得分:3)
你可以尝试
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
答案 1 :(得分:2)
根据Oracle documentation,密钥保留表是表中的密钥保留在连接中的表。
在此示例中,PETS表是密钥保留,但USERS表不是。这是因为每个USER可能有多个PET,因此USERS表的主键可能会在结果集中多次出现。
由于PETS表是密钥保留的,您可以使用更新连接语法(例如)使用USER的名称更新PETS表,但不能使用来自PETS的信息更新USERS表。