Oracle PL/SQL中循环中CLOB数据类型的串联

Oracle PL/SQL中循环中CLOB数据类型的串联,oracle,loops,plsql,clob,Oracle,Loops,Plsql,Clob,我试图在PL/SQL循环中连接CLOB,当使用DBMS_输出打印出循环值时,它一直返回null,当执行CLOB的每个结果时,也会给出一个输出 系统将根据传递到表中的报告名执行表中已存储的SQL。此特定报告有许多报告名称;因此,将每个报告串联起来。传递的参数包括报表名称、感兴趣的报表版本、所需的分隔符类型以及SQL中未知项的参数列表(如果有)。还有两种主要的SQL类型;1,需要将表名替换为临时表名,另一个需要在SQL中的表名后附加ID 请在下面找到REPREF1函数的代码 CREATE OR RE

我试图在PL/SQL循环中连接CLOB,当使用DBMS_输出打印出循环值时,它一直返回null,当执行CLOB的每个结果时,也会给出一个输出

系统将根据传递到表中的报告名执行表中已存储的SQL。此特定报告有许多报告名称;因此,将每个报告串联起来。传递的参数包括报表名称、感兴趣的报表版本、所需的分隔符类型以及SQL中未知项的参数列表(如果有)。还有两种主要的SQL类型;1,需要将表名替换为临时表名,另一个需要在SQL中的表名后附加ID

请在下面找到REPREF1函数的代码

