【问题标题】:Oracle SQL & scriptella: How to do conditional insertion or updation based on select criterion?Oracle SQL & scriptella:如何根据选择标准进行条件插入或更新?
【发布时间】:2013-04-10 11:51:28
【问题描述】:

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

我的意图是 - 我必须为从 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数据库中的选择标准来实现这种有条件的插入或更新?

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

【问题讨论】:

    标签: sql oracle scriptella


    【解决方案1】:

    您可以使用 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 语句中完成,但我会把它留给饥饿的头脑。

    【讨论】:

    • 感谢您提出这个问题。我已经有 3 年没有做繁重的 SQL 了。这对我来说是个好习惯!
    猜你喜欢
    • 1970-01-01
    • 2020-09-08
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2010-11-30
    • 2012-06-16
    相关资源
    最近更新 更多