create table items(item_pk integer, pgid integer, prod_id integer, PRIMARY KEY(item_pk));
create table products(prod_id integer, version integer, pgid integer, flag char(1), PRIMARY KEY(prod_id));
insert into items(item_pk, pgid) values (1, 21);
insert into items(item_pk, pgid) values(2, 31);
insert into products(prod_id, version, pgid, flag) values (11, 101, 21, 'Y');
insert into products(prod_id, version, pgid, flag) values (22, 101, 21, 'N');
insert into products(prod_id, version, pgid, flag) values(33, 101, 31, 'N');
declare
prod_version NUMBER := :1 ;
begin
update items i set i.prod_id = (
select p.prod_id from products p where
p.version = prod_version and p.pgid = i.pgid and rownum =1
order by p.flag desc
) where i.xyz is null
commit; end;
产品表有两个条目 - 伪(flag ='Y')和实际(flag ='N')。
如果没有伪产品,需要获取实际产品。
上述查询导致编译错误。 内部查询可能会返回多个记录,但我只需要第一个记录(即'Y'记录。如果找不到'Y'rec,需要'N'rec)。
答案 0 :(得分:0)
有点矫枉过正但应该有效:
select prod_id
from (
select p.prod_id, ROW_NUMBER() OVER (ORDER BY p.flag DESC) as rn
from products p
where p.version = prod_version and p.pgid = i.pgid
)
where rn=1
答案 1 :(得分:0)
您需要在更新查询中选择其他选项。我想它需要像这样;
update items i set i.prod_id = (
select prod.id from (
select p.prod_id,rownum rn from products p where
p.version = prod_version and p.pgid = i.pgid
order by p.flag desc) x
where x.rn=1
) where i.xyz is null
答案 2 :(得分:0)
我没有任何ide可用来检查我的语法。我是从文本编辑器这样做的,所以可能存在错误。
我总是尽量避免在查询中使用任何类型的rownum,所以这可以使用子查询来处理'N'值。
declare
prod_version NUMBER := :1 ;
begin
update items i set i.prod_id = (select p.prod_id
from products p
where p.version = prod_version
and p.pgid = i.pgid
and (p.flag = 'Y'
or (p.flag = 'N' and 0 = (select count(*)
from products p2
where p2.version = prod_version
and p2.pgid = i.pgid
and p2.flag = 'Y')
)
)
)
where i.xyz is null
commit;
end;
但是,您总是可以使用plsql并执行类似的操作。
declare
temp_prod_id number;
prod_version NUMBER := :1 ;
begin
for v_rec in (select id, pgid from items where xyz is null) loop
begin
select prod_id into temp_prod_id from products p
where p.version = prod_version
and p.pgid = v_rec.pgid
and p.flag = 'Y';
exception
when no_data_found then
select prod_id into temp_prod_id from products p
where p.version = prod_version
and p.pgid = v_rec.pgid
and p.flag = 'N';
-- this assumes there's always an 'N' record if not wrap this select with exception handling.
end;
update items i set i.prod_id = temp_prod_id
where items.id = v_rec.id;
commit;
end loop;
end;
就像我上面说过的那样,我可以自由地处理这个,所以请仔细检查语法。