关于退货声明的 Oracle 文档

Posted

技术标签:

【中文标题】关于退货声明的 Oracle 文档【英文标题】:Oracle documentation on return statement 【发布时间】:2015-02-13 14:39:59 【问题描述】:

它在哪里说“return”语句上的 oracle 函数返回 null。例如,这里是一个简单的函数:

create or replace FUNCTION FOO RETURN NUMBER AS 
BEGIN
  RETURN;
  -- is return null the same as return?
END FOO;

编辑

上述函数不会像 Alex Poole 报告的那样编译。因此,函数必须始终具有返回值,例如数字、日期、blob、clob、varchar2 或 null。它不能只包含“return”。因此,return 在 oracle 中与 return null 不同。

我真正想知道的是它在哪里声明如果函数具有返回某些数据类型(数字、日期、varchar2、blob 或 clob)的签名并且它的主体包含“return null”语句,为什么允许这样做,为什么它可以返回null。我想这与脚本语言相同,例如php

function foo($i)

  if( $i > 0 )
    return $i;
  return null; // return is the same as return null. Tested in PHP.

当然,这种行为在 C# 中是不允许的,例如:

static int foo() return null;
Error 1 Cannot convert null to 'int' because it is a non-nullable value type

【问题讨论】:

第二个问题:oracle 中的null 和PHP 中的null 不太一样。在 oracle 中,与null 的每个比较都是false,所以( null > 0)(null == 0)(null < 0) 或与(null > '0') 相同的都是false。在 PHP 中的 afaik 取决于上下文,与数字零相比,null 可能评估为零并且条件可以变为 true 再次考虑 PHP 应该是这样的:( null == 0) 计算结果为 (false == false) 计算结果为 (true)。另一方面,( null === 0) 应该评估为false,因为数据类型也必须匹配。暂时无法测试。无论如何,我更喜欢 Oracles 空逻辑 ;) 在 Oracle 中不是这样 - (null > 0)(null = 0)(null < 0) 都评估为未知(因此是 null),而不是 false。 Oracle 中的布尔逻辑实际上是三值逻辑——truefalsenull——你必须记住要么迎合或消除 null 情况的可能性。 你显示的内容无法编译;你会得到PLS-00503: RETURN <value> statement required for this return from function。你只能有一个简单的RETURN 没有表达式in a pipelined function 或一个过程。文档没有说明“return 与 return null 相同”,因为它不是...... @AlexPoole 你当然是对的。嗯..应该先测试函数是否编译。 【参考方案1】:

它在哪里说“return”语句上的 oracle 函数返回 null

它没有在任何地方这么说,因为它不是真的。如果it is pipelined,您只能在函数中使用简单的return 而不是return <expression>,即数据已经由管道机制返回,并且返回只是表明控制(而不是数据)应该返回到呼叫者,召集者。您还可以在过程中使用普通的return。您的示例函数无法编译 - 因为没有表达式,您会得到 PLS-00503: RETURN <value> statement required for this return from function

函数中return的行为是described in the PL/SQL subprogram documentation,还有更多关于the return statement的细节,其中提到了expression

当 RETURN 语句在流水线表函数中时可选。当 RETURN 语句在任何其他函数中时是必需的。 RETURN 语句在过程或匿名块中时不允许。

RETURN 语句将表达式 的值赋给函数标识符。因此,表达式的数据类型必须与函数的RETURN子句中的数据类型兼容。

所以您修改后的问题实际上是在询问最后一句话;为什么无论声明的返回数据类型如何,您都可以分配null。但是您可以将 null 分配给大多数数据类型,并且正如 Boneist 指出的那样,大多数数据类型的变量都被初始化为 null。将数字变量设置为 null 是有效的。该文档页面前面的一行说:

RETURN 语句将指定的值赋给函数标识符

... 当您调用函数时,return 语句非常有效地将表达式评估为调用者变量的任何值赋值。 (显然这是一个简单的视图;可能有多个级别的调用者,并且您可能从普通 SQL 调用它,因此没有 PL/SQL 分配,而且内部可能更复杂)。

只要变量是可以为null的类型,就没有违规。虽然它并没有像您希望的那样明确设置 - 更重要的是没有什么说您不能返回 null。如果是这种情况,那将是在正常数据类型限制之上对函数返回的限制。


有点跑题了,也有例外;如果你的数据类型是restricted to not-null values,比如simple_integer,那么返回null的函数是有效的:

create or replace FUNCTION FOO RETURN NUMBER AS 
BEGIN
  RETURN NULL;
END FOO;
/

FUNCTION FOO compiled

...但是调用它并尝试将值分配给受约束的变量将失败:

declare
  n simple_integer := 0;
begin
  n := foo;
end;
/

ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 4

如果你在函数声明中使用受约束的数据类型,你就不能显式返回 null:

create or replace FUNCTION FOO RETURN SIMPLE_INTEGER AS 
BEGIN
  RETURN NULL;
END FOO;
/

FUNCTION FOO compiled
Errors: check compiler log

show_errors 显示:

3/10           PLS-00382: expression is of wrong type
3/3            PL/SQL: Statement ignored

您仍然可以返回一个 评估 为 null 的表达式,编译器无法捕获该表达式(例如 RETURN 1 * NULL),但在运行它时仍然会出现错误:

declare
  n number;
begin
  n := foo;
end;
/

ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "***.FOO", line 3
ORA-06512: at line 4

【讨论】:

测试了你所有的案例。欺骗编译器的好技巧。空值意味着变量没有值。它不同于具有值空间“”的变量。特别是在 sql 中,行是可选的(可为空的),这意味着就像提到的那样,它可以没有价值。这与例如 C# 不同,其中 int a 的默认值为 0(它也不能有 null 值,不会编译)。 Null 表示该值是未知的,有些人可能认为这在语义上与没有值不同,可能是 *8-)。但是,是的,不同于零或空格; Oracle 也将空字符串视为 null,布尔值甚至可以为 null。我会说 C# int 的行为类似于 Oracle 的 simple_integer 在您在问题中显示的分配中;除了 Oracle 类型没有默认值外,你必须在声明它时分配一些东西,并且不能让它默认为 null。 PHP 版本的行为更像pls_integer,因为它允许为空。也许吧。 请阅读mariadb.com/kb/en/sql-99/the-meaning-of-null - null 表示缺少的值,要么是因为我们不知道它,要么是因为它不适用。 NULL / 未知或 NULL / 不适用。【参考方案2】:

我认为您不会在文档中明确针对函数找到这样的声明。但是,如果您在this bit of the documentation about declarations 中看到By default, variables are initialized to NULL...。因此,如果不初始化返回值,会自动为NULL。

ETA:哈哈,我应该先测试该函数,根据 Alex 的评论,它无法编译。但我认为不将变量定义为 null 的一般原则仍然存在于其他地方 *:-)

【讨论】:

尽管如此,您仍然会使用RETURN <expr>,而不仅仅是RETURN。不确定我是否真的理解这个问题 *8-) 确实;我必须记得在将来回复之前测试一下! *;-)

以上是关于关于退货声明的 Oracle 文档的主要内容,如果未能解决你的问题,请参考以下文章

需要退货声明吗? - 编码新手

React JS:渲染的钩子比预期的要少。这可能是由于意外提前退货声明造成的

Oracle EBS PO退货失败

渲染的钩子比预期的要少。这可能是由于意外提前退货声明造成的。基于状态的条件渲染组件

退货还是运营商?

银联支付接口之退货