将大型sql查询作为输入发送到oracle中的过程

将大型sql查询作为输入发送到oracle中的过程,oracle,oracle10g,Oracle,Oracle10g,我编写了一个过程,该过程将自动从给定的查询中获取数据,并将reuslt数据集放入带有分隔符的目录中的文件中。它适用于较小的查询,如表1中的select*,但不适用于较大的查询,如: SELECT i.row_id, translate(i.x_notes_txt, chr(10)||chr(13)||'|' , ' '), null FROM communication i, contact c WHERE i.last_upd >= (SELECT t

我编写了一个过程,该过程将自动从给定的查询中获取数据,并将reuslt数据集放入带有分隔符的目录中的文件中。它适用于较小的查询,如表1中的select*,但不适用于较大的查询,如:

SELECT
   i.row_id,
   translate(i.x_notes_txt, chr(10)||chr(13)||'|' , '   '),
   null
FROM communication i,
     contact c
WHERE   i.last_upd >= (SELECT to_char(last_updated_dt, 'DD-MON-YYYY') 
FROM extract_status
WHERE extract_nm = 'INTN300')
   AND i.last_upd < sysdate
   AND i.x_interaction_type_cd NOT IN ('XRAC','FMS','ATV','IRL')
   AND i.pr_con_id  = c.row_id
   AND c.x_Prospect_Ind = 'Y';
还有更多..有人能帮助我们如何将这些查询作为输入传递吗

        /* Formatted on 06/06/2013 1:42:56 PM (QP5 v5.163.1008.3004) */
       CREATE OR REPLACE FUNCTION tab_to_flat (input_query   IN CLOB,
                                    dir_name      IN VARCHAR2,
                                    file_name     IN VARCHAR2,
                                    seperator     IN VARCHAR2)
   RETURN NUMBER
  IS
   c_seperator          VARCHAR2 (3) := ' ';
   incoming_seperator   VARCHAR2 (3) := seperator;
   no_of_rows           NUMBER;
   rec_tab              DBMS_SQL.DESC_TAB;
   col_cnt              INTEGER;
   src_id               INTEGER DEFAULT DBMS_SQL.open_cursor;
   val_varchar          VARCHAR2 (32767);
   val_num              NUMBER;
  val_date             DATE;
   file_input           UTL_FILE.file_type;
   l_start              NUMBER;
   row_cnt              NUMBER := 0;
   BEGIN
   l_start := DBMS_UTILITY.get_time;

    file_input :=
  UTL_FILE.fopen (dir_name,
                  file_name,
                  'w',
                  32767);
   DBMS_SQL.parse (src_id, input_query, 1);

  DBMS_SQL.describe_columns (src_id, col_cnt, rec_tab);

  FOR i IN 1 .. col_cnt
  LOOP
  CASE (rec_tab (i).col_type)
     WHEN 1
     THEN
        DBMS_SQL.define_column (src_id,
                                i,
                                val_varchar,
                                32767);
     WHEN 2
     THEN
        DBMS_SQL.define_column (src_id, i, val_num);
     --when 8 then dbms_sql.define_column_long(src_id,i);
     WHEN 12
     THEN
        DBMS_SQL.define_column (src_id, i, val_date);
     ELSE
        DBMS_SQL.define_column (src_id,
                                i,
                                val_varchar,
                                32767);
    END CASE;
    END LOOP;

   no_of_rows := DBMS_SQL.execute (src_id);

  LOOP
  EXIT WHEN (DBMS_SQL.FETCH_ROWS (src_id) <= 0);
  c_seperator := ' ';

  FOR j IN 1 .. col_cnt
  LOOP
     CASE (rec_tab (j).col_type)
        WHEN 1
        THEN
           DBMS_SQL.COLUMN_VALUE (src_id, j, val_varchar);
           UTL_FILE.put (file_input, c_seperator || val_varchar);
        WHEN 2
        THEN
           DBMS_SQL.COLUMN_VALUE (src_id, j, val_num);
           UTL_FILE.put (file_input, c_seperator || val_num);
        -- when 8 then dbms_sql.column_value_long(src_id,j,4000,1);

        WHEN 12
        THEN
           DBMS_SQL.COLUMN_VALUE (src_id, j, val_date);
           UTL_FILE.put (
              file_input,
              c_seperator || TO_CHAR (val_date, 'MM/DD/YYYY HH24:MI:SS'));
        ELSE
           DBMS_SQL.COLUMN_VALUE (src_id, j, val_varchar);
           UTL_FILE.put (file_input, c_seperator || val_varchar);
     END CASE;

     c_seperator := incoming_seperator;
  END LOOP;

  UTL_FILE.new_line (file_input);
  row_cnt := row_cnt + 1;
     END LOOP;

     DBMS_SQL.close_cursor (src_id);

       DBMS_OUTPUT.put_line (
  'The execution time is : ' || (DBMS_UTILITY.get_time - l_start));
                    RETURN row_cnt;
       EXCEPTION
      WHEN OTHERS
       THEN
          IF (SQLCODE = -942)
           THEN
           DBMS_OUTPUT.put_line ('Please check the table_name');
           ELSE
           RAISE;
          END IF;
         END;

您可以这样使用am oracle游标:

FUNCTION SELECT_FROM_MY_TABLE(v_QUERY_TO_BE_EXECUTED    VARCHAR2)
RETURN SYS_REFCURSOR
IS
    c_my_cursor   SYS_REFCURSOR;
BEGIN

  OPEN c_my_cursor FOR
    v_QUERY_TO_BE_EXECUTED -- When working with Ref Cursors, open-for can be used directly, instead of execute immediate. 

  RETURN  c_my_cursor;

END SELECT_FROM_MY_TABLE;
PROCEDURE procedure_use_cursor
IS
    c_my_cursor       SYS_REFCURSOR;
    r_my_table_row    my_table%ROWTYPE;

BEGIN

  c_my_cursor := SELECT_FROM_MY_TABLE;

  LOOP

  FETCH c_my_cursor INTO r_my_table_row;
  EXIT WHEN c_my_cursor%NOTFOUND ;

  -- do what you want with r_my_table_row   

 END LOOP;

END procedure_use_cursor;
所以基本上你有一个函数,它返回一个游标,其中包含你查询的信息。使用光标时,可以按如下方式操作:

FUNCTION SELECT_FROM_MY_TABLE(v_QUERY_TO_BE_EXECUTED    VARCHAR2)
RETURN SYS_REFCURSOR
IS
    c_my_cursor   SYS_REFCURSOR;
BEGIN

  OPEN c_my_cursor FOR
    v_QUERY_TO_BE_EXECUTED -- When working with Ref Cursors, open-for can be used directly, instead of execute immediate. 

  RETURN  c_my_cursor;

END SELECT_FROM_MY_TABLE;
PROCEDURE procedure_use_cursor
IS
    c_my_cursor       SYS_REFCURSOR;
    r_my_table_row    my_table%ROWTYPE;

BEGIN

  c_my_cursor := SELECT_FROM_MY_TABLE;

  LOOP

  FETCH c_my_cursor INTO r_my_table_row;
  EXIT WHEN c_my_cursor%NOTFOUND ;

  -- do what you want with r_my_table_row   

 END LOOP;

END procedure_use_cursor;

看起来您只是没有转义查询字符串中包含的引号,所以您将其称为

tab_to_flat('SELECT i.row_id, translate(i.x_notes_txt, chr(10)||chr(13)||'|' , '   '),...')
在chr13之后连接的|是直接的问题,但还有其他问题。您可以仔细阅读并仔细翻倍字符串中的每个引号:

tab_to_flat('SELECT i.row_id, translate(i.x_notes_txt, chr(10)||chr(13)||''|'' , ''   ''),...')
。。。或者更容易地使用:

。。。其中q“[…]”包含原始字符串,允许您使用单引号,而无需转义它们。您只需要确保实际查询不包含[或],如果包含,则选择不同的分隔符


这并没有说明你所做的是否是一个好的方法,以及你是否能找到更好的方法来解决你的问题,也没有说明SQL注入等等。;这只是为了解决您当前调用的内容以及如何执行的问题。

这个大查询有效吗?我的意思是,它显示了正确的结果吗?是的,它工作得很好。。。但我担心如何将其作为输入发送到dat过程。基本上,您希望大查询的结果作为输入参数传递到该过程?不,实际上我需要将查询传递到该过程。。任何疑问。。我是甲骨文的新手。。我们有没有办法发送任何类型的查询作为该过程的输入。。。在这个过程中,我使用dbms_sql包来解析和使用它。它还显示了'DD-MON-YYYY'、'XRAC'、'FMS'、'ATV'、'IRL'和'INTN300'的错误。谢谢您的帮助。。但我正在寻找一个不同的答案,因为查询也是动态的。。。我将动态地获取查询。@user2401828如果我们给我的函数一个参数,这基本上是一个字符串形式的查询,通过使用execute immediate,我们将它的结果放在一个游标中,怎么样?我使这个过程成为通用的过程。。因此它将接受任何查询并将其放入平面文件中。。我把程序也…这是个好主意。。。你们能举个小例子吗?事实上,我尝试了其他解决方案,比如把结果移到光标上。。将其转换为ref_cursor,然后使用dbms_sql.to_cursor_id将其转换为cursor id。。这很容易。。但在11g中引入了to_cursor_id。。。我使用的是10.6:@user2401828-这是“备用报价机制”。我在答案中的链接中描述了这一点;在“语法的底部分支”下查找要点。