是否可以将条件传递给 Oracle 用户定义函数?
Posted
技术标签:
【中文标题】是否可以将条件传递给 Oracle 用户定义函数?【英文标题】:Is it possible to pass a condition to an Oracle user-defined function? 【发布时间】:2012-04-11 10:46:23 【问题描述】:我想知道是否可以将条件(布尔值)传递(任何方式都可以,也可以破解)Oracle 中的用户定义函数。
假设我想要类似的东西:
CREATE OR REPLACE FUNCTION SCHEMA.MY_FUNC (
condition IN ???,
my_value IN NUMBER) RETURN NUMBER IS
BEGIN
IF condition THEN
RETURN my_value + 1;
END IF;
RETURN my_value;
END;
【问题讨论】:
在函数之外测试条件,然后将 1 或 0 传递给函数? @PeterLang 我不能在纯 SQL 上下文中使用 BOOLEAN。 @lorenzo-s:这就是我在您的帖子中遗漏的信息。您尝试解决的具体问题是什么,为什么需要这个? @PeterLang 我只是在寻找比CASE WHEN [some complex condition] THEN 1 ELSE 0
更简洁的东西,用于将一些“标志”传递给某些函数,仅此而已。无论如何,似乎我没有机会,只能使用 CASE 或将条件的每个术语传递给函数本身。
【参考方案1】:
假设您希望能够从普通 SQL 调用它 - 否则您可以只使用 BOOLEAN
- 您可以传递一个固定值并改为解释它。 0/1、Y/N等常见;使用 1 作为真(以及其他任何作为假)例如:
CREATE OR REPLACE FUNCTION MY_FUNC (
condition IN NUMBER,
my_value IN NUMBER) RETURN NUMBER IS
BEGIN
IF condition = 1 THEN
RETURN my_value + 1;
END IF;
RETURN my_value;
END;
/
FUNCTION MY_FUNC compiled
select my_func(0, 42) from dual;
select my_func(1, 42) from dual;
MY_FUNC(0,42)
-------------
42
MY_FUNC(1,42)
-------------
43
如果你可以将表达式作为字符串传递,比如说,你可以用动态 SQL 来破解一些东西,我想:
CREATE OR REPLACE FUNCTION my_func (
condition IN varchar2,
my_value IN NUMBER) RETURN NUMBER IS
boolstr VARCHAR2(5);
BEGIN
EXECUTE IMMEDIATE 'SELECT CASE WHEN ' || condition
|| ' THEN ''true'' ELSE ''false'' END FROM dual' INTO boolstr;
IF boolstr = 'true' THEN
RETURN my_value + 1;
END IF;
RETURN my_value;
END;
/
你必须这样称呼:
select my_func('1=1', 42) from dual;
所以你必须将你的条件构建成一个字符串,比如:
select my_func(a ||'='|| b, 42) from <some table with a and b columns>;
这看起来相当笨拙,并且允许几乎任何东西作为条件传递,这当然可能是危险的(SQL 注入可能性,委婉地说)。如果只有某些“条件”,最好使用带有简单参数并找出布尔条件值来调用实际函数的函数包装器,这样你就可以调用my_func_eq(42, a, b)
之类的东西。
我还会考虑一个函数是否真的有必要——当然,这取决于函数在做什么,你可能可以在一个简单的查询中达到同样的效果,例如带有case语句。
【讨论】:
没有机会直接使用SELECT my_func(a = b)
或不是SELECT my_func(CASE WHEN a = b THEN 1 ELSE 0)
的条件?抱歉,我是 Oracle 新手... PS:函数创建后的/
符号是什么?我也在 Oracle doc 上看到它,但我无法得到它,我在测试过程中没有使用...
@loernzo-s - 我添加了一个版本,表明可以将字符串作为条件进行评估,但可能并不一定是一个好主意。正如 Peter 建议的那样,请详细说明您真正想做的事情,以及您认为需要这种结构的原因。
另外...您需要/
来获取要执行的 PL/SQL 块(在本例中为函数创建),至少在从 SQL*Plus 或 SQL Developer 运行它时。如果您将它放在脚本中,并且无论如何它都是最后执行的,但通常需要它,因此最好始终使用它以避免混淆。
我只是在寻找比CASE WHEN [some complex condition] THEN 1 ELSE 0
更简洁的东西,用于将一些“标志”传递给某些函数,仅此而已。无论如何,似乎我没有机会,只能使用 CASE 或将条件的每个术语传递给函数本身。
+1
: 如果真的有必要,我想我会把你的代码改成EXECUTE IMMEDIATE 'SELECT CASE WHEN ' || condition || ' THEN ''true'' ELSE ''false'' END FROM dual'
。这仍然会评估条件,但限制执行危险代码作为条件。以上是关于是否可以将条件传递给 Oracle 用户定义函数?的主要内容,如果未能解决你的问题,请参考以下文章