quarta-feira, 1 de novembro de 2023

Functions, Triggers e Procedures no PostgreSQL

   

       Nesse artigo vou trazer um exemplo de Functions, Triggers e Procedures no PostgreSQL. Antes vamos entender um pouco a diferença entre eles:

         

1.   Funções (Functions):

·         As funções são rotinas ou subprogramas que recebem um ou mais parâmetros de entrada, realizam cálculos ou operações e retornam um valor.

·         Elas podem ser chamadas a partir de instruções SQL, expressões ou outras funções.

·         As funções podem ser usadas para encapsular lógica de negócio complexa e fornecer um resultado computado.

·         Exemplo: Uma função que calcula a idade com base na data de nascimento.

2.   Triggers:

·         Triggers são procedimentos armazenados que são automaticamente invocados em resposta a um evento específico que ocorre no banco de dados.

·         Eles são acionados por ações, como inserção, atualização ou exclusão de dados em uma tabela.

·         Os triggers podem ser usados para impor regras de negócio, manter integridade referencial, auditar alterações de dados, entre outras funcionalidades.

·         Exemplo: Um trigger que atualiza um campo de data de modificação sempre que uma linha é atualizada em uma tabela.

3.   Procedimentos (Procedures):

·         Os procedimentos são rotinas ou subprogramas que podem receber parâmetros de entrada, executar um conjunto de instruções e, opcionalmente, retornar valores.

·         Eles são usados para agrupar um conjunto de instruções que podem ser executadas repetidamente ou como uma unidade lógica.

·         Os procedimentos podem ser chamados a partir de outros procedimentos, instruções SQL ou de uma aplicação externa.

·         Exemplo: Um procedimento que insere um registro em uma tabela e atualiza um contador.

 

Agora vamos aos exemplos:

 

1 – Function

 

-- Função

CREATE OR REPLACE FUNCTION calcularIdade(data_nascimento DATE) RETURNS INTEGER AS

DECLARE

  idade INTEGER;

BEGIN

  idade := EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM data_nascimento);

  RETURN idade;

END;

LANGUAGE plpgsql;

 

--Chamada da função

SELECT calcularIdade('1990-05-10');

 

2 – Trigger

 

-- Temos uma tabela

CREATE TABLE produtos (

  id SERIAL PRIMARY KEY,

  nome VARCHAR(50),

  quantidade INTEGER,

  data_atualizacao DATE

);

 

-- Criação da função usada pelo Trigger

CREATE OR REPLACE FUNCTION atualizarDataAtualizacao()

  RETURNS TRIGGER AS

DECLARE

BEGIN

  NEW.data_atualizacao := CURRENT_DATE;

  RETURN NEW;

END;

LANGUAGE plpgsql;

 

-- Criação da Trigger

CREATE TRIGGER trigger_atualizar_data

  BEFORE INSERT OR UPDATE ON produtos

  FOR EACH ROW

  EXECUTE FUNCTION atualizarDataAtualizacao();

 

-- Utilização da Trigger ocorre automaticamente

INSERT INTO produtos (nome, quantidade) VALUES ('Produto A', 10);

UPDATE produtos SET quantidade = 20 WHERE id = 1; 

 

Note nesse trecho de código, na criação da função da trigger, o uso da palavra NEW. NEW é uma referência a uma variável especial em PL/pgSQL usada em gatilhos (triggers) no PostgreSQL. Quando um gatilho é acionado, ele tem acesso a duas variáveis especiais: OLD e NEW.

 

OLD contém os valores anteriores das colunas afetadas pela ação que disparou o gatilho.

NEW contém os novos valores que serão inseridos ou já foram inseridos devido à ação que disparou o gatilho.

 

No trecho de código acima, NEW.data_atualizacao está sendo usado para atribuir a data atual à coluna data_atualizacao da linha que está sendo inserida ou atualizada.

 

3 – Procedure

-- Criação da Procedure

CREATE OR REPLACE PROCEDURE inserirProduto(nome VARCHAR(50), quantidade INTEGER)

  AS

DECLARE

BEGIN

  INSERT INTO produtos (nome, quantidade, data_atualizacao)

  VALUES (nome, quantidade, CURRENT_DATE);

END;

LANGUAGE plpgsql;

 

-- Utilização da Procedure

CALL inserirProduto('Produto B', 15);

