Pular para o conteúdo

Operações com LOBs (Large Objects): DBMS_LOB

DBMS_LOB: Operações com LOBs (Large Objects)

Os LOBs (Large Objects) são usados para armazenar grandes quantidades de dados, como imagens, áudios, vídeos e documentos de texto grande. O Oracle fornece o pacote DBMS_LOB para manipular LOBs. Vamos explorar algumas das operações comuns com LOBs.

Iniciando com LOBs

Existem basicamente dois tipos de LOBs: BLOB (para dados binários) e CLOB (para caracteres). Para armazenar LOBs, primeiro definimos colunas do tipo LOB:

CREATE TABLE my_table (
    id NUMBER,
    my_clob CLOB,
    my_blob BLOB
);

Inserindo dados em LOBs

Você pode inserir dados em LOBs como em outros tipos de colunas:

DECLARE
   l_clob CLOB := 'Este é um exemplo de CLOB';
   l_blob BLOB;
BEGIN
   -- Para BLOBs, vamos considerar que l_blob já contém algum dado binário.
   INSERT INTO my_table (id, my_clob, my_blob) VALUES (1, l_clob, l_blob);
END;
/

Lendo dados de LOBs

Para ler dados de LOBs, você pode simplesmente selecionar a coluna. No entanto, para propósitos de demonstração, podemos usar DBMS_LOB.SUBSTR para obter uma substring do CLOB:

SELECT id, DBMS_LOB.SUBSTR(my_clob, 20, 1) as sample_text FROM my_table WHERE id = 1;

Atualizando LOBs

Para atualizar um LOB, você pode usar a função DBMS_LOB.WRITE:

DECLARE
   l_clob CLOB;
BEGIN
   SELECT my_clob INTO l_clob FROM my_table WHERE id = 1 FOR UPDATE;
   DBMS_LOB.WRITE(l_clob, 11, 1, ' novo texto');
END;
/

Operações com DBMS_LOB

  • Append: Anexa um LOB ao final de outro.
DECLARE
   l_clob CLOB;
BEGIN
   SELECT my_clob INTO l_clob FROM my_table WHERE id = 1 FOR UPDATE;
   DBMS_LOB.APPEND(l_clob, ' Anexado');
END;
/
  • Length: Retorna o tamanho do LOB.
DECLARE
   l_length NUMBER;
   l_clob CLOB;
BEGIN
   SELECT my_clob INTO l_clob FROM my_table WHERE id = 1;
   l_length := DBMS_LOB.GETLENGTH(l_clob);
   DBMS_OUTPUT.PUT_LINE('Tamanho do CLOB: ' || l_length);
END;
/
  • Etc: Existem várias outras funções e procedimentos como ERASE, INSTR, TRIM, entre outros.

Exemplos práticos

Vamos criar um exemplo prático mais elaborado, onde uma empresa fictícia deseja armazenar contratos em PDF (formato binário) e sua descrição textual.

Pré-requisito

Tenha certeza de que o diretório contendo os PDFs que você deseja carregar esteja acessível pelo Oracle e que um diretório de banco de dados tenha sido definido para ele.

Por exemplo, se você tiver um diretório /meus_pdfs, você precisaria executar:

CREATE DIRECTORY pdf_dir AS '/meus_pdfs';

Lembre-se de conceder as permissões adequadas:

GRANT READ, WRITE ON DIRECTORY pdf_dir TO seu_usuário;
Criação da Tabela

Primeiro, criamos uma tabela para armazenar os contratos:

CREATE TABLE contratos (
   contrato_id NUMBER PRIMARY KEY,
   descricao CLOB,
   arquivo BLOB
);
Inserindo dados – Carregando um arquivo PDF em um BLOB
DECLARE
    l_bfile BFILE;
    l_blob  BLOB;
