1

Scriptella での Oracle Sql クエリに関する 1 つの問題に直面しています。

私の意図は - PRODUCT テーブルからフェッチされた行 (where 句を使用して決定) ごとに PRODUCT_PRICE テーブルからいくつかの列データをフェッチする必要があり、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>

私の質問は - これは機能していません! ご覧のとおり、製品と店舗 ID に対応するデータが存在しない場合、product_id、store_id、および「価格」を PRODUCT_PRICE テーブルに挿入する必要があります。また、同じ商品と store_id の行が存在する場合は、価格のみを更新する必要があります。しかし、2 番目のクエリでフェッチされた結果セットに何も含まれていない場合、条件 "rownum==0" を持つスクリプトは機能しません。Oracleでこれをどのように達成できますか?

MySQL または SyBase データベースには、"if exists(select ....) / then something / else something" という構文があることは知っていますが、Oracle データベースには何も見つかりませんでした。私たちのプロジェクトはOracleに基づいているため、Oracleデータベースの選択基準に基づいてこの条件付きの挿入または更新を実現するにはどうすればよいですか??

PS - ここで「price」変数は、最初のクエリの前にすでに見つかりました。コードの関連部分のみを配置しました。

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 結合の機能を活用できます。次のソリューションでは、このタスクを達成するために必要なクエリは 1 つだけです。左外部結合を使用します。アイデアは、product_id、store_id で 2 つのテーブルを結合することです。product_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

これら 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 と count by price を適用する必要があります。

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 を使用すると、このアプローチをさらに最適化できると思います。そのため、すべてを 1 つの Oracle ステートメントで実行できますが、空腹の心に任せておきます。

于 2013-04-10T16:04:19.007 に答える