Oracle存储函数 - 传递表名作为参数

时间:2015-04-30 04:26:45

标签: oracle stored-procedures plsql stored-functions

我试图在Oracle中创建一个存储函数来计算表行...我想让表名动态,所以我把它作为参数传递,存储的函数代码看起来像这样

create type tes_jml_obj is object(jumlah integer);
create type tes_jml_table is table of tes_jml_obj;
create or replace function jumlahBaris(namatabel varchar)
return tes_jml_table
is
  tabel tes_jml_table := tes_jml_table();
begin
  for r in (execute immediate 'select count(*) as jumlah from' || namatabel)
  loop
    tabel.extend;
    tabel(1) := tes_jml_obj(r.jumlah);
  end loop;
  return tabel;
end;

但是当我执行它时,它会返回错误。我错过了什么吗?这是动态获取表行的正确方法吗?

2 个答案:

答案 0 :(得分:3)

  1. EXECUTE IMMEDIATE语句中 FROM关键字后缺少空格
  2. EXECUTE IMMEDIATE 语句有语法错误。您缺少 INTO 子句。
  3. 您不能在 CURSOR FOR LOOP 中使用EXECUTE IMMEDIATE。基本上,如上面第2点所述,您从执行立即声明
  4. LOOP 迭代语法不正确。语法为FOR r IN 1..COUNT()
  5. 在纠正您的代码之后,这就是它的样子:

    SQL> CREATE OR REPLACE TYPE TES_JML_OBJ IS OBJECT(JUMLAH NUMBER)
      2  /
    
    Type created.
    
    SQL> CREATE OR REPLACE TYPE TES_JML_TABLE IS TABLE OF TES_JML_OBJ
      2  /
    
    Type created.
    
    SQL> CREATE OR REPLACE
      2    FUNCTION jumlahBaris(
      3        namatabel VARCHAR2)
      4      RETURN tes_jml_table
      5    IS
      6      TABEL TES_JML_TABLE := TES_JML_TABLE();
      7      cnt NUMBER;
      8    BEGIN
      9      EXECUTE IMMEDIATE 'select count(*) as jumlah from ' || NAMATABEL INTO CNT;
     10      FOR R IN 1..CNT
     11      LOOP
     12        TABEL.EXTEND;
     13        TABEL(R) := TES_JML_OBJ(R);
     14        dbms_output.put_line(TES_JML_OBJ(R).jumlah);
     15      END LOOP;
     16      RETURN tabel;
     17    END;
     18    /
    
    Function created.
    
    SQL> SHO ERR
    No errors.
    

    所以,函数编译时没有错误。让我们执行,然后看输出

    SQL> SET SERVEROUTPUT ON
    SQL> SELECT JUMLAHBARIS('EMP') FROM DUAL;
    
    JUMLAHBARIS('EMP')(JUMLAH)
    --------------------------------------------------------------------------------
    TES_JML_TABLE(TES_JML_OBJ(1), TES_JML_OBJ(2), TES_JML_OBJ(3), TES_JML_OBJ(4), TE
    S_JML_OBJ(5), TES_JML_OBJ(6), TES_JML_OBJ(7), TES_JML_OBJ(8), TES_JML_OBJ(9), TE
    S_JML_OBJ(10), TES_JML_OBJ(11), TES_JML_OBJ(12), TES_JML_OBJ(13), TES_JML_OBJ(14
    ))
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SQL>
    

答案 1 :(得分:2)

  1. 你的执行立即只会返回一个值,即计数,那么循环的是什么?
  2. 此外,我不确定执行立即是否使用隐式游标。
  3. 在您的SQL中,您似乎在from关键字之后没有空格。
  4. 尝试这样的事情:

    create or replace function jumlahBaris(namatabel varchar)
    return tes_jml_table
    is
      tabel tes_jml_table := tes_jml_table();
      the_count integer;
      the_sql varchar(100);
    begin
      the_sql := 'select count(*) as jumlah from ' || namatabel;
      execute immediate the_sql INTO the_count;
    
      if the_count IS NOT NULL THEN
          tabel.extend;
          tabel(1) := tes_jml_obj(the_count);
      end if;
      return tabel;
    end;