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"变量已在第一个查询之前找到.我只放了代码的相关部分.
您可以使用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语句中完成,但我会把它留给饥饿的人.