Oracle SQL&scriptella:如何根据选择标准进行条件插入或更新?

use*_*450 1 sql oracle scriptella

我在Scriptella中面临有关Oracle Sql查询的一个问题.

我的意图是 - 我必须从PRODUCT_PRICE表中获取从PRODUCT表中获取的每一行(使用where子句确定)的一些列数据,然后如果从PRODUCT_PRICE获取的数据不包含任何内容或为null,那么我必须为此插入新列对应于产品和商店ID的价格值进入表格,否则如果存在对应于产品和商店ID的行,那么我必须更新价格.

以下代码应该清除我所描述的逻辑 -

<query connection-id="db">
select PRODUCT_ID as "product_id1", STORE_ID as "store_id1" from PRODUCT
  <query connection-id="db">
  select REGULAR_PRICE, PRODUCT_ID as "product_id2", STORE_ID as "store_id2" from PRODUCT_PRICE where PRODUCT_ID=?product_id1 and STORE_ID=?store_id1
    <script connection-id="db" if="rownum==0">
    insert into PRODUCT_PRICE(REGULAR_PRICE, PRODUCT_ID, STORE_ID) values(?price, product_id1, store_id1)
    </script>
    <script connection-id="db" if="rownum gt 0">
    update REGULAR_PRICE=?price where PRODUCT_ID=?product_id2 and STORE_ID=?store_id2
    </script>
  </query>
<query>
Run Code Online (Sandbox Code Playgroud)

我的问题是 - 这不起作用!如您所见,如果没有与产品和商店ID相对应的数据,我必须将product_id,store_id以及'price'插入到PRODUCT_PRICE表中.另外,如果存在一行相同的产品和store_id,我只需要更新价格.但是当在第二个查询中获取的结果集不包含任何内容时,条件为"rownum == 0"的脚本不起作用.那怎样才能在Oracle中实现这一目标?

在MySQL或SyBase数据库中,我知道有一种叫做"if exists(select ....)/ then then/else something"的语法,但我在Oracle数据库中找不到任何东西.如何根据Oracle数据库中的选择标准实现此条件插入或更新,因为我们的项目基于Oracle?

PS - 这里"price"变量已在第一个查询之前找到.我只放了代码的相关部分.

ejb*_*boy 5

您可以使用count()函数来实现它:

<query connection-id="db">
   select PRODUCT_ID as "product_id1", STORE_ID as "store_id1" from PRODUCT
   <query connection-id="db">
       select COUNT(*) as Price_Count from PRODUCT_PRICE where PRODUCT_ID=?product_id1 and STORE_ID=?store_id1
       <script connection-id="db" if="Price_Count==0">
           insert into PRODUCT_PRICE(REGULAR_PRICE, PRODUCT_ID, STORE_ID) values(?price, product_id1, store_id1)
       </script>
       <script connection-id="db" if="Price_Count gt 0">
           update REGULAR_PRICE=?price where PRODUCT_ID=?product_id1 and STORE_ID=?store_id1
      </script>
  </query>
<query>
Run Code Online (Sandbox Code Playgroud)

虽然此解决方案应该正常工作,但您可以利用SQL连接的强大功能.以下解决方案仅需要单个查询即可完成此任务.我将使用左外连接.这个想法是你通过product_id,store_id加入2个表.如果product_price表中没有匹配项,则相应的price属性将为null.想象一下,您有以下输入:

select * from product;
PRODUCT_ID      STORE_ID  
1               1
2               1
3               1

select * from product_price;
PRODUCT_ID      STORE_ID    PRICE  
2               1           100
2               1           150
3               1           200
Run Code Online (Sandbox Code Playgroud)

这两个表的左外连接看起来像:

select p.product_id, p.store_id , pp.price   from product p LEFT OUTER JOIN product_price pp ON p.product_id =pp.product_id  and p.store_id =pp.store_id;

PRODUCT_ID      STORE_ID    PRICE  
1   1   null
2   1   100
2   1   150
3   1   200
Run Code Online (Sandbox Code Playgroud)

然后你需要申请分组并按价格计算:

select p.product_id, p.store_id , count(pp.price) as Prices_Count   from product p LEFT OUTER JOIN product_price pp ON p.product_id =pp.product_id  and p.store_id =pp.store_id group by (p.product_id, p.store_id)
PRODUCT_ID      STORE_ID    Prices_Count  
1   1   0
3   1   1
2   1   2
Run Code Online (Sandbox Code Playgroud)

然后,XML变得微不足道,更重要的是它应该更快,因为数据库连接比任何外部客户端更高效.

  <query connection-id="db">
       select p.product_id, p.store_id , count(pp.REGULAR_PRICE) as Prices_Count   from product p LEFT OUTER JOIN product_price pp ON p.product_id =pp.product_id  and p.store_id =pp.store_id group by (p.product_id, p.store_id)

       <script connection-id="db" if="Prices_Count==0">
         insert into PRODUCT_PRICE(REGULAR_PRICE, PRODUCT_ID, STORE_ID) values(?price, product_id, store_id)
       </script>
       <script connection-id="db" if="Prices_Count gt 0">
          update REGULAR_PRICE=?price where PRODUCT_ID=?product_id and STORE_ID=?store_id
        </script>
  </query>
Run Code Online (Sandbox Code Playgroud)

我认为通过使用MERGE INTO可以进一步优化该方法,因此一切都可以在一个Oracle语句中完成,但我会把它留给饥饿的人.