Stored procedures `使用`getclobval()执行oracle过程时出现无效字符错误``

Stored procedures `使用`getclobval()执行oracle过程时出现无效字符错误``,stored-procedures,plsql,oracle11g,oracle-sqldeveloper,listagg,Stored Procedures,Plsql,Oracle11g,Oracle Sqldeveloper,Listagg,以下过程在ctrll+S上成功编译显示有效,但在执行时抛出错误:在SQL DEVELOPER上执行此过程时出现无效字符错误。 我看不到任何地方有无效字符 以下是创建表和插入值的代码:- CREATE TABLE tempt( "set" VARCHAR2(1), "level" VARCHAR2(1), category VARCHAR2(3), value INT ); INSERT INTO tempt SELECT 'A', 'Z', 'ABC'

以下过程在ctrll+S上成功编译显示有效,但在执行时抛出错误:在SQL DEVELOPER上执行此过程时出现无效字符错误。 我看不到任何地方有无效字符

以下是创建表和插入值的代码:-

 CREATE TABLE tempt( "set" VARCHAR2(1), "level" VARCHAR2(1), category VARCHAR2(3), value INT );

INSERT INTO tempt
SELECT 'A', 'Z', 'ABC', 847549 FROM dual UNION ALL
SELECT 'A', 'Y', 'ABC', 955808 FROM dual UNION ALL
SELECT 'A', 'X', 'ABC', 983462 FROM dual UNION ALL
SELECT 'A', 'Z', 'GHI', 762369 FROM dual UNION ALL
SELECT 'A', 'Y', 'DEF', 615863 FROM dual UNION ALL
SELECT 'A', 'X', 'DEF', 474257 FROM dual UNION ALL
SELECT 'B', 'Z', 'ABC', 959843 FROM dual UNION ALL
SELECT 'B', 'Y', 'ABC', 821704 FROM dual UNION ALL
SELECT 'B', 'X', 'ABC', 377211 FROM dual UNION ALL
SELECT 'B', 'Z', 'DEF', 945053 FROM dual UNION ALL
SELECT 'B', 'Y', 'DEF', 919120 FROM dual UNION ALL
SELECT 'B', 'Y', 'ABC', 821704 FROM dual UNION ALL
SELECT 'C', 'X', 'ABC', 377211 FROM dual UNION ALL
SELECT 'C', 'Z', 'DEF', 945053 FROM dual UNION ALL
SELECT 'C', 'Y', 'DEF', 919120 FROM dual UNION ALL
SELECT 'D', 'X', 'ABC', 377211 FROM dual UNION ALL
SELECT 'D', 'Z', 'DEF', 945053 FROM dual UNION ALL
SELECT 'D', 'Y', 'GHI', 919120 FROM dual UNION ALL
SELECT 'E', 'X', 'ABC', 377211 FROM dual UNION ALL
SELECT 'E', 'Z', 'DEF', 945053 FROM dual UNION ALL
SELECT 'E', 'Y', 'ABC', 919120 FROM dual UNION ALL
SELECT 'E', 'Z', 'ABC', 945053 FROM dual UNION ALL
SELECT 'E', 'Y', 'DEF', 919120 FROM dual UNION ALL
SELECT 'B', 'X', 'IJK', 326886 FROM dual
这在SQL Developer/DB viz上的过程窗口中运行:-

CREATE OR REPLACE PROCEDURE "SCHEMA.pivot"(v_recordset out sys_refcursor)
AS
--v_recordset SYS_REFCURSOR;
  v_sql       long;
  v_cols_1    long;
  v_cols_2    clob; 

BEGIN
  SELECT LISTAGG( ''''||"level"||''' AS "'||"level"||'"' , ',' )
          WITHIN GROUP ( ORDER BY "level" DESC )
    INTO v_cols_1
    FROM (
          SELECT DISTINCT "level"
            FROM tempt
          );

SELECT DBMS_XMLGEN.CONVERT (
          RTRIM (
           XMLAGG (XMLELEMENT (
                        e,
                          'MAX(CASE WHEN CATEGORY = '
                      || CHR (39)
                       || CATEGORY
                       || CHR (39)
                       || ' THEN '
                      || CHR (39)
                      || "level"
                       || CHR (39)
                      || ' END) AS '
                       || "level"
                      || '_'
                       || CATEGORY
                      || '',
                       ',')
                    ORDER BY 1 DESC).EXTRACT ('//text()').getclobval (),
           ','))
    INTO v_cols_2
   FROM (SELECT DISTINCT "level", CATEGORY
          FROM tempt);
                      

  v_sql :=
  'SELECT "set", ('|| v_cols_2 ||')
     FROM
     (
      SELECT *
        FROM tempt
           PIVOT
           (
            MAX(value) FOR "level" IN ( '|| v_cols_1 ||' )
           )
          )
          GROUP BY "set"
          ORDER BY "set"'; 
      v_sql := REPLACE (v_sql, ''', CHR (39));
      DBMS_OUTPUT.PUT_LINE(v_sql);
       
      OPEN v_recordset FOR v_sql;
 end pivot;
编辑1:我运行了答案中提供的查询,虽然编译成功,但得到了一个无效字符 错误:-

00911。00000-无效字符*原因:标识符不能以字母和数字以外的任何ASCII字符开头。$\u也允许在第一个字符后使用。双引号括起的标识符可以包含双引号以外的任何字符。可选引号q“…”不能使用空格、制表符或回车符作为分隔符。对于所有其他上下文,请参阅SQL语言参考手册。 我看到其他帖子也有同样的问题,我尝试了所有的方法,但似乎没有解决这个问题。它为错误显示的行是OPEN v_recordset for v_sql

应该是

SQL> CREATE OR REPLACE PROCEDURE pivot (v_recordset OUT SYS_REFCURSOR)
  2  AS
  3     --v_recordset SYS_REFCURSOR;
  4     v_sql     LONG;
  5     v_cols_1  LONG;
  6     v_cols_2  CLOB;
  7  BEGIN
  8     SELECT LISTAGG ('''' || "level" || ''' AS "' || "level" || '"', ',')
  9               WITHIN GROUP (ORDER BY "level" DESC)
 10       INTO v_cols_1
 11       FROM (SELECT DISTINCT "level"
 12               FROM tempt);
 13
 14     SELECT DBMS_XMLGEN.CONVERT (
 15               RTRIM (
 16                  XMLAGG (XMLELEMENT (
 17                             e,
 18                                'MAX(CASE WHEN CATEGORY = '
 19                             || CHR (39)
 20                             || CATEGORY
 21                             || CHR (39)
 22                             || ' THEN '
 23                             || CHR (39)
 24                             || "level"
 25                             || CHR (39)
 26                             || ' END) AS '
 27                             || "level"
 28                             || '_'
 29                             || CATEGORY
 30                             || '',
 31                             ',')
 32                          ORDER BY 1 DESC).EXTRACT ('//text()').getclobval (),
 33                  ','))
 34       INTO v_cols_2
 35       FROM (SELECT DISTINCT "level", CATEGORY
 36               FROM tempt);
 37
 38     v_sql := 'SELECT "set", ' || v_cols_2 || '
 39       FROM
 40       (
 41        SELECT *
 42          FROM tempt
 43             PIVOT
 44             (
 45              MAX(value) FOR "level" IN ( ' || v_cols_1 || ' )
 46             )
 47            )
 48            GROUP BY "set"
 49            ORDER BY "set"';
 50     v_sql := REPLACE (v_sql, ''', CHR (39));
 51     DBMS_OUTPUT.PUT_LINE (v_sql);
 52
 53     OPEN v_recordset FOR v_sql;
 54  END pivot;
 55  /

Procedure created.

SQL>
测试:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2     l_rc  SYS_REFCURSOR;
  3  BEGIN
  4     pivot (l_rc);
  5  END;
  6  /
SELECT "set", MAX(CASE WHEN CATEGORY = 'GHI' THEN 'Y' END) AS Y_GHI,MAX(CASE
WHEN CATEGORY = 'ABC' THEN 'Y' END) AS Y_ABC,MAX(CASE WHEN CATEGORY = 'ABC' THEN
'Z' END) AS Z_ABC,MAX(CASE WHEN CATEGORY = 'DEF' THEN 'Z' END) AS Z_DEF,MAX(CASE
WHEN CATEGORY = 'IJK' THEN 'X' END) AS X_IJK,MAX(CASE WHEN CATEGORY = 'GHI' THEN
'Z' END) AS Z_GHI,MAX(CASE WHEN CATEGORY = 'DEF' THEN 'X' END) AS X_DEF,MAX(CASE
WHEN CATEGORY = 'ABC' THEN 'X' END) AS X_ABC,MAX(CASE WHEN CATEGORY = 'DEF' THEN
'Y' END) AS Y_DEF
     FROM
     (
      SELECT *
        FROM tempt

PIVOT
           (
            MAX(value) FOR "level" IN ( 'Z' AS "Z",'Y' AS
"Y",'X' AS "X" )
           )
          )
          GROUP BY "set"

ORDER BY "set"

PL/SQL procedure successfully completed.

SQL>
运行结果查询将生成以下结果:

SQL> SELECT "set", MAX(CASE WHEN CATEGORY = 'GHI  <snip>
ORY = 'DEF' THEN 'Z' END) AS Z_DEF,MAX(CASE WHEN  <snip>
(CASE WHEN CATEGORY = 'ABC' THEN 'X' END) AS X_A  <snip>
  2       FROM
  3       (
  4        SELECT *
  5          FROM tempt
  6             PIVOT
  7             (
  8              MAX(value) FOR "level" IN ( 'Z'
  9             )
 10            )
 11            GROUP BY "set"
 12            ORDER BY "set"
 13  /

s Y Y Z Z X Z X X Y
- - - - - - - - - -
A Y Y Z Z   Z X X Y
B   Y Z Z X   X X Y
C   Y Z Z     X X Y
D Y Y Z Z   Z X X Y
E   Y Z Z     X X Y

SQL>

还有,忘了说:真的,真的,真的不好用双引号下的小写来命名列。

不幸的是,这是我们表中给出的列名称,我知道这些是保留关键字。请告诉我您在哪里运行过SQL>SET-SERVEROUTPUT ON SQL>DECLARE l_rc SYS_REFCURSOR;开始旋转l_rc;结束/是的,PL/SQL块已编译,但我使用了您在测试窗口中提供的相同执行语句。。它不工作..这和它的SQL*Plus一样有意义。我使用了进程窗口上的内置运行按钮,它给出了无效字符错误我不知道,我不知道进程窗口上的内置运行按钮。过程及其查询工作正常-如所示。*原因:标识符不能以字母和数字以外的任何ASCII字符开头。$\u也允许在第一个字符后使用。双引号括起的标识符可以包含双引号以外的任何字符。可选引号q“…”不能使用空格、制表符或回车符作为分隔符。对于所有其他上下文,请参阅SQL语言参考手册。