3

这是我的第一个问题

我在尝试将表列(长原始)转换为 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 数据类型”错误。 ORA-00997 的解决方法:非法使用 LONG 数据类型

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

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;

提前谢谢了。

4

3 回答 3

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;
/

当然,强烈建议您将 LONG RAW 列转换为二进制 LOB (BLOB) 列;现在仍然将数据存储为 LONG 或 LONG raw 似乎已经过时了。

于 2015-04-24T18:02:52.740 回答
1

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;
于 2015-04-24T18:32:08.737 回答
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';

非常感谢。

于 2015-04-25T17:46:40.213 回答