0

我有一个用 Oracle 9i(版本 9.2.0.4.0)编写的简单函数来模拟内联 IF。对于那些感兴趣的人,这是代码:

create or replace
FUNCTION IIF  
   (testExpression NUMBER,
    trueResult NUMBER,
    falseResult NUMBER)
RETURN NUMBER   
AS
BEGIN
   /*
      A simple in-line IF function for use with SQL queries. If the test
      expression evaluates to any non-zero value, it is considered to be 
      true, and the trueResult is returned. Otherwise, falseResult is
      returned.
   */   
   IF (testExpression is null) or (testExpression = 0) THEN
      return falseResult;
   ELSE
      return trueResult;
   END IF;
END IIF;

这不是火箭科学。现在,这里有个大谜团:如果我执行以下 SQL 语句,一切都很好,并且完全按照我的预期工作:

SELECT IIF(1, 'true', 'false') FROM DUAL;
SELECT IIF(0, 'false', 'true') FROM DUAL;

但是,以下内容会从 Oracle 生成一个非常奇怪的错误:

SELECT IIF((0 = 1), 'false', 'true') FROM DUAL;

该错误如下:

ORA-00907: missing right parenthesis.

显然,事实并非如此。会有人碰巧对这种奇怪的事情有一个解释吗?

目前需要大量的自我控制来克制自己不要将 Oracle 服务器扔出窗外。甲骨文似乎充斥着这些无聊的东西。

编辑:我必须使用某种魔术语法在选择语句中使用相等运算符吗?

4

5 回答 5

6

也许你可以解释你想要做什么。我认为您正在寻找CASEorDECODE功能,但我不能确定。由于某种原因,您似乎正在违背 SQL 语言的本质。

发生错误是因为 Oracle 不希望select查询子句中包含关系运算符:

SQL> SELECT IIF(1>7, 0, 1) FROM DUAL;
SELECT IIF(1>7, 0, 1) FROM DUAL
            *
ERROR at line 1:
ORA-00907: missing right parenthesis

SQL> SELECT 1=0 FROM DUAL;
SELECT 1=0 FROM DUAL
        *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

请参阅这篇询问汤姆文章

于 2009-01-15T23:13:35.997 回答
3

你要

SELECT CASE WHEN *expr* then 'true' else 'false' end col_alias FROM DUAL;

或用于简单的相等测试

SELECT DECODE(*val1*,*val2*,'true','false') col_alias FROM dual;

这将比退出到 PL/SQL 函数执行得更好。您的方法不起作用的原因有很多。

  1. 布尔值不是 Oracle 数据类型。

  2. 它们是 PL/SQL 数据类型,但即便如此,也没有隐式转换为数字(零假,非零真)

  3. 没有“表达式”数据类型,因此 SQL 引擎无法将表达式传递给 PL/SQL。

  4. 即使您将表达式作为字符串传递给 PL/SQL,PL/SQL 引擎也无法动态评估字符串中的表达式。它必须将字符串构建成动态 SQL 语句并动态执行,返回结果(以有效的 SQL 数据类型,如字符串或数字)。

于 2009-01-16T02:15:32.337 回答
1
  1. Oracle 数据库中没有 BOOLEAN 类型,所以不能使用像“(1=0)”这样的表达式。
  2. 即使存在 BOOLEAN 类型,您也已将第一个参数声明为 NUMBER 类型。你必须给它传递一个数字,或者可以隐式转换为一个的东西。
  3. 最后,我不明白除了“无效数字”之外,您的任何示例实际上如何产生任何内容,因为您的第二个和第三个参数也不能转换为数字。
于 2009-01-15T23:56:38.763 回答
0

从未与 oracle 合作过,我无法直接提供任何合理的建议,但是查看声明可能是 oracle 在从布尔值推断数字时遇到问题?..

IIF 签名需要一个 NUMBER 作为第一个参数,并且在调用中您正在传递一个 BOOL 评估。

这只是一个想法。

于 2009-01-15T22:59:59.050 回答
0

除了decode和case,还有nvl。

于 2009-01-16T16:14:11.797 回答