1

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

我的意图是 - 我必须从 PRODUCT_PRICE 表中为从 PRODUCT_PRICE 获取的每一行(使用 where 子句确定)获取一些列数据,然后如果从 PRODUCT_PRICE 获取的数据不包含任何内容或为空,那么我必须为将产品和商店 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>

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

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

PS - 在第一次查询之前已经找到“价格”变量。我只放了代码的相关部分。

4

1 回答 1

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 属性将为空。假设您有以下输入:

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

这 2 个表的左外连接如下所示:

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

然后你需要申请 group by 并按价格计算:

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 语句中完成,但我将把它留给饥饿的头脑。

于 2013-04-10T16:04:19.007 回答