【问题标题】:Illegal use of LONG datatype Oracle非法使用 LONG 数据类型 Oracle
【发布时间】:2015-07-03 10:32:07
【问题描述】:

这是我的第一个问题

我在尝试将表列(long raw)转换为 base 64 字符串时遇到问题,此列包含一些员工图片。

这是查询,我要转换的字段是 f.fot_empl

SELECT e.NOM_EMPL First_name,
       APE_EMPL Last_name,
       e.NOM_EMPL || ' ' || e.APE_EMPL Full_name,
       car.NOM_CARG position,
       COS.NOM_CCOS Area,
       f.fot_empl Picture, 
       E.FEC_NACI Birth_date
  FROM EMPLE e
       INNER JOIN CONTR c
          ON E.COD_EMPL = C.COD_EMPL
       INNER JOIN cargo car
          ON C.COD_CARG = CAR.COD_CARG
       INNER JOIN CCOST cos
        on COS.COD_CCOS = C.COD_CCOS
       LEFT JOIN FOEMP f -- employee picture
          ON e.cod_empl = F.COD_EMPL
 WHERE C.IND_ACTI = 'A';

我尝试过的:

这篇文章的已接受答案没有结果,我不断收到“非法使用 LONG 数据类型”错误。 Workaround for ORA-00997: illegal use of LONG datatype

我尝试实现以下功能但没有结果:

CREATE OR REPLACE FUNCTION to_base64 (
       vcodem     IN FOEMP.COD_EMPR%TYPE,
       vcodempl   IN FOEMP.COD_EMPL%TYPE)
       RETURN VARCHAR2
    IS
       V_VAR      FOEMP.FOT_EMPL%TYPE;
       V_result   VARCHAR2 (4000);
    BEGIN
       DBMS_OUTPUT.put_line ('Start');
       SELECT UTL_RAW.cast_to_varchar2 (
                 UTL_ENCODE.base64_encode (
                    UTL_RAW.cast_to_raw (DBMS_LOB.SUBSTR (f.FOT_EMPL, 4000))))
         INTO V_result
         FROM FOEMP f
        WHERE COD_EMPL = vcodempl AND COD_EMPR = vcodem;
       DBMS_OUTPUT.put_line ('End');
       DBMS_OUTPUT.put_line ('Result: ' || V_result);
    END to_base64;
    /

由于ORA-00997,函数无效:

   SELECT UTL_RAW.cast_to_varchar2 (
             UTL_ENCODE.base64_encode (
                UTL_RAW.cast_to_raw (DBMS_LOB.SUBSTR (f.FOT_EMPL, 4000))))
     INTO V_result
     FROM FOEMP f
    WHERE COD_EMPL = vcodempl AND COD_EMPR = vcodem;

非常感谢。

【问题讨论】:

  • 如果 f.fot_empl 是 long_Raw,你为什么要对它使用 dbms_lob.substr? (首先需要是一个吊球)

标签: oracle ora-00997


【解决方案1】:

解决方案

  1. 鉴于我在使用 long raw 时遇到的许多问题,我决定创建一个 像这样的表:

    CREATE TABLE FOTS_EMPL ( cod_empr, cod_empl, foto) AS SELECT F.COD_EMPR, F.COD_EMPL, TO_LOB (FOT_EMPL) FROM FOEMP f;

  2. 我采用了@tbone 给出的函数,并添加了 if 条件 像这样:

    CREATE OR REPLACE FUNCTION base64enc (p_blob IN BLOB) RETURN CLOB AS l_clob CLOB; l_step PLS_INTEGER := 1998; BEGIN IF p_blob IS NOT NULL THEN FOR i IN 0 .. TRUNC ( (DBMS_LOB.getlength (p_blob) - 1) / l_step) LOOP l_clob := l_clob || UTL_RAW.cast_to_varchar2 ( UTL_ENCODE.base64_encode ( DBMS_LOB.SUBSTR (p_blob, l_step, i * l_step + 1))); END LOOP; RETURN l_clob; ELSE RETURN NULL; END IF; END base64enc;

  3. 这是我最后的选择语句:

    SELECT e.NOM_EMPL First_name, APE_EMPL Last_name, e.NOM_EMPL || ' ' || e.APE_EMPL Full_name, car.NOM_CARG position, COS.NOM_CCOS Area, base64enc(foto) Picture, E.FEC_NACI Birth_date FROM EMPLE e INNER JOIN CONTR c ON E.COD_EMPL = C.COD_EMPL INNER JOIN cargo car ON C.COD_CARG = CAR.COD_CARG INNER JOIN CCOST cos on COS.COD_CCOS = C.COD_CCOS LEFT JOIN FOTS_EMPL F -- new table with blob instead of long raw ON e.cod_empl = F.COD_EMPL AND e.cod_empr = f.cod_empr WHERE C.IND_ACTI = 'A';

非常感谢。

【讨论】:

    【解决方案2】:

    SQL 最多为 varchar2 绑定 4000 个,为 char 最多绑定 2000 个。 raw 是一个二进制字符,所以我会以不到 2k 的块进行编码,例如:

    create or replace FUNCTION base64enc(p_blob IN BLOB) RETURN CLOB
        AS
          l_clob CLOB;
          l_step PLS_INTEGER := 1998;
        BEGIN
          FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_blob) - 1 )/l_step) LOOP
            l_clob := l_clob || UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(p_blob, l_step, i * l_step + 1)));
          END LOOP;
          RETURN l_clob;
    END base64enc;
    

    现在您有了 base64enc 函数,您可以传入(转换后的)blob 并存储 CLOB。

    一个例子可能是:

    create table t1 ( id int primary key, x long raw )
    
    insert into t1 values( 1, rpad( 'a', 2000, 'a' ) )
    commit;
    
    create or replace function convertLR(i_id in int)
    return clob
    as
      l_blob blob;
      l_longraw long raw;
    begin
      select x into l_longraw from t1 where id = i_id;
      l_blob := to_blob(l_longraw);
      return base64enc(l_blob);
    end;
    
    select convertLR(1) from dual;
    

    【讨论】:

      【解决方案3】:

      您可以将 LONG RAW 值转换为 PL/SQL 块中的 BLOB,然后对其进行 base64 编码:

      CREATE OR REPLACE FUNCTION to_base64 (
         vcodem     IN FOEMP.COD_EMPR%TYPE,
         vcodempl   IN FOEMP.COD_EMPL%TYPE)
         RETURN VARCHAR2
      IS
        l_blob BLOB;
        l_long_raw LONG RAW;
      BEGIN
        SELECT fot_empl INTO l_long_raw
          FROM foemp
         WHERE COD_EMPL = vcodempl AND COD_EMPR = vcodem;
        l_blob := TO_BLOB(l_long_raw);
        RETURN UTL_RAW.cast_to_varchar2 (UTL_ENCODE.base64_encode (l_blob));
      END;
      /
      

      当然,strongly recommends that you convert LONG RAW columns to binary LOB (BLOB) columns;现在仍然将数据存储为 LONG 或 LONG raw 似乎已经过时了。

      【讨论】:

      • 感谢您的回答,当我尝试执行 select 语句或调用函数时,仍然出现错误:to_base64(f.fot_empl) Picture
      • @diegofer11 - 与您的版本一样,您需要传入关键字段以查找行以获得长值。 select to_base64(x, y) from dual,或select codempl, codempr, to_base64(codempl, codempr) picture from foemp。这并不理想,而是使用旧数据类型的限制之一。 tbone 也可能是正确的关于将 BLOB 切碎,我没有尝试任何大的值。
      猜你喜欢
      • 1970-01-01
      • 2017-05-05
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      相关资源
      最近更新 更多