Oracle DB-PLSQL函数中的Clob冲突

kx1ctssn  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(107)

你好,我设计了这张table:

CREATE TABLE "PUBLIC"."FORMS_UNITS" 
   (    "CODE" VARCHAR2(1024 BYTE) NOT NULL ENABLE, 
    "SUBTITLE" VARCHAR2(1024 BYTE), 
    "DESCRIPTION" CLOB, 
    "ELEMENTS" CLOB NOT NULL ENABLE, 
    "STATUS" VARCHAR2(1024 BYTE) DEFAULT 'Borrador' NOT NULL ENABLE, 
    "KEYWORDS" VARCHAR2(1024 BYTE), 
    "CREATED_AT" TIMESTAMP (6), 
    "UPDATED_AT" TIMESTAMP (6), 
    "CREATED_BY" NUMBER(19,0) NOT NULL ENABLE, 
    "UPDATED_BY" NUMBER(19,0), 
     CONSTRAINT "FORMS_UNITS_ID_PK" PRIMARY KEY ("CODE")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "APPSDATA"  ENABLE, 
     CONSTRAINT "FORMS_UNITS_USER_CB_ID_FK" FOREIGN KEY ("CREATED_BY")
      REFERENCES "PUBLIC"."USERS" ("ID") ON DELETE CASCADE ENABLE, 
     CONSTRAINT "FORMS_UNITS_USER_uB_ID_FK" FOREIGN KEY ("UPDATED_BY")
      REFERENCES "PUBLIC"."USERS" ("ID") ON DELETE CASCADE ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "APPSDATA" 
 LOB ("DESCRIPTION") STORE AS BASICFILE (
  TABLESPACE "APPSDATA" ENABLE STORAGE IN ROW CHUNK 8192 RETENTION 
  NOCACHE LOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
 LOB ("ELEMENTS") STORE AS BASICFILE (
  TABLESPACE "APPSDATA" ENABLE STORAGE IN ROW CHUNK 8192 RETENTION 
  NOCACHE LOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;

问题出在下面的plsql函数中,它返回以下错误:
SQL错误:ORA-06502:PL/SQL:数据类型错误在“PUBLIC.FORMS_PKG”中,第315 06502行。00000 -“PL/SQL:数字或值错误%s”* 原因:发生算术、数字、字符串、转换或约束错误。例如,如果试图将值NULL赋给声明为NOT NULL的变量,或者试图将大于99的整数赋给声明为NUMBER(2)的变量,则会发生此错误。* 操作:更改数据,如何操作它,或者如何声明它,以便值不违反约束。
这就是PLSQL函数:

FUNCTION GET_FORMS
RETURN CLOB
AS
     l_query      CLOB;
     l_result     CLOB;
     l_temp       SYS_REFCURSOR;
     l_row        FORMS_UNITS%ROWTYPE;
BEGIN
    l_query := 'SELECT CODE, TITLE, SUBTITLE, DESCRIPTION, KEYWORDS, ELEMENTS, STATUS, CREATED_AT, UPDATED_AT, CREATED_BY, UPDATED_BY  FROM FORMS_UNITS';    
    OPEN l_temp FOR l_query;
    l_result := '[ ';
    LOOP
        FETCH l_temp INTO l_row;
        EXIT WHEN l_temp%NOTFOUND;
        l_result := l_result || '{ "CODE": "' || l_row.CODE || '", "TITLE": "' || l_row.TITLE || '", "SUBTITLE": "' || l_row.SUBTITLE || '", "DESCRIPTION": "' || l_row.DESCRIPTION || '", "KEYWORDS": "' || l_row.KEYWORDS || '", "ELEMENTS": "' || l_row.ELEMENTS || '", "STATUS": "' || l_row.STATUS || '", "CREATED_AT": "' || l_row.CREATED_AT || '", "UPDATED_AT": "' || l_row.UPDATED_AT || '", "CREATED_BY": "' || l_row.CREATED_BY || '", "UPDATED_BY": "' || l_row.UPDATED_BY || '" }, ';
    END LOOP;
    IF l_temp%ISOPEN THEN
        CLOSE l_temp;
    END IF;
    l_result := RTRIM(l_result, ', ') || ' ]';

    RETURN l_result;
END;

问题似乎出在FETCH l_temp INTO l_row这一行上;
由于CL.OB变量的大小不足,因为问题出在表组件元素上。当函数返回的长度为4,959个字符时,问题就出现了。现在,如果我减小大小,函数返回一个正确的值。

ztigrdn8

ztigrdn81#

如果你使用的是Oracle 12或更高版本,那么你不应该尝试手工生成JSON;你应该使用内置的JSON函数:

FUNCTION GET_FORMS
RETURN CLOB
AS
     l_result     CLOB;
BEGIN
  SELECT JSON_ARRAYAGG(
           JSON_OBJECT(
             KEY 'CODE' VALUE CODE,
             -- KEY 'TITLE' VALUE TITLE, -- The table has no TITLE column
             KEY 'SUBTITLE' VALUE SUBTITLE,
             KEY 'DESCRIPTION' VALUE DESCRIPTION,
             KEY 'KEYWORDS'    VALUE KEYWORDS,
             KEY 'ELEMENTS'    VALUE ELEMENTS,
             KEY 'STATUS'      VALUE STATUS,
             KEY 'CREATED_AT'  VALUE TO_CHAR(CREATED_AT, 'YYYY-MM-DD"T"HH24:MI:SS.FF6'),
             KEY 'UPDATED_AT'  VALUE TO_CHAR(UPDATED_AT, 'YYYY-MM-DD"T"HH24:MI:SS.FF6'),
             KEY 'CREATED_BY'  VALUE CREATED_BY,
             KEY 'UPDATED_BY'  VALUE UPDATED_BY
             RETURNING CLOB
           )
           RETURNING CLOB
         )
  INTO   l_result
  FROM   FORMS_UNITS;

  RETURN l_result;
END;
/

如果你想手动生成JSON(不要),那么你的代码可以是:

FUNCTION GET_FORMS
RETURN CLOB
AS
  l_result CLOB := EMPTY_CLOB() || '[';
BEGIN
  FOR l_row IN (SELECT * FROM FORMS_UNITS)
  LOOP
    l_result := l_result
                || '{'
                || '"CODE": "' || l_row.CODE || '",'
             -- || '"TITLE": "' || l_row.TITLE || '",'
                || '"SUBTITLE": "' || l_row.SUBTITLE || '",'
                || '"DESCRIPTION": "' || l_row.DESCRIPTION || '",'
                || '"KEYWORDS": "' || l_row.KEYWORDS || '",'
                || '"ELEMENTS": "' || l_row.ELEMENTS || '",'
                || '"STATUS": "' || l_row.STATUS || '",'
                || '"CREATED_AT": "' || TO_CHAR(l_row.CREATED_AT, 'YYYY-MM-DD"T"HH24:MI:SS.FF6') || '",'
                || '"UPDATED_AT": "' || TO_CHAR(l_row.UPDATED_AT, 'YYYY-MM-DD"T"HH24:MI:SS.FF6') || '",'
                || '"CREATED_BY": "' || TO_CHAR(l_row.CREATED_BY) || '",'
                || '"UPDATED_BY": "' || TO_CHAR(l_row.UPDATED_BY) || '"'
                || '}, ';
  END LOOP;
  l_result := RTRIM(l_result, ', ') || ']';
  RETURN l_result;
END;
/
  • 但是,这并没有正确地对应该转义的字符串中的字符进行编码(即"应该是\"CHR(10)应该是\n,依此类推)。*

fiddle

相关问题