在多个查询PL / SQL中从一个表或另一个表中选择数据

时间:2014-05-16 19:17:10

标签: oracle plsql

提出问题的最简单方法是使用假设情景。

假设我们有3张桌子。 Singapore_Prices,Produce_val和Bosses_unreasonable_demands。

所以价格是一个非常简单的表格。包含名称的项目列和包含数字的价格列。

Produce_Val也是简单的2列表。键入包含产品类型的列(水果或蔬菜),然后键入名称列(番茄,菠萝等)

Bosses_unreasonable_demands只包含一列Fruit,它可以包含一些水果的名称。

行?确定。

所以,我的老板要我写一个查询,在他不合理的需求表中返回每个水果的价格。很简单。但是,如果他的表中没有任何条目,他只是想让我输出produce_val中存在的所有水果的价格。

现在,假设我不知道设计这个愚蠢的假设系统的DBA在哪里(因此无法让他解决这个问题),我们的查询将如下所示:

if <Logic to determine if Bosses demands are empty>
Then
select Item, Price
from Singapore_Prices
where Item in (select Fruit from Bosses_Unreasonable_demands)
Else
select Item, Price
from Singapore_Prices
where Item in (select Name from Produce_val where type = 'Fruit')
end if;

(好吧,我们选择那些变量,然后输出变量,可能是批量收集的恶作剧,但这并不重要)

哪个有效。它完全是功能性的,即使我们将它扩展到除新加坡以外的其他2000家商店,也不会很慢。 (好吧,没有比接触2000个表的任何其他东西慢)但是,我仍然在做两个几乎完全相同的不同选择语句。每当我的手指击中ctrl-V时,我的Comp Sci老师就会在他们的坟墓中滚动。我可以把这个代码减半,只做一个select语句。我知道我可以。

我只是没有世俗的想法。我不能使用游标作为in语句,我不能使用嵌套表或varrays,我不能使用巧妙制作的字符串,我......我只是...我不知道。我不知道该怎么做。有办法吗?它存在吗?

或者我必须永久地复制/粘贴吗?

3 个答案:

答案 0 :(得分:0)

我认为你可以使用嵌套表。假设您有一个模式级嵌套表类型FRUIT_NAME_LIST(使用CREATE TYPE定义)。

SELECT fruit
  BULK COLLECT INTO my_fruit_name_list
  FROM bosses_unreasonable_demands
;

IF my_fruit_name_list.count = 0 THEN
  SELECT name
    BULK COLLECT INTO my_fruit_name_list
    FROM produce_val
    WHERE type='Fruit'
  ;
END IF;

SELECT item, price
  FROM singapore_prices
  WHERE item MEMBER OF my_fruit_name_list
;

(或WHERE item IN (SELECT column_value FROM TABLE(CAST(my_fruit_name_list AS fruit_name_list))如果你更喜欢那样的话)

答案 1 :(得分:0)

您最好的选择是动态SQL,因为您无法参数化表名或列名。

您将拥有一个SQL查询模板,具有确定要查询的表和列的逻辑,然后将它们混合在一起并执行。

另一个方法,(仍然有很多ctrl-v代码)是使用集合构建UNION ALL:

select 1st query where boss_condition
union all
select 2nd query where not boss_condition

答案 2 :(得分:0)

试试这个:

SELECT *
  FROM (SELECT s.*, 'BOSS' AS FRUIT_SOURCE
          FROM BOSSES_UNREASONABLE_DEMANDS b
          INNER JOIN SINGAPORE_FRUIT_LIST s
            ON s.ITEM = b.FRUIT
          CROSS JOIN (SELECT COUNT(*) AS BOSS_COUNT
                        FROM BOSSES_UNREASONABLE_DEMANDS)) x
  UNION ALL
       (SELECT s.*, 'NORMAL' AS FRUIT_SOURCE
          FROM PRODUCE_VAL p
          INNER JOIN SINGAPORE_FRUIT_LIST s
            ON (s.ITEM = p.NAME AND
                s.TYPE = 'Fruit')
          CROSS JOIN (SELECT COUNT(*) AS BOSS_COUNT
                        FROM BOSSES_UNREASONABLE_DEMANDS)) n
  WHERE (BOSS_COUNT > 0 AND FRUIT_SOURCE = 'BOSS') OR
        (BOSS_COUNT = 0 AND FRUIT_SOURCE = 'NORMAL')

分享并享受。