创建返回尚未声明的表的函数

时间:2018-05-30 10:14:02

标签: oracle plsql collections

我们的产品有几个组件可以单独安装并支持oracle。但我们不授予Create type权限。因此,在安装其中一个组件时,我需要让客户安装组件,添加Create type权限,然后运行我的组件。

在将创建函数的SQL文件中,我计划提供以下代码:

CREATE OR REPLACE FUNCTION get_some_data (input INT)
    RETURN my_table
AS
    my_table_var   my_table := my_table ();
    ret_code       INT := 0;
BEGIN
    ret_code := create_my_type_and_table ();

    IF 1 = ret_code
    THEN
        NULL; -- add some data to my_table_var here
    END IF;

    RETURN my_table_var;
END get_some_data;
/

函数create_my_type_and_table将使用execute immediate来创建记录和表类型。

显然,问题是因为函数get_some_data表示它将返回my_table,编译失败。

我想知道:

  • 有出路吗?

  • 我想创建和返回表的原因是因为我需要返回多个字段。所有这些都是int。有没有办法可以返回多维数组,也许系统集合?我尝试了sys.odcinumberlist,但我没有找到一种方法可以返回4个columned sys.odcinumberlist。

1 个答案:

答案 0 :(得分:0)

如果您想要一些匿名通用内容,可以使用TABLE OF [TYPE]

以下是如何构建table of number的示例,该"table of table of number"由另一种类型declare TYPE tableOfNumber is Table of Number; -- Define a row of numbers TYPE tableOfTableOfNumer is Table of tableOfNumber; -- define a table of rows tableMaster tableOfTableOfNumer := tableOfTableOfNumer(); -- init tables tableChild1 tableOfNumber := tableOfNumber(); tableChild2 tableOfNumber := tableOfNumber(); begin tableChild1.Extend; -- add a new number-field to our table tableChild1(1) := 0; -- set the value to the new field tableChild1.Extend; tableChild1(2) := 1; tableChild2.Extend; tableChild2(1) := 2; tableChild2.Extend; tableChild2(2) := 3; tableMaster.Extend; -- add a new 'row' to out table tableMaster(1) := tableChild1; -- fill the new 'row' with the fields tableMaster.Extend; tableMaster(2) := tableChild2; -- loop through our 'table' for r in 1 .. tableMaster.Count LOOP for c in 1 .. tableMaster(r).Count LOOP dbms_output.put_line(tableMaster(r)(c)); END LOOP; END LOOP; end; 使用。

与每种类型一样,您可以在模式中创建它们,以便在不同的plsql-blocks之间使用它或在函数中使用return-value。

CREATE TYPE tableOfNumber AS TABLE OF NUMBER;
CREATE TYPE tableOftableOfNumber AS TABLE OF tableOfNumber;

如果你想创建一个功能,你必须:

1。声明模式中的类型

(对用户的授予权)

CREATE OR REPLACE FUNCTION DINTER.MyFunction
RETURN tableOftableOfNumber
Is
    tableMaster tableOftableOfNumber := tableOftableOfNumber(); -- init tables
    tableChild1 tableOfNumber := tableOfNumber();
    tableChild2 tableOfNumber := tableOfNumber();
begin
    tableChild1.Extend; -- add a new number-field to our table 
    tableChild1(1) := 0; -- set the value to the new field
    tableChild1.Extend;
    tableChild1(2) := 1;
    tableChild2.Extend;
    tableChild2(1) := 2;
    tableChild2.Extend;
    tableChild2(2) := 3;
    tableMaster.Extend; -- add a new 'row' to out table
    tableMaster(1) := tableChild1; -- fill the new 'row' with the fields
    tableMaster.Extend;
    tableMaster(2) := tableChild2;

    RETURN tableMaster;

end MyFunction;
/

2。创建你的功能:

(这里的代码与plsql-block相同)

declare
    tableMaster tableOfTableOfNumber;
begin
    tableMaster := myfunction();
    -- loop through our 'table'
    for r in 1 .. tableMaster.Count
    LOOP
        for c in 1 .. tableMaster(r).Count
        LOOP
            dbms_output.put_line(tableMaster(r)(c)); 
        END LOOP;
    END LOOP;
end;

3。调用函数:

#!/path/to/anaconda2/bin/python
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import sys

val=int(sys.argv[1])

def drawV1(numOfNodes,FilePtr):
    np.random.seed(0)
    G = nx.Graph()
    for ii in range(1,numOfNodes+1):
        G.add_node(str(ii))
    nx.draw(G, with_labels = True)
    plt.savefig(FilePtr) # save as png

def drawV2(numOfNodes,FilePtr):
    np.random.seed(0)
    G2 = nx.Graph()
    for ii in range(1,numOfNodes+1):
        G2.add_node(str(ii))
    nx.draw(G2, with_labels = True)
    plt.savefig(FilePtr) # save as png


if val==1: # Problematic case
    drawV1(5,'V1_1_1.png')
    drawV1(10,'V1_1_2.png')
if val==2: # it is good when I draw only one figure
    drawV1(10,'V1_2_1.png')
if val==3: # problem again
    drawV1(10,'V1_3_1.png')
    drawV2(10,'V2_3_2.png')