【问题标题】:A generic procedure that can execute any procedure/function可以执行任何过程/功能的通用过程
【发布时间】:2013-10-10 17:21:26
【问题描述】:

输入
包名称 (IN)
过程名称(或函数名称)(IN)
一个由整数索引的表,它将包含将用于执行过程(IN/OUT)的值。

例如
假设我们要执行下面的过程

utils.get_emp_num(emp_name IN VARCHAR
                  emp_last_name IN VARCHAR
                  emp_num OUT NUMBER
                  result  OUT VARCHAR);

我们将创建的过程将作为输入:

package_name = utils
procedure_name = get_emp_num
table = T[1] -> name
        T[2] -> lastname
        T[3] -> 0   (any value) 
        T[4] -> N   (any value)

run_procedure(package_name,
              procedure_name,
              table)

主过程应该返回已经在输入中设置的同一张表,但带有过程的执行结果

table =  T[1] -> name
         T[2] -> lastname
         T[3] -> 78734 (new value)
         T[4] -> F     (new value)

有什么想法吗?

【问题讨论】:

  • 当你应该描述你的问题时,听起来你已经跳到了一个解决方案上。我无法想象这是执行任何操作的好方法......那么,你的问题是什么?
  • Lua 脚本将调用 Pro*c 函数,该函数将执行该过程并将数据表(结果)返回给 Lua 函数以供进一步使用。我没有找到从 Lua 脚本获取过程结果的更好方法。
  • 是的,但是您是否需要使用完全相同的调用来调用 every 过程。根据您需要调用的过程更改您的 Pro*C 调用可能更正常,而不是更改数据库以相同地调用所有内容。
  • Proc 是编译语言,Proc 将包含所有用户的主要处理(相同),而 Lua 脚本将用作插件(它取决于用户,它会有所不同),脚本将是一个简单的 .Lua 文件(不是二进制文件),只需向 Proc 程序提供 PATH 即可调用。这是为了避免为每个用户提供特定版本的 Proc 代码,并允许 Lua 脚本在不修改 Pro*C 代码的情况下执行任何过程/函数。

标签: plsql oracle11g


【解决方案1】:

您可以使用 EXECUTE IMMEDIATE 来实现。基本上,您构建一个如下形式的 SQL 语句:

sql := 'BEGIN utils.get_emp_num(:1, :2, :3, :4); END;';

然后你执行它:

EXECUTE IMMEDIATE sql USING t(1), t(2), OUT t(3), OUT t(4);

现在棘手的部分来了:对于每个数量的参数和 IN/OUT 组合,您需要一个单独的 EXECUTE IMMEDIATE 语句。而要弄清楚参数的个数和方向,需要先查询ALL_ARGUMENTS表。

您可以通过将整个表作为绑定参数而不是每个表元素的单独绑定参数来简化它。但我还没有完全弄清楚你会怎么做。

接下来您应该考虑的是:您使用的表 T 的元素将有一个类型:VARCHAR、NUMBER 等。因此,当前既有数字又有字符串的混合将不起作用。

顺便说一句:你为​​什么想要这样的动态调用机制?

【讨论】:

  • 用户可以编写自己的 Lua 脚本,向 DB 请求数据,Lua 将调用 PRO*C 函数执行该过程并将结果(表)返回给 Lua 脚本。我被要求做同样的想法,创建一个允许执行任何查询的过程,使用 DBMS_SQL 包很容易,但使用过程/函数我发现它更棘手。
【解决方案2】:

从 all_arguments 表中获取 argument_name、data_type、in_out 和位置

构建 PLSQL 块

DECLARE
    loop over argument_name and create the declare section
    argument_name data_type if in_out <> OUT then := VALUE OF THE INPUT otherwise NULL
BEGIN

--In the case of function create an additional argument 
function_var:= package_name.procedure_name( loop over argument_name);

--use a table of any_data, declare it as global in the package

if function then
    package_name.ad_table.EXTEND;
    package_name.ad_table(package_name.ad_table.LAST):= function_var;
end if

--loop over argument_name IF IN_OUT <> IN
package_name.ad_table.EXTEND;
package_name.ad_table(package_name.ad_table.LAST):= 

if data_type = VARCHAR2 then := ConvertVarchar2(argument_name)
else if NUMBER then ConvertNumber 
else if DATE then ConvertDate
...

END;

结果存储在表中。 要获得价值,请使用 Access* 函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 2012-04-30
    • 2021-03-10
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    相关资源
    最近更新 更多