如何在存储过程中动态传递表名 - ORACLE [重复]

Posted

技术标签:

【中文标题】如何在存储过程中动态传递表名 - ORACLE [重复]【英文标题】:How to pass table name dynamically in stored procedure - ORACLE [duplicate] 【发布时间】:2019-12-24 18:04:52 【问题描述】:

我想创建一个存储过程,它接受表名作为参数并在过程中动态传递它。例如:我想将表名 'DATA.WORK_CPG' 作为参数传递给存储过程。

这是实际过程

create or replace PROCEDURE Proc_Sample
(
ApplicationID IN varchar2,
CType IN varchar2,
WBName IN varchar2,
WBList OUT SYS_REFCURSOR 
)AS 
BEGIN
OPEN WBList 
FOR

  SELECT 
    WO.RECORDNUMBER  AS RECORDNUMBER,
  FROM DATA.ASSIGN_WB WB 
  INNER JOIN DATA.WORK_CPG WO ON WO.PZINSKEY = WB.PXREFOBJECTKEY 
  INNER JOIN COMMON.REF_APPLICATION RA ON RA.APPLICATIONNAME = WB.PXAPPLICATION 
  WHERE RA.APPLICATIONID = ApplicationID AND WB.ASSIGNEDID IN ( select regexp_substr(WBName,'[^,]+', 1, level) from dual
  connect by regexp_substr(WBName, '[^,]+', 1, level) is not null );

END Proc_Sample;

我尝试通过将表名作为参数传递给存储过程来将其转换如下

create or replace PROCEDURE  Proc_Sample                  
(
TableName in varchar2,
ApplicationID IN varchar2,
CaseType IN varchar2,
WBName IN varchar2,
WBList OUT SYS_REFCURSOR 
)AS 
stmt varchar2(10000);
BEGIN
--OPEN WBList 
--FOR
stmt := ' SELECT 
 WO.RECORDNUMBER  AS RECORDNUMBER,
FROM DATA.PC_ASSIGN_WB WB 
INNER JOIN  ' ||  TableName || ' WO ON WO.PZINSKEY = WB.PXREFOBJECTKEY 
INNER JOIN COMMON.REF_APPLICATION RA ON RA.APPLICATIONNAME = WB.PXAPPLICATION 
WHERE RA.APPLICATIONID = ApplicationID AND WB.ASSIGNEDID IN (select regexp_substr(''' || WBName || ''',''[^,]+'', 1, level) from dual 
            connect by regexp_substr(''' || WBName || ''', ''[^,]+'', 1, level) is not null)';

--execute immediate stmt;
open WBList for stmt; 
END Proc_Sample;

这是正确的做法吗? 注意 - 过程编译成功。 错误: 从客户端应用程序执行此操作时,我收到以下错误 ORA-01745:无效的主机/绑定变量名

【问题讨论】:

oracle != sql-server != mysql 我已经删除了所有冲突的标签。请正确标记。 @Uueerdo 。 . .是的,但您只会在使用 Oracle 时遇到 Oracle 错误。 您可能有太多引号或其他一些语法错误。打印出字符串并手动执行它,看看它是什么样子的 【参考方案1】:

我更喜欢使用绑定变量:

SQL> CREATE OR REPLACE PROCEDURE Proc_Sample(ApplicationID varchar2,
                                           --CType         varchar2,
                                             WBName        varchar2,
                                             RecNum        OUT DATA.WORK_CPG.RECORDNUMBER%type ) AS 
  WBList  sys_refcursor;          
  stmt    varchar2(10000);                            
BEGIN
  stmt := 'SELECT WO.RECORDNUMBER AS RECORDNUMBER
              FROM DATA.ASSIGN_WB WB
             INNER JOIN DATA.WORK_CPG WO
                ON WO.PZINSKEY = WB.PXREFOBJECTKEY
             INNER JOIN COMMON.REF_APPLICATION RA
                ON RA.APPLICATIONNAME = WB.PXAPPLICATION
             WHERE RA.APPLICATIONID = :AppID
               AND WB.ASSIGNEDID IN
                   (SELECT regexp_substr(:WBN, ''[^,]+'', 1, level)
                      FROM dual
                   CONNECT BY regexp_substr(:WBN, ''[^,]+'', 1, level) is not null)';
   OPEN WBList FOR stmt USING ApplicationID, WBName, WBName;
   FETCH WBList INTO RecNum;
   CLOSE WBList; 

END Proc_Sample;
/

无论何时调用,查询的第一个返回值都会为 RecNum 输出:

SQL> SET SERVEROUTPUT ON

SQL> Declare
  rcn DATA.WORK_CPG.RECORDNUMBER%type;
Begin
  Proc_Sample(118,'abc',rcn);
  Dbms_Output.Put_Line(rcn);
End;
/

Demo

如果您的目标只是打印出所有返回记录,那么 替换

FETCH WBList INTO RecNum;

LOOP
     FETCH WBList INTO RecNum;  
  EXIT WHEN WBList%NOTFOUND;
     DBMS_OUTPUT.PUT_LINE(WBList.RECORDNUMBER);   
END LOOP;

在程序内。

【讨论】:

感谢您的回复。一个简单的问题,这些绑定变量 :AppID 和 :WBN 是如何派生的。这些没有在查询权的任何地方设置。 对不起@daks,WBName 应该重复,因为它们是通过OPEN WBList FOR stmt USING ApplicationID, WBName, WBName 设置的,字符串中绑定变量(:AppID,:WBN,:WBN) 的数量和出现顺序。我已经修好了。

以上是关于如何在存储过程中动态传递表名 - ORACLE [重复]的主要内容,如果未能解决你的问题,请参考以下文章

每个将表名传递给过程的 ORACLE PL/SQL

如何用oracle动态查询一张表里面的某些列?

如何在 Oracle SQL Developer 的存储过程中将表名列表作为参数传递?如何使用 PLSQL VARRAY 或嵌套表?

如何从临时表名中选择,传递给存储过程?

如何在存储过程中使用动态表名编写 Select 查询?

当表名是参数时Oracle使用动态sql