如果在游标中未找到 table 中的 NULL 值

NULL values in a table if they're not found in a cursor

我正在尝试:

  1. 创建一个游标,获取商店中所有商品的当前价格。
  2. 我通过使用 MERGE 语句批量收集游标和循环更新插入 STORE_INVENTORY table.
  3. 现在我想将 STORE_INVENTORY table 中不在游标中的 PRICE 列清零。

第 3 步如何完成?我已经可以执行步骤 1 和 2,因为我已经更新或插入了从光标中拉出的项目。

这是一些示例数据:

有 3 个源 table 由外部方更新。我的objective就是把这三个数据源合并成一个单一的table.

来源TABLES

ITEM_DESCRIPTION
  ITEM_ID | TYPE 
  0       |  Kitchen
  1       |  Bath

ITEM_MANIFEST
  ITEM_ID | ORIGIN
  0       | USA
  1       | CHINA

ITEM_PRICE
  ITEM_ID | PRICE
  0       | 3.99
  1       | 2.99

目的地TABLE

STORE_INVENTORY 
  ITEM_ID | TYPE    | ORIGIN | PRICE
  0       | Kitchen | CHINA  | 3.99
  8       | Bath    | USA    | 2.99

因此,在我执行 SQL 程序后,源 table 将被更新到 STORE_INVENTORY 中,并且所有不在源 table 中的项目都有价格无效。我知道如何进行 Upsert 部分,但我不知道如何取消 STORE_INVENTORY table.

中已经存在的项目的价格

预期输出

STORE_INVENTORY
0 | Kitchen | USA   | 3.99
1 | Bath    | China | 2.99
8 | Bath    | USA   | NULL

我从这个例子中知道,如果 ITEM_ID 不在 SOURCE_TABLES 中的任何一个中,我就可以查找然后将其取消,但是如果有更复杂的逻辑来确定从源 table 中提取哪些项目? (这就是我想使用游标的原因)我想知道我是否可以与游标中不存在的内容进行比较?

正如所怀疑的那样,这只需要一个 MERGE 语句:

create table item_description 
as
select 0 item_id, 'Kitchen' type from dual union all
select 1 item_id, 'Bath' type from dual;

create table item_manifest
as
select 0 item_id, 'USA' origin from dual union all
select 1 item_id, 'CHINA' origin from dual;

create table item_price
as
select 0 item_id, 3.99 price from dual union all
select 1 item_id, 2.99 price from dual;

create table store_inventory
as
select 0 item_id, 'Kitchen' type, 'CHINA' origin, 3.99 price from dual union all
select 8 item_id, 'Bath' type, 'USA' origin, 2.99 price from dual;

select * from store_inventory;

   ITEM_ID TYPE    ORIGIN      PRICE
---------- ------- ------ ----------
         0 Kitchen CHINA        3.99
         8 Bath    USA          2.99

merge into store_inventory tgt
using (select coalesce(id.item_id, si.item_id) item_id,
              coalesce(id.type, si.type) type,
              coalesce(im.origin, si.origin) origin,
              ip.price
       from   item_description id
              inner join item_manifest im on (id.item_id = im.item_id)
              inner join item_price ip on (id.item_id = ip.item_id)
              full outer join store_inventory si on (si.item_id = id.item_id)) src
  on (src.item_id = tgt.item_id)
when matched then
  update set tgt.type = src.type,
             tgt.origin = src.origin,
             tgt.price = src.price
when not matched then
  insert (tgt.item_id, tgt.type, tgt.origin, tgt.price)
  values (src.item_id, src.type, src.origin, src.price);

commit;

select * from store_inventory;

   ITEM_ID TYPE    ORIGIN      PRICE
---------- ------- ------ ----------
         0 Kitchen USA          3.99
         8 Bath    USA              
         1 Bath    CHINA        2.99

我所做的只是首先编写 select 语句,该语句从源 tables 生成 item_id、类型、产地和价格的连接列表。

一旦我有了它,就只是对 store_inventory 进行完全外部连接的情况,以确保显示所有行,无论是新行还是现有行。

然后我对 item_id、type 和 origin 列进行了合并,这样即使该行仅存在于 store_inventory table 中,我们仍会看到这些详细信息已填充,但我保留了源行中的价格 - 如果它不存在,则为空。

然后只需将该查询的结果合并回 store_inventory table。

如果您对如何将 merge/update/insert 行放入 table 有疑问,请查看是否可以先编写一个 select 语句来生成您想要的结果。通常只需将该语句插入相关的 merge/update/insert 语句即可。