BEGIN
    -- Inicializando o BLOB
    INSERT INTO contratos (contrato_id, descricao, arquivo)
    VALUES (1, 'Descrição do contrato', EMPTY_BLOB())
    RETURNING arquivo INTO l_blob;
    
    -- Abrindo o arquivo do sistema de arquivos
    l_bfile := BFILENAME('PDF_DIR', 'nome_do_arquivo.pdf');
    
    -- Abre os LOBs
    DBMS_LOB.OPEN(l_bfile, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.OPEN(l_blob, DBMS_LOB.LOB_READWRITE);
    
    -- Carregando o BFILE no BLOB
    DBMS_LOB.LOADFROMFILE(l_blob, l_bfile, DBMS_LOB.GETLENGTH(l_bfile));
    
    -- Fechando os LOBs
    DBMS_LOB.CLOSE(l_bfile);
    DBMS_LOB.CLOSE(l_blob);
    
    -- Atualizando a tabela
    UPDATE contratos 
    SET arquivo = l_blob 
    WHERE contrato_id = 1;
    
    COMMIT;
END;
/
1 linha inserida.
Explicação
  1. BFILE: É um tipo de dado que representa um LOB armazenado fora do banco de dados, geralmente no sistema de arquivos.
  2. BFILENAME: Esta função retorna um locator para um BFILE. O primeiro argumento é o nome do diretório de banco de dados, e o segundo é o nome do arquivo.
  3. DBMS_LOB.LOADFROMFILE: Esta função carrega conteúdo de um BFILE para um BLOB (ou CLOB/NCLOB).

Após executar o procedimento acima, o arquivo PDF nome_do_arquivo.pdf será carregado no BLOB na tabela contratos para o contrato_id especificado.

Lembre-se: Sempre garanta que os tamanhos dos arquivos e os tamanhos permitidos para os BLOBs sejam compatíveis e que você tenha espaço suficiente no tablespace. Além disso, dependendo do tamanho do arquivo, você pode considerar opções adicionais para otimizar o desempenho.

Atualizando a Descrição do Contrato
DECLARE
    l_nova_descricao CLOB := ' (Atualizado em 20/08/2023)';
BEGIN
    UPDATE contratos
    SET descricao = descricao || l_nova_descricao
    WHERE contrato_id = 1;
END;
/

-- Verificando a atualização:

SELECT descricao FROM contratos WHERE contrato_id = 1;
Contrato de venda referente ao imóvel X. (Atualizado em 20/08/2023)
Consultando o Tamanho do Arquivo do Contrato
DECLARE
    l_tamanho NUMBER;
BEGIN
    SELECT DBMS_LOB.GETLENGTH(arquivo) 
    INTO l_tamanho 
    FROM contratos WHERE contrato_id = 1;

    DBMS_OUTPUT.PUT_LINE('Tamanho do arquivo: ' || l_tamanho || ' bytes');
END;
/
Tamanho do arquivo: 1024 bytes <o resultado será de acordo com o PDF que você utilizou>
Extraindo Parte da Descrição

Suponha que desejamos extrair os primeiros 20 caracteres da descrição para um resumo:

SELECT contrato_id, DBMS_LOB.SUBSTR(descricao, 20, 1) AS resumo 
FROM contratos WHERE contrato_id = 1;
Deletando um Contrato
DELETE FROM contratos WHERE contrato_id = 1;
1 linha deletada.

Conclusão

O pacote DBMS_LOB fornece uma variedade de funções úteis para manipular dados LOB. Neste exemplo, demonstramos algumas operações básicas para trabalhar com CLOBs e BLOBs em um cenário prático. Em uma aplicação real, a interação com BLOBs envolveria também a leitura e escrita de arquivos binários do sistema de arquivos. Porém, para fins de simplicidade, o exemplo acima é baseado apenas em texto.

Lembre-se, para operações complexas com LOBs, é crucial compreender as nuances de desempenho, especialmente ao lidar com objetos muito grandes.

Abs

Referências

Giovano Silva

Giovano Silva

Giovano Silva é um profissional com mais de 10 anos de experiência em tecnologias Oracle, com ênfase em PL/SQL. Ele adora escrever sobre soluções para problemas comuns enfrentados por profissionais Oracle em seu dia a dia. Seu objetivo é compartilhar conhecimento, simplificar conceitos complexos e ajudar a comunidade Oracle a crescer coletivamente.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress