当前位置: 首页 > 知识库问答 >
问题:

以Oracle表为输入参数编写Oracle存储过程

童浩言
2023-03-14

如何使用表(X)作为输入参数编写Oracle存储过程,并且在过程中使用表X与另一个表Y联接?

表X将有数千条记录。

不希望将表名传递为varchar,然后使用动态SQL(因此,此选项不在画面中)

共有3个答案

微生翼
2023-03-14

在SQL作用域中创建表类型:

CREATE TYPE string_list AS TABLE OF VARCHAR2(5);

然后将其用作存储过程的参数,并使用表集合表达式将其连接到另一个表:

CREATE PROCEDURE test_proc(
  p_list IN string_list
)
IS
  v_cursor SYS_REFCURSOR;
  v_string VARCHAR2(10);
BEGIN
  OPEN v_cursor FOR
  SELECT d.*
  FROM   DUAL d
         INNER JOIN TABLE( p_list ) t
         ON ( d.DUMMY = t.COLUMN_VALUE );

  -- do something with the cursor.
 LOOP 
   FETCH v_cursor into v_string;
   EXIT WHEN v_cursor%NOTFOUND;
   DBMS_OUTPUT.PUT_LINE( v_string );
 END LOOP;
END;
/

然后你可以称之为:

BEGIN
  test_proc( string_list( 'X', 'Y', 'Z' ) ) ;
END;
/

它输出:

X

db

唐海阳
2023-03-14

您可能会发现另一种有趣的方法:将游标变量传递给流水线表函数,在SQL中调用它,允许您直接传递表的内容(select*from…),批量收集到集合中,然后将集合与其他表格一起加入!

DROP TYPE tickertype FORCE;
DROP TYPE tickertypeset FORCE;
DROP TABLE stocktable;
DROP TABLE tickertable;

CREATE TABLE stocktable
(
   ticker        VARCHAR2 (20),
   trade_date    DATE,
   open_price    NUMBER,
   close_price   NUMBER
)
/

BEGIN
   FOR indx IN 1 .. 100
   LOOP
      INSERT INTO stocktable
           VALUES ('STK' || indx,
                   SYSDATE,
                   indx,
                   indx + 15);
   END LOOP;

   COMMIT;
END;
/

CREATE TABLE tickertable
(
   ticker      VARCHAR2 (20),
   pricedate   DATE,
   pricetype   VARCHAR2 (1),
   price       NUMBER
)
/

CREATE TYPE tickertype AS OBJECT
(
   ticker VARCHAR2 (20),
   pricedate DATE,
   pricetype VARCHAR2 (1),
   price NUMBER
);
/

BEGIN
   FOR indx IN 1 .. 100
   LOOP
      INSERT INTO tickertable
           VALUES ('STK' || indx,
                   SYSDATE,
                   'O',
                   indx);
   END LOOP;

   COMMIT;
END;
/

CREATE TYPE tickertypeset AS TABLE OF tickertype;
/

CREATE OR REPLACE PACKAGE refcur_pkg
   AUTHID DEFINER
IS
   TYPE refcur_t IS REF CURSOR
      RETURN stocktable%ROWTYPE;

   TYPE dataset_tt IS TABLE OF stocktable%ROWTYPE;
END refcur_pkg;
/

CREATE OR REPLACE FUNCTION pipeliner (dataset refcur_pkg.refcur_t)
   RETURN tickertypeset
   PIPELINED
   AUTHID DEFINER
IS
   l_row_as_object   tickertype
                        := tickertype (NULL,
                                       NULL,
                                       NULL,
                                       NULL);

   l_dataset         refcur_pkg.dataset_tt;
   l_count             PLS_INTEGER;
BEGIN
   FETCH dataset BULK COLLECT INTO l_dataset;

   CLOSE dataset;

   /* Let's do a join with another table. */
   SELECT COUNT (*) into l_count
     FROM TABLE (l_dataset) st, tickertable tt
    WHERE st.ticker = tt.ticker;

   DBMS_OUTPUT.put_line ('Count = ' ||l_count);

   l_row_as_object.ticker := 'ABC';
   PIPE ROW (l_row_as_object);

   RETURN;
END;
/

BEGIN
   FOR rec
      IN (SELECT * FROM TABLE (pipeliner (CURSOR (SELECT * FROM stocktable))))
   LOOP
      DBMS_OUTPUT.put_line (rec.ticker);
   END LOOP;
END;
/

我看到这个输出:

Count = 100
ABC
容阳焱
2023-03-14

在19.6中,可以创建SQL宏。这将返回一个包含查询片段的字符串

在解析时,数据库将用您传递的表查找/替换表参数:

create or replace function f ( tab dbms_tf.table_t ) 
  return varchar2 sql_macro as
begin
  return 'select * from tab 
    join ( select level rn from dual connect by level <= 2 ) 
    on c1 = rn';
end f;
/

create table t1 (
  c1 int
);
create table t2 (
  c1 int
);

insert into t1 values ( 1 );
insert into t2 values ( 2 );


select * from f ( t1 );

C1       RN   
    1     1 

select * from f ( t2 );

C1       RN   
    2     2 
 类似资料:
  • 我试图通过Oracle光标从python到Oracle存储过程(SP)。要求SP获取数据并将数据插入表中。SP取两个参数p1和p2 p1 以下是存储过程的详细信息: p2sys_refcursor,数据将以串联格式(col1|col2|...) 获取cur.callproc(“LIBRA.pt1,[linestr,result]”行中的“DatabaseError:ORA-01036:非法变量名称

  • 本文向大家介绍Oracle带输入输出参数存储过程(包括sql分页功能),包括了Oracle带输入输出参数存储过程(包括sql分页功能)的使用技巧和注意事项,需要的朋友参考一下 记录一下,免得以后忘记了又要到处去找。 begin /*这里不能直接执行select语句但可以直接执行update、delete、insert语句*/ end里面不能接执行select语句,声明会话级临时表必须有“execu

  • 我试图从JDBC调用以下pl/sql过程。 这就是我试图调用它的方式,但没有成功: 我刚刚读到oracle jdbc不支持pl/sql结构类型。因此,这在“无效名称模式:test.testrec_r”中失败 如何从Java调用这个过程?理想情况下,只使用java库/API,但这似乎几乎是不可能的,在简单的sql调用中封装pl/sql包并调用它的最佳解决方案是什么? 另外,我正在使用Spring J

  • 问题内容: 我在SQL Server 2008 R2中有一个Oracle链接服务器。我需要执行Oracle存储过程(在第一个过程中使用输出参数,在第二个过程中使用输入参数): 我没有找到有关此问题的完整文档,只有带有无参数选择/非选择过程的简单示例,并且想知道如何调用这些过程,具有内部select的过程以及具有基本参数类型的多参数过程。 问题答案: 它应该像这样工作: 如果您有几个参数,则可能如下

  • 我正在尝试执行从hibernate到oracle表的插入操作。我的存储过程是:-