The Setup
I have two tables, USERS and PETS.
each user has an ID, a NAME, and a flag HAS_PETS, which is 1 if the user owns at least one pet, and 0 otherwise.
Each pet has an ID, a NAME, and an OWNER_ID. Here is the creation script:
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);
The Problem
At one point, many pets were added to PETS, but the OWNER table’s HAS_PETS flag was not updated. In the sample data above, Carol owns Xerxes, but her flag is 0.
I want to write a statement which will set HAS_PETS to true if the owner has a pet. With the above data, it should set Carol’s HAS_PETS flag to 1.
I tried this:
update (
select *
from USERS a join PETS b
on a.HAS_PETS = 0 and a.ID = b.OWNER_ID
)
set HAS_PETS = 1
but it gives an error, cannot modify a column which maps to a non key-preserved table. Oracle recommends that I Modify the underlying base tables directly, but I can’t identify which rows need updating unless I do this join.
Googling around prompted me to try this alternative syntax:
update a
set a.HAS_PETS = 1
from USERS a join PETS b
on a.HAS_PETS = 0 and a.ID = b.OWNER_ID
but it gives an error, SQL command not properly ended, and Wikipedia says “Some databases allow the non-standard use of the FROM clause”, leading me to believe this isn’t supported by Oracle.
The Questions
- What is the meaning of the first error? HAS_PETS belongs to USERS, which has a primary key. I don’t see any non key-preserved tables here.
- How can I modify my statement so that it executes the way I expect it to?
You could try
It could be faster using your additional condition (thanks to @jadarnel27 to noticed that)