Select 当结果可能为空时,如何选择PL/SQL中的变量?
考虑到查询可能不返回任何内容,那么在这种情况下,变量应该为null。有没有办法只运行一次查询来选择变量 目前,我无法直接在变量中执行Select 当结果可能为空时,如何选择PL/SQL中的变量?,select,plsql,Select,Plsql,考虑到查询可能不返回任何内容,那么在这种情况下,变量应该为null。有没有办法只运行一次查询来选择变量 目前,我无法直接在变量中执行选择,因为如果查询不返回任何内容,PL/SQL将抱怨变量未设置。我只能运行两次查询,第一次执行计数,如果计数为零,则将变量设置为null,如果计数为1,则选择变量 因此,代码如下所示: v_列我的_表。列%TYPE; v_计数器编号; 从my_表中选择计数(列)到v_计数器,其中。。。; 如果(v_计数器=0),则 v_列:=null; elsif(v_计数器=1)
选择,因为如果查询不返回任何内容,PL/SQL将抱怨变量未设置。我只能运行两次查询,第一次执行计数,如果计数为零,则将变量设置为null,如果计数为1,则选择变量
因此,代码如下所示:
v_列我的_表。列%TYPE;
v_计数器编号;
从my_表中选择计数(列)到v_计数器,其中。。。;
如果(v_计数器=0),则
v_列:=null;
elsif(v_计数器=1)则
从my_表中选择列进入v_列,其中。。。;
如果结束;
谢谢
更新:
我没有使用exception的原因是,在分配v_列
之后,我仍然有一些以下逻辑,并且我必须在exception部分使用goto
,以跳回以下代码。我有点犹豫goto
行。您只需将变量设置为NULL
即可处理找不到数据的异常。这样,只需要一个查询
v_column my_table.column%TYPE;
BEGIN
BEGIN
select column into v_column from my_table where ...;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := NULL;
END;
... use v_column here
END;
我建议使用游标。游标获取总是一行(除非您使用大容量集合),并且游标不会自动抛出未找到数据或太多行异常;尽管您可以在打开游标属性后检查该属性,以确定是否有行以及有多少行
declare
v_column my_table.column%type;
l_count pls_integer;
cursor my_cursor is
select count(*) from my_table where ...;
begin
open my_cursor;
fetch my_cursor into l_count;
close my_cursor;
if l_count = 1 then
select whse_code into v_column from my_table where ...;
else
v_column := null;
end if;
end;
或者更简单地说:
declare
v_column my_table.column%type;
cursor my_cursor is
select column from my_table where ...;
begin
open my_cursor;
fetch my_cursor into v_column;
-- Optional IF .. THEN based on FOUND or NOTFOUND
-- Not really needed if v_column is not set
if my_cursor%notfound then
v_column := null;
end if;
close my_cursor;
end;
我使用这种语法是为了灵活性和速度-
begin
--
with KLUJ as
( select 0 ROES from dual
union
select count(*) from MY_TABLE where rownum = 1
) select max(ROES) into has_rows from KLUJ;
--
end;
Dual返回1行,rownum添加0或1行,max()组正好为1。对于表中没有任何行,该值为0;对于任何其他行数,该值为1
我扩展where子句以按条件计数行,删除rownum以计数满足条件的行,并增加rownum以计数满足条件的行,直到达到一个限制 使用A是我最喜欢的方法
它比使用显式游标更安全,因为您不需要记住关闭它,所以不会“泄漏”游标。
您不需要“进入”变量,不需要“获取”,不需要捕获和处理“未找到数据”异常
试试看,你再也回不去了
v_column my_table.column%TYPE;
v_column := null;
FOR rMyTable IN (SELECT COLUMN FROM MY_TABLE WHERE ....) LOOP
v_column := rMyTable.COLUMN;
EXIT; -- Exit the loop if you only want the first result.
END LOOP;
COALESCE
将始终返回第一个非空结果。通过执行此操作,您将获得所需的计数或0:
select coalesce(count(column) ,0) into v_counter from my_table where ...;
用MAX怎么样?
这样,如果找不到数据,变量将设置为NULL,否则为最大值。
因为您期望0或1值,所以MAX应该可以使用
v_column my_table.column%TYPE;
select MAX(column) into v_column from my_table where ...;
我知道这是一条古老的线索,但我仍然认为回答它是值得的
select (
SELECT COLUMN FROM MY_TABLE WHERE ....
) into v_column
from dual;
使用示例:
declare v_column VARCHAR2(100);
begin
select (SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'DOES NOT EXIST')
into v_column
from dual;
DBMS_OUTPUT.PUT_LINE('v_column=' || v_column);
end;
从以上所有答案来看,似乎是最优雅、最简短的。我个人多次使用这种方法。最大或最小功能将同样很好地完成这项工作。下面是完整的PL/SQL,只需指定where子句
declare v_column my_table.column%TYPE;
begin
select MIN(column) into v_column from my_table where ...;
DBMS_OUTPUT.PUT_LINE('v_column=' || v_column);
end;
@Adam,我没有使用exception的原因是在分配了v_列
之后,我仍然有一些下面的逻辑,我必须在exception部分使用“goto”跳回下面的代码。我有点犹豫goto
行。@Sapience,这不是问题,只需将逻辑放在这个嵌套块的末尾。@Shannon:谢谢您的编辑。我自然会使用匿名PL/SQL块,所以我没有意识到这是不明确的。谢谢你的回复。但我试图避免的是对同一where子句运行两次查询,第一次是判断是否存在一个条件,第二次是将现有记录提取到一个变量。@sapicence:Gotcha,我忽略了你的第一句话。在这种情况下,使用cursor属性使这变得非常简单(我建议的第二个选项)。只需将实际查询写入游标(noCOUNT(*)
),打开游标并将结果提取到局部变量中。然后,使用%FOUND
属性确定所需状态。这样,您只需执行一次查询,不需要异常块,并避免使用SELECT。。进入
潜在异常。Count将始终返回一个数字,无需合并它。但这个问题并不是真正的计数问题。作者只是为了避免例外情况而获得计数。如果删除聚合函数,则coalesce将无助于避免找不到任何数据,因为可能没有行。此外,像这样将函数包装在列周围通常会跳过可能已使用的任何索引,因为编译器无法判断该函数是否会更改列值,从而使其在索引中无法查找,所以它根本不寻找任何索引。(您可以创建一个基于函数的索引来提供帮助,但实际上,谁知道该怎么做呢?)。它很好用。为了简单起见,我跳过了开始和结束部分。@Miki:我添加了一个示例来说明它是PLSQL,并且可以工作。我在这里看到了这种技术:当我将多个列写入变量时,它似乎不起作用。我得到了太多的值。谢谢你的评论!没错,它只适用于1列,因为标量子查询只能返回1个值。我希望有人能改变这一点……我利用这一技巧创建了一个漂亮的select查询。谢谢:(从dual中选择round(round(round(在('2018年5月30日,'c.column_date')之间的月份),0)/12,1)作为参数,当查询返回多行时也可以使用