Oracle:如何为“SELECT * FROM tab WHERE name IN (function())”创建返回值的函数

Posted

技术标签:

【中文标题】Oracle:如何为“SELECT * FROM tab WHERE name IN (function())”创建返回值的函数【英文标题】:Oracle: How to create a function returning values for a "SELECT * FROM tab WHERE name IN (function())" 【发布时间】:2014-08-27 10:06:14 【问题描述】:

我有一个我无法解决的问题。也许你对如何解决它有一个想法。

我确实有一个像这样的给定参数表:

P_VALUE     P_NAME 
----------- ---------- 
X85         A_03      
XH1         A_04      
XH2         A_04      
XH3         A_04           
C84         A_05      

如您所见,有多个条目的参数。目前这个参数是这样使用的:

SELECT * FROM tablex
WHERE code IN (SELECT p_value 
               FROM parameter_table
               WHERE p_name LIKE 'A_04');

由于查询非常大,这些参数子选择经常使用。我试图在 Oracle 中实现一个函数来获取我的参数。只要每个参数只有 1 行,它就可以很好地工作。当我想在“IN-Statements”中使用它时,它不起作用,因为函数只返回一个值。

--WORKS
SELECT * FROM tablex
WHERE code = (f_get_param('A_03'));

--DOES NOT WORK
SELECT * FROM tablex
WHERE code IN (f_get_param('A_04'));

请注意,对于普通的 SQL 语句,我需要它,因此过程无法正常工作,因为它们只适用于 PL/SQL。

如果有好的想法或帮助,我将不胜感激!

【问题讨论】:

寻找Table Functions? 查看我对第一个答案的评论。 据我所知,您希望减少 select 语句中的代码行数 【参考方案1】:

使用集合。这里有一个例子http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html

【讨论】:

嗨 Isalgueiro 和 Maheswaran,我已经尝试过 Collections/NestedTables,但这不会避免编写子选择。我仍然需要写... in (select * from table(f_function('A_04'))) 而不是... in (f_function('A_04'))。在这种情况下,我可以简单地坚持我的子选择。感谢您的第一次尝试。 :-) 欢迎提供更多想法!【参考方案2】:

从技术上讲,您可以通过这种方式使用该函数,但这样做会导致 tablex 上的代码列上不使用索引,并可能影响性能。使用函数索引可以降低性能影响

 CREATE OR REPLACE FUNCTION f_get_param(p_value1 IN VARCHAR2,p_name1 in VARCHAR2) return NUMBER
 DETERMINISTIC
 IS 
 l_count NUMBER;
 BEGIN 
 select count(1) into l_count from parameter_table where p_value =p_value1 
 and p_name=p_name1;
 if l_count > 0
 then 
 return 1;
 else
 return 0;
 end if;
 end f_get_param;

并像这样使用 select 语句

SELECT * FROM tablex
WHERE f_get_param(code,'A_04')=1;

编辑 1:- 还可以降低数据库 10.2 及更高版本中的性能影响如果 parameter_table 是静态的,您可以在函数中使用 DETERMINISTIC 子句来表示如果每次使用相同的参数调用该函数,则该函数返回相同的值

请查找link on the article关于在SELECT语句中使用函数

【讨论】:

【参考方案3】:
--DOES NOT WORK

SELECT * FROM tablex
WHERE code IN (f_get_param('A_04'));

-- Try this
SELECT * FROM tablex
WHERE code IN (select * from TABLE(f_get_param('A_04')));

您必须将一个集合“投射”到 SQL TABLE 上。 此外,当您使用 cast 时,您还可以使用内部关节:

SELECT * FROM tablex join TABLE(f_get_param('A_04') using (code);

我认为 - 通常 - 您的问题称为“动态 where 子句”。尝试在 AskTom 上搜索一些关于它的文章。

【讨论】:

【参考方案4】:

我认为您的问题的实际解决方案是简单地连接两个表并创建适当的索引,而不是调用 PL/SQL 函数:

SELECT x.* FROM tablex x, parameter_table p
   WHERE x.code = p.p_value
   AND p.p_name LIKE '%A_04%';

请注意,您的 LIKE 子句中也存在语义错误。您没有使用 % 符号,因此您的 LIKE 'A_04'= 'A_04'

相同

【讨论】:

以上是关于Oracle:如何为“SELECT * FROM tab WHERE name IN (function())”创建返回值的函数的主要内容,如果未能解决你的问题,请参考以下文章

关于oracle数据库查询1

SQL语句中模糊查询中不区分大小写怎么写?如:select × from table where number like‘%PK%’

Oracle 访问数据库字段和表名有大小写区分吗?

abap中select * from 后面能跟变量吗?

Oracle中如何用sql处理分页

oracle中是否有except函数: select * from a except select * from b