Programação funcional no Java (Java 8+)

      Nesse artigo vou falar um pouco sobre programação funcional no Java. A programação funcional se refere ao uso de conceitos e técnicas como funções de ordem superior, expressões lambda, programação sem efeitos colaterais, imutabilidade e streams, para escrever código mais conciso, legível (nem sempre) e robusto. Esses recursos estão disponíveis a partir do Java 8.

 

Aqui estão alguns conceitos chave relacionados à programação funcional no Java:

 

1. Expressões Lambda: As expressões lambda permitem definir funções anônimas (funções sem nome) de forma concisa. Elas são usadas em várias partes do código, como argumentos para métodos, implementações de interfaces funcionais e para criar objetos ‘Comparator’. É sempre bom lembrar da importância da legibilidade do código, porque nem todos tem a mesma experiência, e o uso exagerado pode atrapalhar. Um exemplo de função lambda:

 

  (a, b) -> a + b  // Uma expressão lambda que adiciona dois números

 

2. Interfaces Funcionais: As interfaces funcionais são interfaces que têm um único método abstrato. Alguns exemplos incluem ‘Function’, ‘Predicate’, ‘Consumer’ e ‘Supplier’. Você pode usar expressões lambda para implementar essas interfaces de maneira concisa.

 

3. Streams: Os Stream’s são sequências de elementos que podem ser processadas de forma funcional. Eles permitem realizar operações de consulta, transformação e agregação em coleções de dados, como listas e conjuntos. Os Stream’s operam de forma lazy e podem ser processados sequencialmente ou em paralelo.

 

4. Imutabilidade: A programação funcional incentiva a imutabilidade, o que significa que objetos não devem ser alterados após a criação. Em vez disso, você cria novos objetos com base em objetos existentes. Isso evita efeitos colaterais e torna o código mais previsível.

 

5. Funções de Ordem Superior: Funções de ordem superior são funções que podem receber outras funções como argumentos e/ou retornar funções como resultado. No Java, usando programação funcional, você pode passar funções como argumentos para métodos e implementar métodos que aceitam funções como parâmetros.

 

6. Recursão Funcional: A programação funcional incentiva o uso de recursão funcional, onde os métodos se chamam de forma recursiva, evitando loops tradicionais. Isso promove um código mais declarativo. Porém tem que se tomar muito cuidado, pois o Java faz uso da pilha de chamadas, e caso essas chamadas recursivas sejam muito longas pode quebrar. Embora esteja disponível, é uma boa prática dar preferência  aos loops tradicionais caso o número de chamadas seja desconhecido ou sabidamente grande.

 

Aqui está um exemplo de programação funcional usando uma expressão lambda e um Stream:

 

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);

 

//  calcular a soma dos quadrados dos números pares

int somaDosQuadradosDosPares = numeros.stream()

    .filter(n -> n % 2 == 0)  // Filtrar números pares

    .map(n -> n * n)  // Elevar ao quadrado

    .reduce(0, Integer::sum);  // Somar os resultados

 

System.out.println(somaDosQuadradosDosPares);  // Saída: 20

 

        A função ‘filter’ filtra os números pares, a função ‘map’ eleva ao quadrado (ambas usando expressão lambda) e ‘reduce’ soma os resultados. Isso ilustra a programação funcional em Java, tornando o código mais enxuto, embora nem sempre mais claro. 

Transformando String de Inteiros em Lista usando Programação Funcional

             Nesse artigo vou mostrar como transformar uma String de números inteiros separadas por “;” em um Array de Integer usando programação funcional em Java.

         

       A programação funcional ajuda muito a reduzir códigos, embora possa também, dependendo da forma que utilizada, perder um pouco legibilidade dele. Então as vezes usar uma forma não tão reduzida das funções e colocar comentários ajuda bastante. Lembre-se que nem todo mundo que programa tem o mesmo nível de experiência.

 

          O código abaixo monta um Stream (Um Stream é uma sequência de elementos que pode ser processada de forma sequencial ou paralela) a partir do split da String, usando o Map para transformar os dados (ele pode ser usado para converter tipos de dados, para chamar funções como UpperCase, etc.) e depois retornados como uma lista.

 

import java.util.Arrays;

import java.util.List;

import java.util.stream.Collectors;

 

public class Exemplo {

    public static void main(String[] args) {

 

        String str = "10;20;30;40;50";

  

        List<Integer> integerList = Arrays.stream(str.split(";"))

                .map(Integer::parseInt)

                .collect(Collectors.toList());

       

        integerList.forEach(System.out::println);

    }

}