当结果可能为空时,如何选择 PL/SQL 中的变量?

发布于 2024-12-01 09:38:44 字数 650 浏览 2 评论 0原文

有没有办法只运行一次查询来选择变量,考虑到查询可能不返回任何内容,那么在这种情况下变量应该为空。

目前,我无法直接select into 变量,因为如果查询不返回任何内容,PL/SQL 会抱怨变量未设置。我只能运行查询两次,第一次执行计数,如果计数为零,则将变量设置为 null,如果计数为 1,则选择变量。

所以代码应该是这样的:

v_column my_table.column%TYPE;
v_counter number;
select count(column) into v_counter from my_table where ...;
if (v_counter = 0) then
    v_column := null;
elsif (v_counter = 1) then
    select column into v_column from my_table where ...;
end if;

谢谢。

更新: 我没有使用异常的原因是在分配v_column之后我仍然有一些以下逻辑,并且我必须在异常部分使用goto跳回以下内容代码。我对goto行有点犹豫。

Is there a way in to just run a query once to select into a variable, considering that the query might return nothing, then in that case the variable should be null.

Currently, I can't do a select into a variable directly, since if the query returns nothing, the PL/SQL would complain variable not getting set. I can only run the query twice, with the first one do the count and if the count is zero, set the variable to null, and if the count is 1, select into the variable.

So the code would be like:

v_column my_table.column%TYPE;
v_counter number;
select count(column) into v_counter from my_table where ...;
if (v_counter = 0) then
    v_column := null;
elsif (v_counter = 1) then
    select column into v_column from my_table where ...;
end if;

thanks.

Update:
The reason I didn't use exception is I still have some following logic after assigning the v_column, and I have to use goto in the exception section to jump back to the following code. I'm kind of hesitate of goto lines.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

ら栖息 2024-12-08 09:38:44

您只需将变量设置为 NULL 即可处理 NO_DATA_FOUND 异常。这样,只需要一次查询。

    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;

You can simply handle the NO_DATA_FOUND exception by setting your variable to NULL. This way, only one query is required.

    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;
南薇 2024-12-08 09:38:44

我知道这是一个旧线程,但我仍然认为值得回答它。

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;

I know it's an old thread, but I still think it's worth to answer it.

select (
        SELECT COLUMN FROM MY_TABLE WHERE ....
        ) into v_column
from dual;

Example of use:

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;
秋意浓 2024-12-08 09:38:44

使用 MAX 怎么样?
这样,如果没有找到数据,则变量设置为 NULL,否则设置为最大值。
由于您期望 0 或 1 值,因此 MAX 应该可以使用。

v_column my_table.column%TYPE;
select MAX(column) into v_column from my_table where ...;

What about using MAX?
That way if no data is found the variable is set to NULL, otherwise the maximum value.
Since you expect either 0 or 1 value, MAX should be OK to use.

v_column my_table.column%TYPE;
select MAX(column) into v_column from my_table where ...;
岁月无声 2024-12-08 09:38:44

我最喜欢使用 游标 FOR LOOP 语句方法来做到这一点。

它比使用显式游标更安全,因为您不需要记住关闭它,因此您不能“泄漏”游标。

您不需要“进入”变量,不需要“FETCH”,不需要捕获和处理“NO DATA FOUND”异常。

尝试一下,你永远不会回去。

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;

Using an Cursor FOR LOOP Statement is my favourite way to do this.

It is safer than using an explicit cursor, because you don't need to remember to close it, so you can't "leak" cursors.

You don't need "into" variables, you don't need to "FETCH", you don't need to catch and handle "NO DATA FOUND" exceptions.

Try it, you'll never go back.

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;
尘曦 2024-12-08 09:38:44

从上面的所有答案来看,Björn 的答案似乎是最优雅和简短的。我个人多次使用过这种方法。 MAX 或 MIN 函数同样可以很好地完成这项工作。完整的 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;

From all the answers above, Björn's answer seems to be the most elegant and short. I personally used this approach many times. MAX or MIN function will do the job equally well. Complete PL/SQL follows, just the where clause should be specified.

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;
万劫不复 2024-12-08 09:38:44

我建议使用光标。游标获取始终是单行(除非您使用批量集合),并且游标不会自动抛出 no_data_found 或 Too_many_rows 异常;尽管您可以在打开后检查游标属性以确定是否有一行以及有多少行。

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;

I would recommend using a cursor. A cursor fetch is always a single row (unless you use a bulk collection), and cursors do not automatically throw no_data_found or too_many_rows exceptions; although you may inspect the cursor attribute once opened to determine if you have a row and how many.

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;

Or, even more simple:

    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;
蝶舞 2024-12-08 09:38:44

我使用这种语法是为了灵活性和速度 -

    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 以对满足条件的行进行计数直至达到限制。

I use this syntax for flexibility and speed -

    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 returns 1 row, rownum adds 0 or 1 rows, and max() groups to exactly 1. This gives 0 for no rows in a table and 1 for any other number of rows.

I extend the where clause to count rows by condition, remove rownum to count rows meeting a condition, and increase rownum to count rows meeting the condition up to a limit.

自此以后,行同陌路 2024-12-08 09:38:44

COALESCE 将始终返回第一个非空结果。通过这样做,你将得到你想要的计数或 0:

select coalesce(count(column) ,0) into v_counter from my_table where ...;

COALESCE will always return the first non-null result. By doing this, you will get the count that you want or 0:

select coalesce(count(column) ,0) into v_counter from my_table where ...;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文