【问题标题】:Oracle stored function - pass table name as parameterOracle 存储函数 - 将表名作为参数传递
【发布时间】:2015-07-09 15:21:38
【问题描述】:

我正在尝试在 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;

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

【问题讨论】:

  • 您遇到了什么错误。你肯定也总是想发布错误。
  • 我不一定认为这是问题所在,但为了安全起见,您可以将带有连接的 sql 字符串放在括号中:(execute immediate ('select count(*) as jumlah from ' || namatabel))。另外,在from 后面加一个空格(这可能是个问题)。
  • 对不起,我的错.. 这里是错误 Error(6,21): PLS-00103: Encountered the symbol "IMMEDIATE" when expecting 以下之一:. ( ) , * @ % & = - + at in is mod 余数 not rem => or != or ~= >= and or like2 like4 likec介于 || multiset member submultiset 在“IMMEDIATE”之前插入符号“(”以继续。

标签: oracle stored-procedures plsql stored-functions


【解决方案1】:
  1. EXECUTE IMMEDIATE 语句中的FROM 关键字 后面缺少一个空格
  2. EXECUTE IMMEDIATE 语句存在语法错误。您缺少 INTO 子句。
  3. 您不能在 CURSOR FOR LOOP 内使用 EXECUTE IMMEDIATE。基本上,您不会从上面第 2 点中提到的立即执行语句中返回任何内容
  4. LOOP迭代语法 不正确。语法为FOR r IN 1..COUNT()

修改你的代码后,它的样子是这样的:

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>

【讨论】:

    【解决方案2】:
    1. 您的立即执行将只返回一个值,即计数,那么有什么要循环的呢?
    2. 另外,我不确定执行立即是否适用于隐式游标。
    3. 在您的 SQL 中,from 关键字后面似乎没有空格。

    试试这样的:

    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;
    

    【讨论】:

    • 又是我的错,感谢您提醒我:) 但错误仍然相同,并且在我运行后“执行”和“立即”之间有一条红色下划线。你认为这是错误吗?
    • hmm .. 我试图用“if”替换“for循环”,但仍然没有运气:(
    • 查看我的更新。我肯定认为光标在使用立即执行时可能会出现问题。
    • 像魅力一样工作!谢谢!但是你错过了那里的“结束如果”:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 2021-12-24
    • 2023-03-20
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多