PL/SQL:在单个查询中选择多个变量

Tha*_*hla 0 oracle plsql

在 oracle 包的初始化部分,我尝试确定具有给定名称的某些对象的当前 ID。原因:该包用于多个数据库,这些对象的 ID 可能会有所不同,但它们的名称是不变的。

代码如下所示:

SELECT id INTO varCat FROM myTable WHERE Type = 'Object' AND Name = 'Cat';
SELECT id INTO varDog FROM myTable WHERE Type = 'Object' AND Name = 'Dog';
...
SELECT id INTO varMouse FROM myTable WHERE Type = 'Object' AND Name = 'Mouse';
Run Code Online (Sandbox Code Playgroud)

有没有办法优化查询,也许可以在单个查询中完成?

Ale*_*ole 5

您可以将它们与手动枢轴结合使用:

select max(case when name = 'Cat' then id end),
  max(case when name = 'Dog' then id end),
  max(case when name = 'Mouse' then id end)
into varCat, varDog, varMouse
from mytable
where type = 'Object'
and name in ('Cat', 'Dog', 'Mouse');
Run Code Online (Sandbox Code Playgroud)

快速演示:

create table mytable (id number, type varchar2(10), name varchar2(10));
insert into mytable (id, type, name) values (1, 'Object', 'Mouse');
insert into mytable (id, type, name) values (2, 'Object', 'Cat');
insert into mytable (id, type, name) values (3, 'Object', 'Dog');

set serveroutput on
declare
  varCat mytable.id%type;
  varDog mytable.id%type;
  varMouse mytable.id%type;
begin
  select max(case when name = 'Cat' then id end),
    max(case when name = 'Dog' then id end),
    max(case when name = 'Mouse' then id end)
  into varCat, varDog, varMouse
  from mytable
  where type = 'Object'
  and name in ('Cat', 'Dog', 'Mouse');

  dbms_output.put_line('varCat: ' || varCat);
  dbms_output.put_line('varDog: ' || varDog);
  dbms_output.put_line('varMouse: ' || varMouse);
end;
/

varCat: 2
varDog: 3
varMouse: 1

PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)

如果类型和名称的组合不唯一,那么您当前的代码会出错(行太多);这将无声地选择最高的 ID。

如果您还获得名称可能相同的其他类型的 ID,您也可以在 case 表达式中包含该类型:

select max(case when type = 'Object' and name = 'Cat' then id end),
  max(case when type = 'Object' and name = 'Dog' then id end),
  max(case when type = 'Object' and name = 'Mouse' then id end)
  -- , ... other combinations you want to get
into varCat, varDog, varMouse --, ... other variables
from mytable
where (type = 'Object' and name in ('Cat', 'Dog', 'Mouse'))
or ... ;
Run Code Online (Sandbox Code Playgroud)

  • (a) 几乎可以肯定,因为你只上桌一次;但它可能有点取决于索引和选择性。并且 (b) 因此,如果您只需要几行,则不会考虑进行全表扫描;否则,它将评估表中的所有数据 - 或至少所有对象 - 在 case 表达式中,除了那些将在不存在的“else”条件中丢失。优化器可能足够聪明来避免这种情况,但我不这么认为。如果您正在评估大部分行,而不仅仅是一小部分,那么您可能不需要该过滤器。 (2认同)