Oracle 9i:据说缺少右括号
Posted
技术标签:
【中文标题】Oracle 9i:据说缺少右括号【英文标题】:Oracle 9i: Supposedly missing right parenthesis 【发布时间】:2009-01-15 22:54:02 【问题描述】:我有一个用 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 服务器扔出窗外。甲骨文似乎充斥这些无聊的东西。
编辑:我必须使用某种魔术语法在 select 语句中使用相等运算符吗?
【问题讨论】:
您不能在选择语句的选择列表中使用关系运算符。 【参考方案1】:也许您可以解释一下您要做什么。我认为您正在寻找 CASE
或 DECODE
函数,但我不能确定。您似乎出于某种原因正在违背 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
见this Ask Tom article。
【讨论】:
首先,感谢您对这篇文章的指点(尽管我认为汤姆是为了争论而争论,并且表现出非常的顽固倾向)。我现在明白为什么它不起作用了。 (续) 也就是说,我想这样做的原因是为了在我重构的一些非常长、复杂的 SQL 语句中保持简洁,并且为了清楚起见,我想将它们分解。令我震惊的是,你不能在 Oracle 中做这样的事情。再说一次,我真的不应该感到惊讶。 我仍然不确定为什么需要这样做。 IFF 函数有何帮助?根据我的经验,很长、很复杂的 SQL 语句应该重新格式化而不是重构。【参考方案2】:你想要
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 函数执行得更好。 您的方法不起作用的原因有很多。
布尔值不是 Oracle 数据类型。
它们是 PL/SQL 数据类型,但即便如此,也没有隐式转换为数字(零假,非零真)
没有“表达式”数据类型,因此 SQL 引擎无法将表达式传递给 PL/SQL。
即使将表达式作为字符串传递给 PL/SQL,PL/SQL 引擎也无法动态计算字符串中的表达式。它必须将字符串构建成动态 SQL 语句并动态执行,返回结果(以有效的 SQL 数据类型,如字符串或数字)。
【讨论】:
【参考方案3】:-
Oracle 数据库中没有 BOOLEAN 类型,因此不能使用“(1=0)”之类的表达式。
即使存在 BOOLEAN 类型,您也已将第一个参数声明为 NUMBER 类型。您必须向其传递一个数字,或者可以隐式转换为一个的数字。
最后,我不明白您的任何示例实际上如何产生除“无效数字”之外的任何内容,因为您的第二个和第三个参数也无法转换为数字。
【讨论】:
【参考方案4】:我从未使用过 oracle,我无法直接提供任何合理的建议,但查看声明可能是 oracle 在从布尔值推断数字时遇到问题?..
IIF 签名需要一个 NUMBER 作为第一个参数,并且在调用中您传递的是 BOOL 评估。
这只是一个想法。
【讨论】:
【参考方案5】:除了decode和case,还有nvl。
【讨论】:
以上是关于Oracle 9i:据说缺少右括号的主要内容,如果未能解决你的问题,请参考以下文章