使用 Oracle PLSQL 从动态选择的表中合并唯一值的更有效方法
Posted
技术标签:
【中文标题】使用 Oracle PLSQL 从动态选择的表中合并唯一值的更有效方法【英文标题】:More Efficient Way To Merge Unique Values From Dynamically Selected Tables using Oracle PLSQL 【发布时间】:2011-05-16 20:53:48 【问题描述】:给定一个声明的 PLSQL 过程
PROCEDURE GET_DISTINCT_TIMES(dtypes IN VARCHAR2, start IN NUMBER, end IN NUMBER
distinct_times_cursor OUT SYS_REFCURSOR)
地点:
'Dtypes' 是一个逗号分隔的字符串,每个值对应于我要检索的一般数据类型。 一种数据类型可能对应一个或多个不同的表需要检索不同的时间 “开始”和“结束”是我查询的两次我编写了一些实现,这些实现使用 Unions 动态创建 SQL,以从每个表中提取唯一的时间值。但是,由于 'Dtypes' 参数的动态特性,我不得不在循环控制中生成此 SQL,并且无法找到实现绑定变量的方法。
我认为失去绑定变量的好处可能会导致查询花费的时间超过必要的时间
所以我想知道,有没有办法:
当绑定变量的数量与传入过程的参数完全可变时,将绑定变量与动态创建的 SQL 字符串相关联。 采用不同的方法,对于每个 dtype - 执行另一个存储过程或 SQL 语句,存储每个查询的记录集,然后合并唯一结果并将游标分配给新结果诚然,我是 PLSQL 编程的新手,还没有机会获得关于该语言的良好参考/书籍。任何 cmets、见解或建议的读数也将不胜感激。
【问题讨论】:
为什么不传入一个 varchar2 的表而不是逗号分隔的列表?此外,更多的程序主体会有所帮助 【参考方案1】:看到这个SO question。您可以使用 DBMS_SQL 包绑定不同数量的绑定变量。
另一种可能性是使用pipelined table function。对于每个 dtype,您将执行一个存储过程或 SQL 语句并使用PIPE ROW
输出结果。如果您仍然需要引用游标中的结果,可以使用SELECT * FROM TABLE(pipelined_function())
。
【讨论】:
感谢您提供这些链接,我昨天开始尝试实现流水线表方法,但从朋友那里发现了一个更适合我的解决方案。虽然这些链接提供了丰富的信息,但我感谢您的意见!【参考方案2】:我四处询问,我的一个朋友想出了一个我今天成功实施的解决方案。
基本上,我将整个 PLSQL 块动态创建为 VARCHAR2,然后使用 EXECUTE IMMEDIATE 分配绑定变量。这种方法的好处是我现在可以按名称而不是按位置分配绑定变量。
这是我的意思的一个例子:
var rs_cursor refcursor
DECLARE
start_tm CONSTANT PLS_INTEGER := 989452800;
end_tm CONSTANT PLS_INTEGER := 989452820;
plsql_block VARCHAR(1024);
BEGIN
plsql_block := 'BEGIN ' ||
'OPEN :rs_cursor FOR ' ||
' SELECT TIME ' ||
' FROM TBL_1 ' ||
' WHERE TIME BETWEEN :start_tm AND :end_tm ' ||
' UNION ' ||
' SELECT TIME ' ||
' FROM TBL_2 ' ||
' WHERE TIME BETWEEN :start_tm AND :end_tm ' ||
' ORDER BY TIME; ' ||
'END;';
EXECUTE IMMEDIATE plsql_block USING IN OUT :rs_cursor, IN start_tm, IN end_tm
END;
/
print rs_cursor
start_tm 和 end_tm 只需要传入一次,但适用于 PLSQL 块内的多个绑定
我的实际实现与此完全不同,但它使用 EXECUTE IMMEDIATE 绑定变量的特定功能按名称允许我根据提供给过程的任何数据类型动态创建 SQL 块。
【讨论】:
以上是关于使用 Oracle PLSQL 从动态选择的表中合并唯一值的更有效方法的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SQL 或 PLSQL 将多行数据插入 Oracle 中的表中?
如何使用plsql导出oracle数据建表语句,存储过程,视图.以及表中数据