为什么null在plsql中的语句中是正确的

发布于 2025-02-11 06:00:04 字数 324 浏览 0 评论 0原文

大家好,我想知道有人知道为什么这个PL/SQL代码会给结果错误,但是我在示出了结果会提高异常,但是我没有明白,为什么像NVL这样的NVL保护我们免受我所知的无效价值。

declare
i_send_type varchar2(100) := null;
begin
    if nvl(i_send_type,'') <> 'cash' and nvl(i_send_type,'') <> 'card'  then
      raise_application_error(-20032,'o_userMessage');
  end if; 
end;

Hello guys I was wondering anyone knows why this pl/sql code give a result false but I was excpeting the result will be raise exception but I didn't get it why like that nvl protect us from null value as I know.

declare
i_send_type varchar2(100) := null;
begin
    if nvl(i_send_type,'') <> 'cash' and nvl(i_send_type,'') <> 'card'  then
      raise_application_error(-20032,'o_userMessage');
  end if; 
end;

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

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

发布评论

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

评论(2

┼── 2025-02-18 06:00:04

那是因为null的空字符串 - oracle中的一个空字符串是等效的,这意味着nvl实际上什么也没做;它说

如果i_send_typenull,然后取空字符串(即null再次)

在这种情况下,您比较了null null 到'cash''card'使用&lt;&gt;,但null无法比较。方式 - 您必须使用是null不是null


那么,该怎么办?

一个选项:不要在nvl中使用空字符串,但例如'x'(或其他无法是i_send_type的其他字符串:

SQL> declare
  2    i_send_type varchar2(100) := null;
  3  begin
  4      if nvl(i_send_type,'x') <> 'cash' and nvl(i_send_type,'x') <> 'card'  then
  5        raise_application_error(-20032,'o_userMessage');
  6      end if;
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-20032: o_userMessage
ORA-06512: at line 5


SQL>

另一个(更好的)选项:检查 - 正如我所说 - 变量的值是否为null

SQL> declare
  2    i_send_type varchar2(100) := null;
  3  begin
  4      if i_send_type not in ('cash', 'card') or i_send_type is null then
  5        raise_application_error(-20032,'o_userMessage');
  6      end if;
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-20032: o_userMessage
ORA-06512: at line 5


SQL>

That's because an empty string - in Oracle - is equivalent of NULL, which means that NVL actually did nothing; it said

if i_send_type is NULL, then take empty string (i.e. NULL again) instead

In that case, you compared NULL to 'cash' and 'card' using <>, but NULL can't be compared that way - you have to use IS NULL or IS NOT NULL.


So, what to do?

One option: don't use empty string in NVL but e.g. 'x' (or some other string that can't be contents of i_send_type:

SQL> declare
  2    i_send_type varchar2(100) := null;
  3  begin
  4      if nvl(i_send_type,'x') <> 'cash' and nvl(i_send_type,'x') <> 'card'  then
  5        raise_application_error(-20032,'o_userMessage');
  6      end if;
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-20032: o_userMessage
ORA-06512: at line 5


SQL>

Another (better) option: check - as I said - whether variable's value IS NULL:

SQL> declare
  2    i_send_type varchar2(100) := null;
  3  begin
  4      if i_send_type not in ('cash', 'card') or i_send_type is null then
  5        raise_application_error(-20032,'o_userMessage');
  6      end if;
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-20032: o_userMessage
ORA-06512: at line 5


SQL>
奈何桥上唱咆哮 2025-02-18 06:00:04

为什么此PL/SQL代码给出结果false

。它给出了结果不正确。

不正确的二进制逻辑中的false仅相同,而有两个可能的值是正确的或错误。在数据库(不仅是Oracle)中,它们使用三元逻辑,并且可以具有以下值:true,false或未知(null)。

例如,如果您比较= 运算符:

=xynull
xtruefalsenull
y false true null nullnull
nullnullnull

然后null =&lt; nothing&gt;&lt; nothing&gt; = null始终给出结果null(而不是false),因为您无法确定未知是否等于其他任何内容(甚至是另一个未知),因为值未知。

对于&lt;&gt;运算符,逻辑与上述相似,true and false交换在输出中,但结果仍然是null(而不是truefalse)当两个输入为null时。


在Oracle中,空字符串''null so nvl(i_send_type,'')nvl( i_send_type,null)i_send_type相同,因此您最终获得了比较null&lt;&gt;&gt; '现金'或null&lt;&gt; 'card'导致null(而不是truefalse)。


要解决它,您可以反转操作员并在中使用=,然后使用else条件:

DECLARE
  i_send_type varchar2(100) := null;
BEGIN
  IF i_send_type IN ('cash', 'card') THEN
    -- Do nothing
    NULL;
  ELSE
    raise_application_error(-20032,'o_userMessage');
  END IF; 
END;
/

或者,如果要骑行在else的情况下,您必须使用null是null :

DECLARE
  i_send_type varchar2(100) := null;
BEGIN
  IF i_send_type IS NULL OR i_send_type NOT IN ('cash', 'card') THEN
    raise_application_error(-20032,'o_userMessage');
  END IF; 
END;
/

why this pl/sql code give a result false

It does not. It gives a result as not true.

Not true is only the same as false in binary logic where there are two possible values, true or false. In databases (and not just Oracle), they use trinary logic and can have the values: true, false or unknown (NULL).

For example, if you compare the = operator:

=xyNULL
xTRUEFALSENULL
yFALSETRUENULL
NULLNULLNULLNULL

Then NULL = <anything> or <anything> = NULL always gives the result NULL (and not false) because you cannot tell if an unknown is equal to anything else (even another unknown) as the values are unknown.

For the <> operator, the logic is similar to above with TRUE and FALSE swapped in the output but the result is still NULL (and not TRUE or FALSE) when either input is NULL.


In Oracle, the empty string '' is identical to NULL so nvl(i_send_type,'') is the same as nvl(i_send_type,NULL) which is the same as i_send_type so you end up with the comparisons NULL <> 'cash' OR NULL <> 'card' which results in NULL (and not TRUE or FALSE).


To solve it, you can reverse the operator and use = or IN and then use an ELSE condition:

DECLARE
  i_send_type varchar2(100) := null;
BEGIN
  IF i_send_type IN ('cash', 'card') THEN
    -- Do nothing
    NULL;
  ELSE
    raise_application_error(-20032,'o_userMessage');
  END IF; 
END;
/

or, if you want to get rid of the ELSE then you have to explicitly check for NULL values using IS NULL:

DECLARE
  i_send_type varchar2(100) := null;
BEGIN
  IF i_send_type IS NULL OR i_send_type NOT IN ('cash', 'card') THEN
    raise_application_error(-20032,'o_userMessage');
  END IF; 
END;
/
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文