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

时间:2013-04-10 11:51:29

标签: sql oracle scriptella

我在Scriptella面临一个关于Oracle Sql查询的问题。

我的意图是 - 我必须从PRODUCT_PRICE表中获取从PRODUCT表中获取的每一行(使用where子句确定)的一些列数据,然后如果从PRODUCT_PRICE获取的数据不包含任何内容或为null,那么我必须插入一个新的对应于产品和价值的价格列将id存储到表中,否则如果存在对应于product&amp ;;的行。商店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>

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

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

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

1 个答案:

答案 0 :(得分: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>

虽然此解决方案应该正常工作,但您可以利用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

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

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

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

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

然后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>

我认为通过使用MERGE INTO可以进一步优化该方法,因此所有内容都可以在一个Oracle语句中完成,但我会将其留给饥饿的人。