Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Czy mogę przechowywać ciąg binarny w kolumnie CLOB?

Generalnie nie możesz tego zrobić. Zwłaszcza jeśli twoja baza danych używa UTF-8 (obecnie domyślne), masz wiele wartości bitowych, które nie pasują do prawidłowego znaku i zostałyby zastąpione symbolem zastępczym (zazwyczaj ¿ ) podczas wstawiania i zaznaczania.

To, co możesz zrobić, to zakodować dane binarne jako ciąg Base64. Jest to bardzo powszechny sposób przesyłania danych binarnych przez interfejsy, które obsługują tylko tekst (np. pliki XML lub wiadomości SMTP)

Użyj tej funkcji, aby zakodować dane binarne jako tekst:

FUNCTION EncodeBASE64(InBlob IN BLOB) RETURN CLOB IS

    BlobLen INTEGER := DBMS_LOB.GETLENGTH(InBlob);
    read_offset INTEGER := 1;
    warning INTEGER;

    amount INTEGER := 1440; -- must be a whole multiple of 3
    -- size of a whole multiple of 48 is beneficial to get NEW_LINE after each 64 characters 
    buffer RAW(1440);
    res CLOB := EMPTY_CLOB();

BEGIN

    IF InBlob IS NULL OR NVL(BlobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF BlobLen <= 24000 THEN
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(InBlob));
    ELSE
        -- UTL_ENCODE.BASE64_ENCODE is limited to 32k, process in chunks if bigger
        LOOP
            EXIT WHEN read_offset >= BlobLen;
            DBMS_LOB.READ(InBlob, amount, read_offset, buffer);
            res := res || UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(buffer));       
            read_offset := read_offset + amount;
        END LOOP;
    END IF;
    RETURN res;

END EncodeBASE64;

I ta funkcja do konwersji z powrotem do BLOB

FUNCTION DecodeBASE64(InBase64Char IN CLOB) RETURN BLOB IS

    res BLOB;
    clob_trim CLOB;

    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    ClobLen INTEGER := DBMS_LOB.GETLENGTH(InBase64Char);

    amount INTEGER := 1440; -- must be a whole multiple of 4
    buffer RAW(1440);
    stringBuffer VARCHAR2(1440);
    -- BASE64 characters are always simple ASCII. Thus you get never any Mulit-Byte character and having the same size as 'amount' is sufficient

BEGIN

    IF InBase64Char IS NULL OR NVL(ClobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF ClobLen <= 32000 THEN
        RETURN TO_BLOB(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(InBase64Char)));
    ELSE
        -- Remove all NEW_LINE from base64 string
        DBMS_LOB.CREATETEMPORARY(clob_trim, TRUE);
        LOOP
            EXIT WHEN read_offset > ClobLen;
            stringBuffer := REPLACE(REPLACE(DBMS_LOB.SUBSTR(InBase64Char, amount, read_offset), CHR(13), NULL), CHR(10), NULL);
            DBMS_LOB.WRITEAPPEND(clob_trim, LENGTH(stringBuffer), stringBuffer);
            read_offset := read_offset + amount;
        END LOOP;

        read_offset := 1;
        ClobLen := DBMS_LOB.GETLENGTH(clob_trim);
        DBMS_LOB.CREATETEMPORARY(res, TRUE);
        LOOP
            EXIT WHEN read_offset > ClobLen;
            buffer := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(clob_trim, amount, read_offset)));
            DBMS_LOB.WRITEAPPEND(res, DBMS_LOB.GETLENGTH(buffer), buffer);
            read_offset := read_offset + amount;
        END LOOP;
        DBMS_LOB.FREETEMPORARY(clob_trim);
    END IF;

    RETURN res;    

END DecodeBASE64;

W Internecie można znaleźć wiele dekoderów/koderów Base64, w których można zweryfikować swoją procedurę.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle JDBC ojdbc6 Jar jako zależność Maven

  2. TO_TIMESTAMP_TZ() Funkcja w Oracle

  3. Klauzula Where Oracle SQL do znajdowania rekordów dat starszych niż 30 dni

  4. Zapytanie rekurencyjne w Oracle

  5. Kalkulacja średnich kosztów zapasów w SQL