CREATE OR REPLACE FUNCTION REPREF1(P_VER       IN VARCHAR2 DEFAULT 'LATEST',
                                   P_SEPARATOR IN VARCHAR2 DEFAULT ', ',
                                   P_ARGLIST   IN VAR DEFAULT NULL) RETURN CLOB IS
  L_CLOB CLOB;
  FUNCTION GET_CLOB(P_REPNAM    IN VARCHAR2,
                    P_VER       IN VARCHAR2 DEFAULT 'LATEST',
                    P_SEPARATOR IN VARCHAR2 DEFAULT ', ',
                    P_ARGLIST   IN VAR DEFAULT NULL) RETURN CLOB IS
    ---------------------------------------------------------------------------------
    -- TITLE - GET_CLOB beta - b.0  DATE 2010Mar12
    --
    -- DESCRIPTION -  A function that return a report based on the report name put in
    --
    -- USAGE - select get_clob(p_repnam,p_ver, p_separator, var(varay(val_1,...val_n), varay(val_1,...val_n))) FROM dual
    -----------------------------------------------------------------------------------------------------------------------------
    V_SQL       VARCHAR2(32767);
    L_RESULT    CLOB;
    V_TITLE     VARCHAR2(4000);
    V_REPDATE   VARCHAR2(30);
    V_CNT       NUMBER(2);
    V_NUMARG    NUMBER(3);
    V_CDCRU     NUMBER(3);
    V_BCNT      NUMBER(3);
    V_NEWTABDAT VARCHAR2(30);
    V_NEWTABLIN VARCHAR2(30);
    L_COLLIST   VARAY;
    V_VER       VARCHAR2(6);
    N           PLS_INTEGER;
    V_CNTTAB    NUMBER(3);

    -- EXEC_SQL_CLOB  
    FUNCTION EXEC_SQL_CLOB(P_SQL       IN VARCHAR2,
                           P_NUMARG    IN NUMBER,
                           P_COLLIST   IN VARAY DEFAULT NULL,
                           P_ARGLIST   IN VARAY DEFAULT NULL,
                           P_SEPARATOR IN VARCHAR2 DEFAULT '') RETURN CLOB IS
      ------------------------------------------------------------------------------------------------------
      -- TITLE - EXEC_SQL_CLOB beta - b.0  DATE 2010Mar22
      --
      -- DESCRIPTION -  A function that returns a clob value after executing the sql query that is passed into it 
      --
      -- USAGE - select exec_sql_clob(p_sql, p_numarg, var(varay(val_1, val_2,...val_n), varay(val_1, val_2,...val_n))) FROM dual
      ---------------------------------------------------------------------------------------------------------------
      L_CUR       INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR;
      L_STATUS    INTEGER;
      V_COL       VARCHAR2(4000);
      L_RESULT    CLOB;
      L_COLCNT    NUMBER DEFAULT 0;
      L_SEPARATOR VARCHAR2(10) DEFAULT '';
      V_NUMARG    NUMBER(3);

    BEGIN
      -- parse the query for the report
      DBMS_SQL.PARSE(L_CUR, P_SQL, DBMS_SQL.NATIVE);
      -- whilst it is not more than 255 per line
      FOR I IN 1 .. 255
      LOOP
        BEGIN
          -- define each column in the select list
          DBMS_SQL.DEFINE_COLUMN(L_CUR, I, V_COL, 2000);
          L_COLCNT := I;
        EXCEPTION
          WHEN OTHERS THEN
            IF (SQLCODE = -1007) THEN
              EXIT;
            ELSE
              RAISE;
            END IF;
        END;
      END LOOP;

      -- If query has no bind variables
      IF (P_ARGLIST IS NULL) THEN
        IF (P_NUMARG = 0) THEN
          -- Execute the query in the cursor
          L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
          LOOP
            -- Exit loop when fetch is complete
            EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
            L_SEPARATOR := '';
            FOR I IN 1 .. L_COLCNT
            LOOP
              DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
              L_RESULT    := L_RESULT || L_SEPARATOR || V_COL;
              L_RESULT    := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
              L_SEPARATOR := P_SEPARATOR;
            END LOOP;
            L_RESULT := L_RESULT || CHR(13);
          END LOOP;
        ELSE
          RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
        END IF;
        -- Query has bind variables
      ELSE
        -- Check if the numarg passed is the same has stored in the table
        SELECT NUMARG
          INTO V_NUMARG
          FROM REPVER
         WHERE REPCODE = P_SQL;
        -- If number of arguments is greater than 0
        IF (V_NUMARG > 0) THEN
          -- Check if the number of arguments are the same
          IF (P_NUMARG = V_NUMARG) THEN
            -- Replace the bind variables in the query
            FOR J IN 1 .. P_ARGLIST.COUNT
            LOOP
              DBMS_SQL.BIND_VARIABLE(L_CUR, P_COLLIST(J), P_ARGLIST(J));
            END LOOP;
            -- Execute the query in the cursor
            L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
            LOOP
              -- Exit loop when fetch is complete
              EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
              L_SEPARATOR := '';
              FOR I IN 1 .. L_COLCNT
              LOOP
                DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
                L_RESULT    := L_RESULT || L_SEPARATOR || V_COL;
                L_RESULT    := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
                L_SEPARATOR := P_SEPARATOR;
              END LOOP;
              L_RESULT := L_RESULT || CHR(13);
            END LOOP;
          ELSE
            RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
          END IF;
        ELSE
          -- If the number of argument is equal to 0
          IF (P_NUMARG = 0) THEN
            -- Execute the query in the cursor
            L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
            LOOP
              -- Exit loop when fetch is complete
              EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
              L_SEPARATOR := '';
              FOR I IN 1 .. L_COLCNT
              LOOP
                DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
                L_RESULT    := L_RESULT || L_SEPARATOR || V_COL;
                L_RESULT    := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
                L_SEPARATOR := P_SEPARATOR;
              END LOOP;
              L_RESULT := L_RESULT || CHR(13);
            END LOOP;
          ELSE
            RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
          END IF;
        END IF;
      END IF;
      -- Close cursor
      DBMS_SQL.CLOSE_CURSOR(L_CUR);
      RETURN L_RESULT;
    END EXEC_SQL_CLOB;
  BEGIN
    -- Check if the version entered is null or latest
    IF (P_VER IS NULL)
       OR (UPPER(P_VER) = UPPER('LATEST')) THEN
      SELECT MAX(VER)
        INTO V_VER
        FROM REPORT B, REPVER R
       WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
         AND B.REPREF = R.REPREF;
    ELSE
      V_VER := P_VER;
    END IF;

    -- Check if the repname and version entered exists
    SELECT COUNT(*)
      INTO V_CNT
      FROM REPORT B, REPVER R
     WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
       AND VER = V_VER
       AND B.REPREF = R.REPREF;

    IF (V_CNT > 0) THEN
      -- Store the SQL statement, title and number of arguments of the report name passed.
      SELECT REPCODE, REPTITLE, NUMARG, COLLIST
        INTO V_SQL, V_TITLE, V_NUMARG, L_COLLIST
        FROM REPVER R, REPORT B
       WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
         AND B.REPREF = R.REPREF
         AND VER = V_VER;

      V_REPDATE := TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI');

      L_RESULT := V_TITLE || ' (' || P_REPNAM || ' version ' || V_VER || ') generated ' || V_REPDATE || CHR(13) || CHR(13);

      -- Check for some specific type of queries
      SELECT COUNT(*)
        INTO V_CDCRU
        FROM REPVER R, REPORT B
       WHERE CTDDATA = 'Y'
         AND UPPER(REPNAM) = UPPER(P_REPNAM)
         AND B.REPREF = R.REPREF
         AND VER = V_VER;

      SELECT COUNT(*)
        INTO V_BCNT
        FROM REPVER R, BODCREPS B
       WHERE BENLIST = 'Y'
         AND UPPER(REPNAM) = UPPER(P_REPNAM)
         AND B.REPREF = R.REPREF
         AND VER = V_VER;

      IF (V_CDCRU > 0) THEN

        V_NEWTABDATA := 'CT_' || 'DAT_' || P_ARGLIST(1) (P_ARGLIST(1).FIRST);
        V_NEWTABLINK := 'CT_' || 'LIN_' || P_ARGLIST(1) (P_ARGLIST(1).FIRST);

        -- Check if the tables exist
        SELECT COUNT(*)
          INTO V_CNTTAB
          FROM ALL_TABLES
         WHERE TABLE_NAME = V_NEWTABDAT
            OR TABLE_NAME = V_NEWTABLIN
           AND OWNER = 'SCOTT';

        IF (V_CNTTAB > 0) THEN

          V_SQL := UPPER(V_SQL);
          V_SQL := REPLACE(V_SQL, 'CT_DAT_CRU', V_NEWTABDAT);
          V_SQL := REPLACE(V_SQL, 'CT_LIN_CRU', V_NEWTABLIN);

        ELSE
          V_SQL := 'SELECT ''THE TABLE NOT CREATED YET''
                              FROM DUAL';
        END IF;
      END IF;

      IF (V_BCNT > 0) THEN

        V_SQL := UPPER(V_SQL);
        V_SQL := REPLACE(V_SQL, 'LIST', P_ARGLIST(1) (P_ARGLIST(1).LAST));

      END IF;

      IF (P_ARGLIST IS NULL) THEN
        -- execute the query
        L_RESULT := L_RESULT || EXEC_SQL_CLOB(V_SQL, V_NUMARG, L_COLLIST, NULL, P_SEPARATOR);
      ELSE
        N := P_ARGLIST.COUNT;
        -- execute the query
        L_RESULT := L_RESULT || EXEC_SQL_CLOB(V_SQL, V_NUMARG, L_COLLIST, P_ARGLIST(N), P_SEPARATOR);
      END IF;
      RETURN L_RESULT;
    ELSE
      RAISE_APPLICATION_ERROR(-20012, P_REPNAM || ' or ' || P_VER || ' DOES NOT EXIST ');
    END IF;
  END GET_CLOB;
BEGIN
  FOR I IN (SELECT REPNAM
              FROM REPORT
             WHERE REPREF NOT IN ('R01', 'R02', 'R03', 'R04'))
  LOOP
    SELECT CONCAT_CLOB(GET_CLOB(I.REPNAM, P_VER, P_SEPARATOR, P_ARGLIST))
      INTO L_CLOB
      FROM DUAL;
    DBMS_OUTPUT.PUT_LINE(I.REPNAM);
    -- DBMS_OUTPUT.PUT_LINE (COUNT(i.REPNAM));
  END LOOP;
  RETURN L_CLOB;
END REPREF1;

/
当我尝试这个的时候

FOR I IN (SELECT REPNAM
            FROM REPORT
           WHERE REPREF NOT IN ('R01', 'R02', 'R03', 'R04'))
LOOP
  L_CLOB := L_CLOB || CHR(13) || GET_CLOB(I.REPNAM, P_VER, P_SEPARATOR, P_ARGLIST);
  DBMS_OUTPUT.PUT_LINE(I.REPNAM);
END LOOP;

它也给出了null;但是这次repnam的dbms输出不完整。

不知道您的代码。以下是它对我的作用: 每当我创建返回clob值的函数时,我都会执行以下操作:

function foo return clob is
l_clob clob;
begin
      dbms_lob.createtemporary(lob_loc => l_clob, cache => true, dur => dbms_lob.call);
      ...
      return l_clob;
end;
将值连接到clob时,我使用一个函数:

   procedure add_string_to_clob(p_lob    in out nocopy clob
                             ,p_string varchar2) is
   begin
      dbms_lob.writeappend(lob_loc => p_lob, amount => length(p_string), buffer => p_string);
   end;
你必须使用

dbms\u lob.substr(您的clob参数、起始位置、长度)

e、 g

dbms_输出(“我的clob值:”| | dbms_lob.substr(您的clob参数、起始位置、长度);


但是你可以打印一个最大为4000个字符的字符串,然后你可以在循环函数中使用它在每行打印4000个字符。

没有什么比筛选几百行其他人的劣质代码更好的了。Rene,关于这行的快速问题:
dbms\u lob.createtemporary(lob_loc=>l_lob,cache=>true,dur=>dbms_lob.call)
这是不是
lob_loc=>l_lob
应该是
lob_loc=>l_clob
?@JWiley-yup,9年后被修复的打字错误!
   procedure add_string_to_clob(p_lob    in out nocopy clob
                             ,p_string varchar2) is
   begin
      dbms_lob.writeappend(lob_loc => p_lob, amount => length(p_string), buffer => p_string);
   end;