sql >> データベース >  >> RDS >> Oracle

バイナリ文字列をCLOB列に格納できますか

    一般的に、それはできません。特に、データベースでUTF-8(現在のデフォルト)を使用している場合は、有効な文字と一致しないビット値が多数あり、それらはプレースホルダー(通常は¿)に置き換えられます。 )挿入して選択します。

    できることは、バイナリデータをBase64文字列としてエンコードすることです。これは、テキスト(XMLファイルやSMTPメールなど)のみをサポートするインターフェイスでバイナリデータを転送するための非常に一般的な方法です

    この関数を使用して、バイナリデータをテキストとしてエンコードします:

    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;
    

    そして、この関数は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;
    

    手順を確認できるインターネット上の多くのオンラインBase64デコーダー/エンコーダーを見つけます。




    1. サブクエリの順序は保持されることが保証されていますか?

    2. SQL ServerでFORMAT()を使用するときに不変カルチャを指定する方法

    3. MySQL高可用性フレームワークの説明–パートIII:障害シナリオ

    4. どのバージョンのPostgreSQLを実行していますか?