Sejam muito bem-vindos à Alura. Meu nome é Vinicius Dias, embora vocês não estejam me vendo eu vou guiar vocês por mais um treinamento de programação utilizando PostgreSQL.
Neste treinamento vamos ver algumas coisas bem interessantes. Como por exemplo vamos resolver aquele problema de que alguém poderia simplesmente inserir um instrutor se executar a função e não teríamos os logs.
Vamos resolver isso e além de resolver vamos complementar nossa função com muitas coisas interessantes, com algumas verificações a mais, e com isso nesse processo vamos aprender algumas pegadinhas sobre gerenciamento de transação dentro de funções, utilizando plpgsql, vamos ver como gerenciar, como tratar e como gerar erros, e como isso pode ser útil para nós.
também vamos falar um pouco sobre como o Postgres trabalha por baixo dos pano em alguns casos, utilizando cursores. Vamos ver como criar na mão algum cursor, mas vamos entender que o PostgreSQL já faz em diversos casos esse trabalho de forma automática para nós.
vamos aprender sobre blocos anônimos, vamos conversar um pouco sobre boas práticas, vamos conversar sobre algumas ferramentas de mercado. Vai ser um bate-papo legal, espero que você aproveite. E durante o treinamento, caso você fique com alguma dúvida, não hesite. Você pode abrir uma dúvida lá no fórum.
Eu tento ajudar pessoalmente sempre que possível, mas quando não consigo nossa comunidade de alunos, moderadores e instrutores é muito solícita e alguém com certeza vai conseguir te ajudar.
Espero que você tire proveito deste treinamento, espero que você aprenda bastante, e te vejo no próximo vídeo para começarmos a conversar sobre o que vamos fazer, começar a brincar um pouco.
Sejam bem-vindos de volta. Nesse treinamento vamos dar continuidade no que trabalhamos, no último treinamento, sobre programação utilizando o Postgres. Qual o problema que encontramos? Qual situação nos deparamos no final do último treinamento?
Temos uma função muito interessante que cria um instrutor, e baseado na criação desse instrutor, registra alguns logs, informando se esse instrutor recebe ou não acima da média, informando ainda quantos instrutores recebem menos.
Fiz uma pequena modificação aqui, que disse que esse tipo decimal só vai ter cinco dígitos, sendo dois deles depois da casa decimal. Dessa forma temos uma representação um pouco mais amigável.
Mas continuando, ele salva dois logs, então armazenei alguns logs para vocês darem uma olhada em como temos isso desenvolvido. Esse ponto já fizemos no último treinamento, caso você não esteja entendendo o que está acontecendo aqui é porque você ainda não fez o último treinamento, então corre lá.
Mas continuando, nosso problema é que posso muito bem fazer diretamente um insert into instrutor, passar os campos, os valores necessários para instrutor, passar o nome e salário, e isso não vai armazenar meu log.
Isso vai fazer com que eu tenha minha tabela de logs desatualizada. Isso vai fazer com que eu não tenha todas as informações necessárias, e isso vai fazer com que eu possa arbitrariamente inserir instrutores que recebem muito mais do que a média sem que eu tenha nenhuma informação sobre isso de forma mais direta, sendo que preciso de forma manual sempre ficar monitorando a tabela de instrutores, sendo que já tenho a tabela de instrutores, que me traz essas informações com mais detalhes.
O que eu quero é que quando, e absorva essa palavra, quando eu inserir um instrutor, alguma coisa precisa acontecer. E se tenho a palavra quando, normalmente, pensando principalmente em programação, caso você já esteja familiarizado com programação, mas mesmo que não esteja, na vida real mesmo, quando temos a palavra quando remetemos ao conceito de eventos, pensamos logo em um evento que pode acontecer.
No evento de inserção de um instrutor quero que algo aconteça. Pode ser logo antes de inserir esse instrutor, pode ser logo depois de inserir esse instrutor, e vamos trabalhar em cima dessa ideia de eventos.
Eventos no banco de dados possuem um nome um pouco diferente, vamos dizer assim, mas é algo bastante comum, que são os triggers. Ou gatilhos, trazendo para o português.
Os triggers no bancos de dados são formas de executar um código sempre que algum evento acontecer. Então, por exemplo, caso eu tenha após inserir algo, eu vou realizar alguma função. É esse o tipo de funcionalidade, essa é a funcionalidade que precisamos para atingir nosso objetivo.
Precisamos criar triggers, ou precisamos criar gatilhos para que quando um instrutor for inserido, por exemplo, logo depois que eu inseri um instrutor, eu executar todo esse código. Todo esse pedaço de código.
O que queremos que aconteça? Queremos que esse insert
seja executado normalmente pelo usuário, pela pessoa que está utilizando o banco de dados. A pessoa vai executar o insert
e automaticamente, por baixo dos panos, o banco de dados, o PostgreSQL vai falar “opa, um instrutor foi inserido, então preciso executar tudo isso de forma automática, porque sei que preciso, fui configurado para isso”.
Essa configuração, essa ideia de criar um evento, de criar um gatilho para executar quando um evento acontecer é o que vamos trabalhar nesse capítulo. No próximo vídeo paramos de falação e finalmente partimos para a prática.
Bem-vindos de volta. Vamos editar essa funcionalidade para que possamos utilizar triggers. No PostgreSQL como fazemos para criar um trigger? Precisamos definir o que é conhecido como trigger procedure, uma função que vai gerar um trigger. E se ela vai gerar um trigger, se ela vai gerar um gatilho, precisamos dizer que ela retorna um gatilho, certo? Então ela não mais vai retornar nada. O retorno dessa função vai ser um gatilho.
Continuando, uma coisa muito importante é que sempre que temos uma função que vai ser executada através de um trigger, não vamos receber nenhum parâmetro, não podemos receber nenhum parâmetro.
“Mas Vinicius, então como vou saber o nome do instrutor, o salário do instrutor que está sendo inserido?”, e aí que está uma coisa muito interessante. Em funções que são executadas por trigger, temos algumas variáveis especiais, definidas automaticamente pelo Postgres.
Vamos dar uma olhada na documentação para que você possa ver algumas dessas variáveis. Temos a variável new, que é do tipo record,
ou seja, é aquele tipo genérico, pode vir qualquer coisa nessa variável. E ela vai ter a nova linha quando estivermos realizando um insert
com update, e se for um delete que estamos tratando, essa new não vai ter nada.
Se eu estou executando um insert
e um trigger é ativado, um gatilho é executado, então essa variável new vai ter exatamente a linha que está seno inserida. É isso que preciso. Através da variável new
, consigo acessar o nome, e consigo acessar o salário do instrutor que está sendo inserido.
Logo, não preciso mais desses parâmetros mesmo. Show de bola, não temos problema nenhum quanto a isso. Continuando, esse insert
obviamente vai ter que sair, porque não vamos mais executar o insert
aqui. Quando o insert
for executado, essa função vai ser chamada, ou seja, o instrutor
já foi inserido.
Vou remover isso e colar lá embaixo para não me esquecer, e vamos continuar. Sendo assim também não preciso do id do instrutor inserido, porque tenho lá naquela variável new
. Vou tirar isso e vamos modificar nossa função para que ela utilize aquele new
.
Estamos pegando a média salarial da tabela instrutor
onde o id não é igual a NEW.id
, ou seja, não é igual ao id que acabou de ser inserido. Moleza até aqui. Estamos verificando se o salário do instrutor recém-inserido, então NEW.salario
, é maior do que a média.
Até aqui só facilidade. Vou inserir NEW.nome
, ou seja, o nome do instrutor recém-inserido. Até aqui tem sido bem tranquilo, vamos continuar. Para cada salário dos meus instrutores, da tabela de instrutor, de novo, diferente do id recém-inserido.
No if são todas as variáveis, NEW.salario
, se o salário que estou inserindo agora for maior do que o salário percorrido desse select
vou adicionar no contador e show de bola. Depois NEW.nome
, que pega o percentual, e a princípio temos nossa função completa.
Vou fazer um drop
dessa função porque lembra que se alteramos os parâmetros ou se alteramos o tipo de retorno não posso substituir, então DROP FUNCTION cria_instrutor
. Removi essa função, agora vou recriar como uma trigger procedure, e vamos ver se vai dar tudo certo.
A princípio está tudo ok, então já temos uma função que gera um trigger, só que ainda não tenho o trigger criado, ainda não tenho efetivamente a ação configurada para ser executada depois do insert.
“Mas como não, Vinicius? A função está criada”. Sim, a função está criada, mas em que momento aqui estou dizendo que essa função vai ser executada depois de um insert
na tabela instrutor? Ainda não configurei isso. Então antes de configurarmos, vamos dar uma batida de olho, uma passada de olho bem rápida sobre trigger procedures, ou seja, sobre funções que são executadas com triggers, para vermos algumas particularidades.
Temos diversas variáveis especiais, temos o new, que é o que utilizamos, ou seja, a nova linha que está sendo inserida, ou a nova linha depois de ser atualizada. Temos o old
, que é a linha que está sendo removida, ou a linha antes da alteração, antes do update
ser executado. E temos várias variáveis especiais. Vai ser o nome do trigger que está sendo executado, quando esse trigger está sendo executado, se é antes, se é depois, se é ao invés de alguma instrução.
O nível, e isso podemos tratar com um pouco mais de detalhes depois. Mas basicamente se é para cada linha ou para cada instrução executada. Dos conversamos sobre isso. Qual operação está sendo executada, se é um insert
, um update
, um delete, um truncate
.
O id da tabela que foi modificada para gerar esse trigger, o nome da tabela que foi modificada. Tem muita coisa aqui. Você pode passar o olho depois e ver todas as variáveis com detalhes. Mas uma coisa interessante que quero mostrar aqui é que caso eu queira, por exemplo, baseado em uma condição cancelar a inserção de um instrutor, se esse instrutor estivesse acima da média, quero cancelar ele.
Essa função precisaria retornar, por exemplo, está acima da média salarial, vou retornar nulo, RETURN NULL
. O que isso faria? Quando retorno nulo, sou permitido retornar nulo, primeiro é importante deixar isso claro, sou permitido retornar nulo, e caso eu retorne nulo, em uma função que é executada antes do insert
, por exemplo, então se eu tivesse um trigger before insert
, antes de inserir instrutor, o que vai acontecer?
Quando eu retornar nulo o trigger vai dizer para o Postgres “eu estou retornando nulo, isso quer dizer que a instrução não vai ser executada”. Então quando tenho um trigger que vai ser executado antes de uma funcionalidade, antes de uma instrução, eu cancelo a instrução quando retorno nulo.
Agora, caso eu queira que a instrução seja executada, posso a princípio não retornar nada, ou o que é bastante comum, posso retornar essa nova linha, esse novo registro. Essa é a palavra que eu estava buscando. Posso retornar esse novo registro informando que está tudo ok, que tudo deu certo, e isso é bastante comum.
Mas no nosso caso, para não confundir, vou deixar sem nada. De novo, esses detalhes, essas particularidades podemos bater um papo com mais detalhes, com mais especificidade, com mais profundidade em um futuro vídeo. Só queria dar uma passada bem rápida depois de criarmos a função nas variáveis especiais que temos de bandeja, que o Postgres já cria para nós. E também nesse detalhe de que posso cancelar uma execução se meu trigger for criado para antes da instrução.
Mas estou falando dessa parte de criar trigger
e por enquanto só tenho a função. No próximo vídeo, porque esse já está longo, vamos finalmente criar esse trigger
.
O curso PostgreSQL: Triggers, transações, erros e cursores possui 116 minutos de vídeos, em um total de 52 atividades. Gostou? Conheça nossos outros cursos de SQL e Banco de Dados em Data Science, ou leia nossos artigos de Data Science.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.