提问人:Kevin 提问时间:11/29/2011 最后编辑:Mahmoud GamalKevin 更新时间:11/29/2011 访问量:1718
基于依赖表更新表
Updating A Table Based On A Dependent Table
问:
设置
我有两张表,还有.USERS
PETS
每个用户都有一个 、 和 一个标志 ,如果用户拥有至少一只宠物,则为 1,否则为 0。ID
NAME
HAS_PETS
每个都有 、 和 。下面是创建脚本: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);
问题
有一次,许多宠物被添加到,但表的标志没有更新。在上面的示例数据中,Carol 拥有 Xerxes,但她的标志是 0。PETS
OWNER
HAS_PETS
我想写一个声明,如果主人有宠物,该声明将设置为 true。根据上述数据,它应该将 Carol 的标志设置为 1。
我试过了这个:HAS_PETS
HAS_PETS
update (
select *
from USERS a join PETS b
on a.HAS_PETS = 0 and a.ID = b.OWNER_ID
)
set HAS_PETS = 1
但它给出了一个错误,.Oracle 建议我 ,但除非我执行此联接,否则我无法确定哪些行需要更新。cannot modify a column which maps to a non key-preserved table
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
但它给出了一个错误,维基百科说“某些数据库允许非标准地使用 FROM 子句”,这让我相信 Oracle 不支持这一点。SQL command not properly ended
问题
- 第一个错误的含义是什么?HAS_PETS属于 USERS,它有一个主键。我在这里没有看到任何非键保留的表。
- 如何修改我的语句,使其按照我期望的方式执行?
答:
你可以试试
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
评论
WHERE
UPDATE
根据 Oracle 文档,保留键的表是表的键保留在联接中的表。
在此示例中,PETS 表是密钥保留,但 USERS 表不是。这是因为每个 USER 可能具有多个 PET,因此 USERS 表的主键可能会在结果集中多次出现。
由于 PETS 表保留键,因此可以使用更新联接语法(例如)使用 USER 的名称更新 PETS 表,但不能使用 PETS 中的信息更新 USERS 表。
评论