Last active
July 8, 2022 12:20
-
-
Save edgarsandi/7800b55e491adebf78d5 to your computer and use it in GitHub Desktop.
PL/SQL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Edgar Rodrigues Sandi | |
Edgar Sandi | |
tw/@EdgarSandi | |
fb/EdgarSandi | |
G+/EdgarSandi | |
Ln/EdgarSandi | |
Oracle PL/SQL - 24h | |
Aula 1 - 17/01 | |
Aula 2 - 24/01 | |
Aula 3 - 31/01 | |
Aula 4 - 07/02 | |
Aula 5 - 21/02 | |
Aula 6 - 28/02 | |
Alunos: | |
Leonardo Lima - ALUNO ORACLE ESSENCIAL e PLSQL NOV/2014 <[email protected]>, | |
Mario Celso Gonçalves de Souza - ALUNO ORACLE ESSENCIAL e PLSQL NOV/2014 <[email protected]>, | |
Amanda Cortez Machado - ALUNO ORACLE ESSENCIAL e PLSQL NOV/2014 <[email protected]>, | |
Thiago Arantes Magalhães - ALUNO ORACLE ESSENCIAL e PLSQL NOV/2014 <[email protected]>, | |
Bruno Gabriel dos Santos - ALUNO ORACLE PLSQL JAN/2014 <[email protected]>, | |
Cesar Figueiredo Augusto - ALUNO ORACLE PLSQL JAN/2015 <[email protected]> | |
-- PL/SQL | |
-- Program Language SQL | |
-- Programação no Banco de dados | |
-- Transaction SQL - SQL Server | |
-- PG/PLSQL - PostgreSQL | |
-- PL/SQL - MySQL | |
-- regras de negócio | |
-- procedures - Stored Procedures | |
-- packages | |
-- triggers | |
-- functions | |
-- blocos anônimos | |
-- ESCOPO básico de um bloco anônimo | |
[DECLARE] -- opcional | |
-- declaração das variáveis | |
BEGIN | |
-- progamação | |
-- regras de negócios | |
[EXCEPT] | |
-- Tratamentos de erros | |
END; | |
-- enviar texto ao console | |
BEGIN | |
dbms_output.put_line('Hello world'); | |
END; | |
-- comentário de linha | |
/* | |
comentário de bloco | |
// comentário de linha | |
# comentário de linha | |
*/ | |
-- Variáveis no PL/SQL ou em qualquer lugar | |
-- Nomes de variáveis com no máximo 30 caracteres | |
-- Use no nome da variávle algo que descreva muito bem do que | |
-- se trata | |
-- Inicie com letra ou _ | |
-- Não usar palavras reservadas do Oracle | |
-- Não usar caracteres especiais (ç , ^, ~, ...) | |
-- _ e o # podem ser utilizados | |
-- Quando o nome for composto utilize o camelCase | |
-- camelCase -> variavelComPadraoCamelCase | |
-- variaveis | |
-- funções | |
-- metodos | |
-- StudlyCaps -> VariavelComPadraoStudlyCaps | |
-- classes, intefaces, enum | |
-- constantes -> IDADE | |
-- constante composta -> IDADE_DO_ALUNO | |
-- Utilização das aspas simples e aspas duplas | |
-- Utilização da apóstrofe ou das aspas | |
-- "" -> identificação de objetos (tabelas, procedures...) | |
-- '' -> identificação de textos | |
DECLARE | |
-- <nome> <tipo> := <valor>; | |
x number; -- 38 digitos | |
contadorDeAlunos number(2); | |
preco number(6, 2); -- 9999,99 | |
vNome varchar(50); | |
vUF char(2); | |
vSexo1 char(1) := 'M'; | |
ano date; | |
nivel constant varchar(50) := 'admin'; | |
vSexo2 char(1) := 'M'; | |
vIdade number(3); -- -999 a 999 | |
vIdade positiveN := 10; | |
-- binary_integer -> -2^31 a +2^31 | |
-- positiveN -> binary_integer positivos e não nulos | |
BEGIN | |
dbms_output.put_line(vSexo2); | |
vSexo2 := 'F'; | |
dbms_output.put_line(vSexo2); | |
END; | |
-- Olá <meu nome>, tudo bem? | |
DECLARE | |
vMeuNome varchar(50); | |
BEGIN | |
vMeuNome := 'Edgar Rodrigues Sandi'; | |
dbms_output.put_line('Olá ' || vMeuNome || ', tudo bem?'); | |
END; | |
-- Transações - transaction | |
-- Iniciar -> START TRANSACTION - BEGIN TRANSACTION - BEGIN | |
-- Confirmar -> COMMIT | |
-- Desfazer -> ROLLBACK | |
SELECT * FROM tb_alunos; | |
START TRANSACTION | |
DELETE FROM teste; | |
COMMIT; | |
ROLLBACK; | |
SELECT * FROM teste; | |
-- ACID | |
A -> Atomicidade | |
C -> consistencia | |
I -> isolamento | |
D -> durabilidade | |
-- Operadores de condição | |
/* | |
se <condiçao> então | |
<comandos> | |
senão | |
<comandos> | |
*/ | |
if <condicao> then / elsif | |
true -> 'a' 1, 6, 9 | |
false -> '', 0, null, | |
DECLARE | |
a boolean := true; | |
b boolean := false; | |
c boolean := null; | |
vTeste boolean; | |
BEGIN | |
vTeste := (b AND NOT c) OR NOT(a = b) AND (c IS NULL); | |
-- true ou true e true | |
if (vTeste = true) then | |
dbms_output.put_line('vTeste = true'); | |
elsif (vTeste = false) then | |
dbms_output.put_line('vTeste = false'); | |
elsif (vTeste IS NULL) then | |
dbms_output.put_line('vTeste is null'); | |
else | |
dbms_output.put_line('NDA'); | |
end if; | |
END; | |
DECLARE | |
a boolean := true; | |
BEGIN | |
dbms_output.put_line('a = '); | |
if not a then | |
dbms_output.put_line('false'); | |
else | |
dbms_output.put_line('true'); | |
end if; | |
END; | |
-- refatoramos | |
-- DRY -> Don't repeat yourself | |
-- KISS -> Keep It Simple Stupid | |
-- lab: 01 | |
Dado um código, nome e sexo | |
Responda: | |
-- Olá aluna <nome>, seu código é <código> | |
-- Olá aluno <nome>, seu código é <código> | |
DECLARE | |
vCodigo number := 1; | |
vNome varchar(50) := 'Joana'; | |
vSexo char(1) := 'M'; | |
vResult varchar(10); | |
BEGIN | |
vResult := 'aluno'; | |
IF vSexo = 'F' THEN | |
vResult := 'aluna'; | |
END IF; | |
dbms_output.put_line('Ola '|| vResult || ' ' ||vNome||', seu código e: '|| vCodigo); | |
END; | |
-- Lab02: | |
-- Dado 4 notas, calcule a média e: | |
-- se a média for maior que 7 mostre: Aprovado | |
-- se a média for igual a 7 mostre: Em recuperação | |
-- se a média for menor que 7 mostre: Reprovado | |
DECLARE | |
vNota1 number(2); | |
vNota2 number(2); | |
vNota3 number(2); | |
vNota4 number(2); | |
vMedia number(4, 2); | |
BEGIN | |
vMedia := (&vNota1 + &vNota2 + &vNota3 + &vNota4) /4; | |
IF vMedia = 7 THEN | |
dbms_output.put_line('Recuperação'); | |
ELSIF vMedia > 7 THEN | |
dbms_output.put_line('Aprovado'); | |
ELSE | |
dbms_output.put_line('Reprovado'); | |
END IF; | |
END; | |
-- Homework PL/SQL | |
1. Calculadora | |
-- dados dois valores e a operação matemática | |
-- execute a operação e mostre o valor na saída dbms | |
2. Conversor de temperatura | |
-- Dada a temperatura em fahrenheit converta para celsius | |
-- fórmula 'ºC = (ºF - 32) / 1,8' | |
Respostas: | |
1. Calculadora | |
DECLARE | |
a number(2); | |
b number(2); | |
vOperacao char(1); | |
vResultado number(3); | |
BEGIN | |
a := &a; | |
vOperacao := &vOperacao; --- + | |
b := &b; | |
-- vOperacao := '' || vOperacao || ''; | |
-- vOperacao := CONCAT(CONCAT(q'[']', vOperacao), q'[']'); | |
dbms_output.put_line(vOperacao); | |
if vOperacao = '+' then | |
vResultado := a + b; | |
elsif vOperacao = '-' then | |
vResultado := a - b; | |
elsif vOperacao = '*' then | |
vResultado := a * b; | |
elsif vOperacao = '/' then | |
vResultado := a / b; | |
end if; | |
dbms_output.put_line('Resultado da operacao: ' || vResultado); | |
END; | |
2. Conversor de temperatura | |
DECLARE | |
vFahrenheit number(2) := 40; | |
vCelsius number(2); | |
BEGIN | |
vCelsius := (vFahrenheit - 32) / 1.8; | |
dbms_output.put_line('Resultado: ' || vCelsius || 'º Celsius'); | |
END; | |
-- Tabela cidades | |
CREATE TABLE tb_cidades( | |
cd_cidade number(5) primary key, | |
nm_cidade varchar(50) not null, | |
tx_uf char(2) not null | |
); | |
-- INSERINDO VALORES | |
INSERT INTO tb_cidades (cd_cidade, nm_cidade, tx_uf) | |
VALUES (seq_cidade.nextval, 'Sao Paulo', 'SP'); | |
INSERT INTO tb_cidades (cd_cidade, nm_cidade, tx_uf) | |
VALUES (seq_cidade.nextval, 'Sao Jose dos Campos', 'SP'); | |
-- SEQUENCE | |
-- MySQL - autoincrement | |
-- PostgreSQL - serial | |
-- Oracle - SEQUENCE | |
-- current value? currval | |
-- next value? nextval | |
CREATE SEQUENCE <sequencia>; | |
CREATE SEQUENCE seq_cidade; | |
-- Para descobrir o valor atual? | |
SELECT seq_cidade.currval FROM dual; | |
-- Inicializar ou pegar o próximo valor | |
SELECT seq_cidade.nextval FROM dual; | |
-- TYPES | |
-- Usando o Type para capturar o tipo de dado de uma coluna | |
-- exemplo sem usar o type | |
DECLARE | |
vCidade varchar(50) := 'Taubaté'; | |
vUf char(2) := 'SP'; | |
vCod number(5); | |
BEGIN | |
INSERT INTO tb_cidades (cd_cidade, nm_cidade, tx_uf) | |
VALUES (seq_cidade.nextval, vCidade, vUf) | |
RETURNING cd_cidade INTO vCod; | |
dbms_output.put_line('A cidade ' || vCidade || ' foi cadastrada com o id ' || vCod); | |
END; | |
-- exemplo usando o type | |
DECLARE | |
vCidade tb_cidades.nm_cidade%type := 'Guaratingueta'; | |
vUf tb_cidades.tx_uf%type := 'SP'; | |
vCod tb_cidades.cd_cidade%type; | |
BEGIN | |
INSERT INTO tb_cidades (cd_cidade, nm_cidade, tx_uf) | |
VALUES (seq_cidade.nextval, vCidade, vUf) | |
RETURNING cd_cidade INTO vCod; | |
dbms_output.put_line('A cidade ' || vCidade || ' foi cadastrada com o id ' || vCod); | |
END; | |
-- com o ROWTYPE | |
DECLARE | |
vReg tb_cidades%rowtype; | |
vCod vReg.cd_cidade%type; | |
BEGIN | |
vReg.nm_cidade := 'Pindamonhangaba'; | |
vReg.tx_uf := 'SP'; | |
INSERT INTO tb_cidades (cd_cidade, nm_cidade, tx_uf) | |
VALUES (seq_cidade.nextval, vReg.nm_cidade, vReg.tx_uf) | |
RETURNING cd_cidade INTO vCod; | |
dbms_output.put_line('A cidade ' || vReg.nm_cidade || ' foi cadastrada com o id ' || vCod); | |
END; | |
-- SUBTYPE | |
DECLARE | |
SUBTYPE idade IS NUMBER; | |
vIdadeHumana idade(3); | |
vIdadeRochas idade(20); | |
SUBTYPE Word is CHAR(20); | |
verb Word; | |
other Word; | |
more Word; | |
BEGIN | |
END; | |
-- OFFTOPIC - Criando tipos de dados no Oracle | |
TYPE | |
CREATE OR REPLACE TYPE <nome> | |
AS OBJECT ( | |
); | |
-- esquentando o cerebro | |
CREATE OR REPLACE TYPE full_name_type | |
AS OBJECT( | |
First_name varchar(30), | |
Last_name varchar(30) | |
); | |
CREATE OR REPLACE TYPE full_mailing_address_type | |
AS OBJECT( | |
Street varchar(80), | |
City varchar(80), | |
State char(2), | |
Zip char(9) | |
); | |
CREATE TABLE customer( | |
full_name full_name_type, | |
full_address full_mailing_address_type | |
); | |
-- Inserindo registros | |
INSERT INTO customer(full_name, full_address) | |
VALUES( | |
full_name_type('Edgar', 'Sandi'), | |
full_mailing_address_type('Av. Nelson DAvila', 'SJC', 'SP', '12200-000') | |
); | |
SELECT c.full_name.first_name FROM customer c; | |
-- ESCOPO de variáveis | |
DECLARE | |
x1 number := 5; | |
BEGIN | |
DECLARE | |
x2 number := 7; | |
BEGIN | |
DECLARE | |
x3 number := 9; | |
BEGIN | |
dbms_output.put_line(x3); | |
END; | |
dbms_output.put_line(x2); | |
END; | |
dbms_output.put_line(x1); | |
END; | |
-- quiz | |
DECLARE | |
x1 number := 5; | |
BEGIN | |
x1 := x1 + 3; | |
dbms_output.put_line('ETAPA 1 = ' || x1); -- 8 | |
DECLARE | |
x2 number := 7; | |
BEGIN | |
x1 := x1 + x2; | |
dbms_output.put_line('ETAPA 2 = ' || x1); -- 15 | |
DECLARE | |
x1 number := 9; | |
BEGIN | |
x1 := x1 + x2 - 3; | |
dbms_output.put_line('ETAPA 3 = ' || x1); -- 13 | |
END; | |
x1 := x1 - 1; | |
dbms_output.put_line('ETAPA 4 = ' || x1); -- 14 | |
END; | |
dbms_output.put_line('ETAPA 5 = ' || x1); -- 14 | |
END; | |
-- CASE | |
DECLARE | |
vPartido varchar(10) := 'PSOL'; | |
BEGIN | |
CASE vPartido | |
WHEN 'PT' THEN | |
dbms_output.put_line('PT'); | |
WHEN 'PSDB' THEN | |
dbms_output.put_line('PSDB'); | |
WHEN 'PMDB' THEN | |
dbms_output.put_line('PMDB'); | |
WHEN 'PSOL' THEN | |
dbms_output.put_line('PSOL'); | |
ELSE | |
dbms_output.put_line('NA'); | |
END CASE; | |
END; | |
--- Estruturas de repetição | |
ESCOPO | |
LOOP | |
EXIT WHEN <condicao> | |
END LOOP; | |
-- exemplo contador | |
DECLARE | |
x number := 1; | |
BEGIN | |
dbms_output.put_line('Inicio do LOOP'); | |
LOOP | |
dbms_output.put_line('x = ' || x); | |
EXIT WHEN x = 5; | |
x := x + 1; | |
END LOOP; | |
dbms_output.put_line('Final do LOOP'); | |
END; | |
-- WHILE | |
ESCOPO | |
WHILE <condicao> LOOP | |
<comandos> | |
END LOOP; | |
DECLARE | |
x number := 1; | |
BEGIN | |
dbms_output.put_line('Inicio do LOOP'); | |
WHILE x <= 10 LOOP | |
dbms_output.put_line('x = ' || x); | |
x := x + 1; | |
END LOOP; | |
dbms_output.put_line('Final do LOOP'); | |
END; | |
-- Lab03: - Pl/SQL | |
-- Se você guardar R$ 120,00 por mês na poupança, | |
-- quando você terá 1 milhão de reais? | |
-- rendimento: 0.5% => 0.005 => 1.005 | |
-- fórmula: total = (total + deposito) * rendimento | |
DECLARE | |
vMensal number(8,2) := 120.00; | |
vRendimento number(6,3) := 1.005; | |
vSaldo number(10,2) := 0; | |
vMeses number := 0; | |
BEGIN | |
WHILE vSaldo <= 1000000 LOOP | |
vMeses := vMeses + 1; | |
vSaldo := (vSaldo + vMensal) * vRendimento; | |
END LOOP; | |
dbms_output.put_line('Meses: ' || vMeses); | |
dbms_output.put_line('Anos: ' || vMeses/12); | |
dbms_output.put_line('Anos: ' || ROUND(vMeses/12,0)); | |
dbms_output.put_line('Anos: ' || FLOOR(vMeses/12)); | |
dbms_output.put_line('Anos: ' || CEIL(vMeses/12)); | |
dbms_output.put_line('Anos: ' || TRUNC(vMeses/12)); | |
dbms_output.put_line('Saldo final: ' || vSaldo); | |
END; | |
-- FOR | |
FOR <var> IN <inicio> .. <fim> LOOP | |
END LOOP; | |
-- exemplo crescente | |
BEGIN | |
dbms_output.put_line('Inicio do LOOP'); | |
FOR x IN 1 .. 10 LOOP | |
dbms_output.put_line('x = ' || x); | |
END LOOP; | |
dbms_output.put_line('Final do LOOP'); | |
END; | |
-- exemplo decrescente | |
BEGIN | |
dbms_output.put_line('Inicio do LOOP'); | |
FOR x IN REVERSE 1 .. 10 LOOP | |
dbms_output.put_line('x = ' || x); | |
END LOOP; | |
dbms_output.put_line('Final do LOOP'); | |
END; | |
-- Lab 04: - FOR | |
-- Quanto você terá na poupança aplicando R$ 50.00 por mês durante 3 anos? | |
-- rendimento 0.5% | |
-- Resposta: - FOR | |
DECLARE | |
vMensal number(8,2) := 50.00; | |
vRendimento number(6,3) := 1.005; | |
vSaldo number(10,2) := 0; | |
vMeses number := 36; | |
BEGIN | |
FOR vMes IN 1 .. vMeses LOOP | |
vSaldo := (vSaldo + vMensal) * vRendimento; | |
dbms_output.put_line(vMes || ' --> ' ||vSaldo); | |
END LOOP; | |
dbms_output.put_line('Meses: ' || vMeses); | |
dbms_output.put_line('Saldo R$ ' ||vSaldo); | |
END; | |
-- SQL dentro do PL/SQL | |
--- Dentro do Pl/SQL você usa do DML | |
--- o SELECT dentro do PL/SQL tem limitações | |
-- Ele não pode retornar mais do que 1 registro | |
-- Ele não pode retornar um grid de registros | |
DECLARE | |
vCidade varchar(50); | |
BEGIN | |
SELECT nm_cidade INTO vCidade FROM tb_cidades WHERE cd_cidade = 2; | |
dbms_output.put_line('Cidade : ' || vCidade); | |
END; | |
SELECT nm_cidade FROM tb_cidades; | |
-- Exemplo | |
-- Dado um código diga o aluno / a aluna realizou X inscricoes | |
DECLARE | |
vCodigo number := 1; | |
vNome varchar(50); | |
vSexo char(1); | |
vQtde number; | |
BEGIN | |
SELECT nm_aluno, tx_sexo INTO vNome, vSexo FROM tb_alunos WHERE cd_aluno = vCodigo; | |
IF vSexo = 'M' THEN | |
dbms_output.put_line('O aluno : ' || vNome); | |
ELSE | |
dbms_output.put_line('A aluna : ' || vNome); | |
END IF; | |
SELECT COUNT(*) INTO vQtde FROM tb_inscricoes WHERE cd_aluno = vCodigo; | |
dbms_output.put_line('Realizou ' || vQtde || ' inscricoes'); | |
END; | |
-- tabelas e dados da modelagem escola: | |
-- http://bit.ly/1yuoxif | |
-- Lab 05: SQL dentro do PL/SQL | |
-- Criar um PL/SQL onde você informará o código da turma: 4 | |
-- Mostrar as informações: | |
-- Nome do curso | |
-- Data de início | |
-- Data de fim | |
-- Capacidade | |
-- Quantidade de inscritos | |
-- Vagas na turma | |
RENAME TABLE <nome> TO <novo nome>; | |
DECLARE | |
vCodTurma number := 4; | |
vNomeCurso varchar(50); | |
vInicio date; | |
vFim date; | |
vCapacidade number; | |
vInscritos number; | |
BEGIN | |
SELECT dt_inicio, dt_fim, cd_curso, cd_sala, nm_curso, vl_capacidade | |
INTO vInicio, vFim, vCodCurso, vCodSala, vNomeCurso, vCapacidade | |
FROM tb_turmas | |
NATURAL JOIN tb_cursos | |
NATURAL JOIN tb_salas | |
WHERE cd_turma = vCodTurma; | |
SELECT COUNT(*) INTO vInscritos | |
FROM tb_inscricoes | |
WHERE cd_turma = vCodTurma; | |
dbms_output.put_line('Nome do curso: ' || vNomeCurso); | |
dbms_output.put_line('Data de inicio: ' || TO_CHAR(vInicio,'dd/mm/yyyy') ); | |
dbms_output.put_line('Data de fim: ' || TO_CHAR(vFim,'dd/mm/yyyy')); | |
dbms_output.put_line('Capacidade: ' || vCapacidade); | |
dbms_output.put_line('Inscritos: ' || vInscritos); | |
dbms_output.put_line('Vagas: ' || (vCapacidade - vInscritos)); | |
END; | |
-- HOMEWORKS 24/01/2015 | |
1. Imprima o quadrado de 8 * por 10 * usando for e while (no mesmo bloco). | |
********** | |
********** | |
********** | |
********** | |
********** | |
********** | |
********** | |
********** | |
-- resposta: | |
DECLARE | |
j NUMBER; | |
i NUMBER; | |
ch VARCHAR2(80) := ''; | |
BEGIN | |
FOR j IN 1.. 8 LOOP | |
i := 1; | |
WHILE i <= 10 LOOP | |
ch := ch || '*'; | |
i := i + 1; | |
END LOOP; | |
DBMS_OUTPUT.PUT_LINE(ch); | |
ch := ''; | |
END LOOP; | |
END; | |
2. Imprimir a tabuada do 5 | |
exemplo: | |
5 * 1 = 5 | |
5 * 2 = 10 | |
... | |
-- resposta: | |
BEGIN | |
FOR i IN 1 .. 10 LOOP | |
DBMS_OUTPUT.PUT_LINE(5 || ' * ' || i || ' = ' || 5 * i); | |
END LOOP; | |
END; | |
3. Imprimir a tabuada do x: | |
Exemplo: | |
x := 5 | |
Saída na tela: | |
1 * 5 = 5 | |
2 * 5 = 10 | |
3 * 5 = 15 | |
... | |
-- resposta: | |
DECLARE | |
x int := 7; | |
BEGIN | |
FOR i IN 1 .. 10 LOOP | |
END LOOP; | |
END; | |
4. Imprimir uma tabuada do 1 * 10 ao 10 * 10 | |
exemplo: | |
1 * 1 = 1 | |
1 * 2 = 2 | |
... | |
10 * 9 = 90 | |
10 * 10 = 100 | |
-- resposta: | |
DECLARE | |
j NUMBER; | |
i NUMBER; | |
BEGIN | |
FOR j IN 1 .. 10 LOOP | |
FOR i IN 1 .. 10 LOOP | |
DBMS_OUTPUT.PUT_LINE(j || ' * ' || i || ' = ' || j * i); | |
END LOOP; | |
DBMS_OUTPUT.PUT_LINE(''); | |
END LOOP; | |
END; | |
5. Anos bissexto entre os anos de 2000 e 2100 | |
(ano bissexto é quando é possível dividí-lo por 4 mas não por 100) | |
ou | |
(quando for possível dividí-lo por 400) | |
-- resposta: | |
BEGIN | |
FOR i IN 2000 .. 2100 LOOP | |
IF ( MOD(i, 4) = 0 AND MOD(i, 100) != 0 ) OR MOD(i, 400) = 0 THEN | |
dbms_output.put_line('Ano bissexto encontrado: ' || i); | |
ELSE | |
dbms_output.put_line('Não é um ano bissexto: ' || i); | |
END IF; | |
END LOOP; | |
END; | |
6. Reescreva o código abaixo eliminando os IF desnecessarios | |
(exercício apenas lógico) | |
... | |
IF salario < 1000 THEN | |
bonus := 2000; | |
ELSE | |
IF salario < 2000 THEN | |
bonus := 1500; | |
ELSE | |
IF salario < 4000 THEN | |
bonus := 1000; | |
ELSE | |
bonus := 500; | |
END IF; | |
END IF; | |
END IF; | |
-- resposta: | |
bonus := 500; | |
IF salario < 1000 THEN | |
bonus := 2000; | |
ELSIF salario > 1000 AND salario < 2000 THEN | |
bonus := 1500; | |
ELSIF salario > 2000 AND salario < 4000 THEN | |
bonus := 1000; | |
END IF; | |
IF salario < 1000 THEN | |
bonus := 2000; | |
ELSIF salario BETWEEN 1000 AND 2000 THEN | |
bonus := 1500; | |
ELSIF salario BETWEEN 2001 AND 4000 THEN | |
bonus := 1000; | |
END IF; | |
7. Qual será o valor de a? | |
DECLARE | |
a number := 0; | |
BEGIN | |
FOR x IN REVERSE 12 .. 1 LOOP | |
a := a + 1; | |
END LOOP; | |
dbms_output.put_line(a); | |
END; | |
-- resposta: | |
0 | |
-- OPEN YOUR MIND - Abram as suas mentes | |
-- CURSOR | |
--- Cursor é um recurso que disponibiliza capturar <n> linhas de um SELECT | |
-- 1. Declaração do CURSOR | |
-- 2. Abrir o CURSOR | |
-- 3. Iterar sobre o CURSOR | |
-- 4. Captura as linhas do CURSOR | |
-- 5. Fechar o CURSOR | |
DECLARE | |
CURSOR cAlunas IS | |
SELECT nm_aluno, dt_nascimento | |
FROM tb_alunos | |
WHERE tx_sexo = 'F'; | |
vNome varchar(50); | |
vData date; | |
BEGIN | |
OPEN cAlunas; | |
LOOP | |
FETCH cAlunas INTO vNome, vData; | |
EXIT WHEN cAlunas%notfound; | |
dbms_output.put_line('Nome: ' || vNome || | |
' - ' || TO_CHAR(vData, 'dd/mm/yyyy')); | |
END LOOP; | |
CLOSE cAlunas; | |
END; | |
-- Usando CURSOR com o WHILE | |
DECLARE | |
CURSOR cAlunas IS | |
SELECT nm_aluno, dt_nascimento | |
FROM tb_alunos | |
WHERE tx_sexo = 'F'; | |
vNome varchar(50); | |
vData date; | |
BEGIN | |
OPEN cAlunas; | |
FETCH cAlunas INTO vNome, vData; | |
WHILE (cAlunas%found) LOOP | |
dbms_output.put_line('Nome: ' || vNome || | |
' - ' || TO_CHAR(vData, 'dd/mm/yyyy')); | |
FETCH cAlunas INTO vNome, vData; | |
END LOOP; | |
CLOSE cAlunas; | |
END; | |
-- Usando CURSOR com o FOR | |
DECLARE | |
CURSOR cAlunas IS | |
SELECT nm_aluno, dt_nascimento | |
FROM tb_alunos | |
WHERE tx_sexo = 'F'; | |
BEGIN | |
FOR vReg IN cAlunas LOOP | |
dbms_output.put_line('Nome: ' || vReg.nm_aluno || | |
' - ' || TO_CHAR(vReg.dt_nascimento, 'dd/mm/yyyy')); | |
END LOOP; | |
END; | |
-- Usando CURSOR com o SUPER FOR | |
BEGIN | |
FOR vReg IN (SELECT nm_aluno, dt_nascimento FROM tb_alunos WHERE tx_sexo = 'F') LOOP | |
dbms_output.put_line('Nome: '||vReg.nm_aluno ||' - '||TO_CHAR(vReg.dt_nascimento, 'dd/mm/yyyy')); | |
END LOOP; | |
END; | |
-- Lab: 06 | |
Criar um resultado: | |
-- Categoria: <codigo> - <nome da categoria> | |
-- Curso: <nome do curso> - <carga horária> | |
Saída DBMS | |
01 - Banco de dados | |
Oracle - 24h | |
Mysql - 24h | |
02 - Programação | |
PHP - 32h | |
Java 32h | |
Python 8h | |
03 - Design | |
Photoshop - 32h | |
InDesign - 32h | |
-- Conteúdo do curso até agora | |
http://goo.gl/0S3fY3 | |
-- resposta | |
DECLARE | |
CURSOR cCategorias IS | |
SELECT cd_categoria, nm_categoria | |
FROM tb_categorias; | |
vCod number; | |
vCategoria varchar(50); | |
CURSOR cCursos IS | |
SELECT nm_curso, vl_ch | |
FROM tb_cursos | |
WHERE cd_categoria = vCod; | |
vCurso varchar(50); | |
vCH number; | |
BEGIN | |
OPEN cCategorias; | |
LOOP | |
FETCH cCategorias INTO vCod, vCategoria; | |
EXIT WHEN cCategorias%notfound; | |
dbms_output.put_line('Categoria: ' || vCod ||' - ' || vCategoria); | |
OPEN cCursos; | |
LOOP | |
FETCH cCursos INTO vCurso, vCH; | |
EXIT WHEN cCursos%notfound; | |
dbms_output.put_line(' - ' || vCurso || ' - ('||vCH||')' ); | |
END LOOP; | |
CLOSE cCursos; | |
END LOOP; | |
CLOSE cCategorias; | |
END; | |
-- Usando o SUPER FOR | |
BEGIN | |
FOR vRegCat IN (SELECT cd_categoria, nm_categoria FROM tb_categorias) LOOP | |
dbms_output.put_line('Categoria: ' || vRegCat.cd_categoria ||' - ' || vRegCat.nm_categoria); | |
FOR vRegCur IN (SELECT nm_curso, vl_ch FROM tb_cursos WHERE cd_categoria = vRegCat.cd_categoria) LOOP | |
dbms_output.put_line(' - ' || vRegCur.nm_curso || ' - ('||vRegCur.vl_ch||')' ); | |
END LOOP; | |
END LOOP; | |
END; | |
-- lab 7: | |
-- Alterar a tabela Alunos adicionando uma coluna chamada vl_salario | |
-- Setar o salário de 1000 reais para todos | |
ALTER TABLE tb_alunos ADD vl_salario NUMBER(14,5) DEFAULT 0; | |
UPDATE tb_alunos SET vl_salario = 1000; -- nuuuunca façam isso na vida real | |
-- monkey mode: | |
UPDATE tb_alunos SET vl_salario = vl_salario + 230; -- nuuuunca façam isso na vida real | |
-- Com cursor | |
-- Atualizar o salário de todos os alunos em 230 reais * cd_aluno | |
-- resposta | |
DECLARE | |
CURSOR cAlunos IS -- 1000 alunos 567 => salario 500 | |
SELECT * | |
FROM tb_alunos | |
FOR UPDATE OF vl_salario WAIT 60; | |
vValor number(14,2) := 230; | |
BEGIN | |
FOR vReg IN cAlunos LOOP | |
-- updated 567 => salario 1000 | |
UPDATE tb_alunos | |
SET vl_salario = vl_salario + (vValor * vReg.cd_aluno) | |
-- WHERE cd_aluno = vReg.cd_aluno; | |
WHERE CURRENT OF cAlunos; | |
END LOOP; | |
END; | |
-- salario 567 ? | |
SELECT * FROM tb_alunos; | |
FOR UPDATE; -- qualquer alteração em toda a tabela só ocorrerá de pois de liberado os registros | |
FOR UPDATE WAIT x; -- x = segundos, toda a tabela será liberada depois de x segundos | |
FOR UPDATE OF <coluna> WAIT x; -- x =segundos, a coluna será liberada depois de x segundos | |
-- Tratamento de erros, erros mais comuns | |
-- SELECT INTO que não retorne linhas | |
-- SELECT INTO que retorne 2 ou mais linhas | |
-- CASE sem DEFAULT | |
-- Abrir/Fechar o CURSOR mais de uma vez | |
-- Dividir um numero por 0 (zero) | |
-- Erros de violação de CONSTRAINTS (PRIMARY KEY, FOREIGN KEY, CHECK, UNIQUE) | |
DECLARE | |
x number := 100; | |
y number := 20; | |
total number(3); | |
BEGIN | |
total := x * y; | |
dbms_output.put_line('Total: ' || total); | |
EXCEPTION | |
WHEN zero_divide THEN | |
dbms_output.put_line('OOOOps, a divisão por zero non ecziste'); | |
WHEN value_error THEN | |
dbms_output.put_line('OOOOps, ocorreu um erro com as variáveis'); | |
WHEN others THEN | |
dbms_output.put_line('OOOOps, ocorreu algum erro'); | |
END; | |
-- http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/07_errs.htm | |
-- Criando tipos de exceptions | |
DECLARE | |
vIdade number := 15; | |
eAcesso_negado exception; | |
BEGIN | |
IF vIdade < 18 THEN | |
RAISE eAcesso_negado; | |
END IF; | |
EXCEPTION | |
WHEN eAcesso_negado THEN | |
dbms_output.put_line('Acesso negado'); | |
WHEN other THEN | |
dbms_output.put_line('Corram para as montanhas!'); | |
END; | |
-- QUIZ: | |
DECLARE | |
A exception; | |
B exception; | |
C exception; | |
BEGIN | |
BEGIN | |
BEGIN | |
BEGIN | |
raise A; | |
EXCEPTION | |
WHEN C THEN dbms_output.put_line('Error 1'); | |
END; | |
EXCEPTION | |
WHEN A OR B THEN dbms_output.put_line('Error 2'); | |
raise NO_DATA_FOUND; | |
END; | |
EXCEPTION | |
WHEN B OR C THEN dbms_output.put_line('Error 3'); | |
END; | |
EXCEPTION | |
WHEN OTHERS THEN dbms_output.put_line('Unknown Error'); | |
END; | |
-- Resposta | |
-- Error 2 | |
-- Unknown Error | |
-- FUNCOES | |
-- Função retorna um valor | |
-- Função pode ser utilizada dentro do DML e do DQL | |
-- Função é utilizada para criar programas auxiliares | |
-- ESCOPO | |
CREATE [OR REPLACE] FUNCTION <nome da função>([params]) | |
RETURN <tipo de dado> | |
AS | |
<variaveis> | |
BEGIN | |
<codigo> | |
END; | |
-- IMC - Índice de Massa Corporal | |
-- imc = peso / ( aultura * altura) | |
CREATE OR REPLACE FUNCTION fn_imc(pPeso number, pAltura number) | |
RETURN varchar | |
AS | |
imc number; | |
BEGIN | |
imc := pPeso / (pAltura * pAltura); | |
IF imc > 24 THEN | |
RETURN 'Você está acima do peso ideal'; | |
ELSE | |
RETURN 'Você está com o peso ideal'; | |
END IF; | |
END; | |
SELECT fn_imc(80, 1.90) FROM dual; | |
-- Lab 07 | |
-- Função para converter graus celsius para Fahrenheit | |
-- fn_fahrenheit(pCelsius number) | |
-- fórmula 'ºF = (ºC * 1.8) + 32' | |
CREATE OR REPLACE FUNCTION fn_fahrenheit(pCelsius number) | |
RETURN number | |
AS | |
BEGIN | |
RETURN (pCelsius * 1.8) + 32; | |
END; | |
SELECT fn_fahrenheit(44) FROM dual; | |
SELECT nm_sala, vl_capacidade, fn_fahrenheit(vl_capacidade) celsius | |
FROM tb_salas; | |
UPDATE tb_alunos SET vl_salario = fn_fahrenheit(vl_salario) | |
WHERE cd_aluno = 555; | |
-- Lab 08 - Criar uma função para calculo de comissão | |
-- Valor de vendas no mês | |
-- Tempo de empresa (meses) | |
SELECT fn_comissao(<valor>, <tempo de empresa>); | |
-- Regras de comissão: | |
-- Se o total de vendas: | |
-- for menor que R$ 1000.00, comissão 0.5% sobre as vendas | |
-- for menor que R$ 2500.00, comissão 0.75% sobre as vendas | |
-- for menor que R$ 5000.00, comissão 0.75% + R$ 250.00 de bônus sobre as vendas | |
-- for maior que R$ 5000.00, comissão 1% + R$ 350.00 de bônus sobre as vendas | |
-- Bônus extra | |
-- Se o vendedor: | |
-- tem menos que 1 ano de empresa: 0% sobre as vendas | |
-- tem menos que 2 anos de empresa: 0.20% sobre as vendas | |
-- tem menos que 5 anos de empresa: 0.40% sobre as vendas | |
-- tem mais que 5 anos de empresa: 0.60% sobre as vendas | |
SELECT fn_comissao(6000, 29) FROM dual; | |
CREATE OR REPLACE FUNCTION fn_comissao(pValor number, pTempo number) | |
RETURN number | |
AS | |
vComissaoValor number; | |
vComissaoTotal number; | |
BEGIN | |
CASE | |
WHEN pValor < 1000 THEN | |
vComissaoValor := pValor * 0.005; | |
WHEN pValor BETWEEN 1000 AND 2500 THEN | |
vComissaoValor := pValor * 0.0075; | |
WHEN pValor BETWEEN 2500 AND 5000 THEN | |
vComissaoValor := (pValor * 0.0075) + 250; | |
ELSE | |
vComissaoValor := (pValor * 0.01) + 350; | |
END CASE; | |
CASE | |
WHEN pTempo < 12 THEN | |
vComissaoTotal := vComissaoValor; | |
WHEN pTempo BETWEEN 12 AND 24 THEN | |
vComissaoTotal := vComissaoValor + (pValor * 0.002); | |
WHEN pTempo BETWEEN 24 AND 60 THEN | |
vComissaoTotal := vComissaoValor + (pValor * 0.004); | |
ELSE | |
vComissaoTotal := vComissaoValor + (pValor * 0.006); | |
END CASE; | |
RETURN vComissaoTotal; | |
END; | |
SELECT fn_comissao(6000, 29) FROM dual; | |
SELECT ((6000 * 0.01) + (6000 * 0.004)) + 350 FROM dual; | |
SELECT (6000 * (1/100) + 350)) * 1.004 FROM dual; | |
SELECT fn_comissao(6000, 29) FROM dual; | |
-- Procedures - Stored Procedures | |
- Procedure é utilizada para manipulação de dados | |
CREATE [OR REPLACE] PROCEDURE <nome> ([PARAM] [IN / OUT] <tipo>) | |
AS | |
<variaveis> | |
BEGIN | |
<codigo> | |
END; | |
-- Exemplo | |
-- qual a qtde de alunos de um sexo M ou F | |
sp_qtd_alunos('M'); | |
CREATE OR REPLACE PROCEDURE sp_qtd_alunos(pSexo IN char) | |
AS | |
vQtd OUT number; | |
BEGIN | |
SELECT COUNT(*) INTO pQtd | |
FROM tb_alunos | |
WHERE tx_sexo = pSexo; | |
RETURN vQtd; | |
END; | |
DECLARE | |
vQtd number; | |
BEGIN | |
dbms_output.put_line('ANTES: Foram encontrados '||vQtd||' alunos'); | |
sp_qtd_alunos('M', vQtd); | |
dbms_output.put_line('DEPOIS: Foram encontrados '||vQtd||' alunos'); | |
END; | |
-- Exemplo pratico | |
-- Procedure sp_add_sala(cod. sala, nome sala, capacidade) | |
-- Verificar se o código da sala já existe | |
-- Verificar se o nome da sala já existe | |
-- Verifica se a capacidade está entre 2 e 20 alunos | |
CREATE OR REPLACE | |
PROCEDURE sp_add_sala(pCodSala char, pNmSala varchar, pVlCapacidade number) | |
AS | |
eVlCapacidadeInvalida exception; | |
eSalaJaExiste exception; | |
vNomeSala tb_salas.nm_sala%type; | |
BEGIN | |
IF pVlCapacidade NOT BETWEEN 2 AND 20 THEN | |
RAISE eVlCapacidadeInvalida; | |
END IF; | |
BEGIN | |
SELECT nm_sala INTO vNomeSala FROM tb_salas WHERE nm_sala = pNmSala; | |
IF vNomeSala IS NOT NULL THEN | |
RAISE eSalaJaExiste; | |
END IF; | |
EXCEPTION | |
WHEN no_data_found THEN | |
null; | |
END; | |
INSERT INTO tb_salas(cd_sala, nm_sala, vl_capacidade) | |
VALUES (pCodSala, pNmSala, pVlCapacidade); | |
EXCEPTION | |
WHEN eVlCapacidadeInvalida THEN | |
dbms_output.put_line('Capacidade Invalida'); | |
WHEN eSalaJaExiste THEN | |
dbms_output.put_line('Sala ja existe'); | |
WHEN dup_val_on_index THEN | |
dbms_output.put_line('Código da sala ja existe'); | |
END; | |
BEGIN | |
sp_add_sala('S01','Sala 11', 20); | |
END; | |
SELECT * FROM tb_salas; | |
2013nosaes* | |
http://goo.gl/0S3fY3 - PL/SQL | |
http://bit.ly/1yuoxif - Oracle Essencial | |
-- Lab09 - | |
Montar uma procedure sp_add_turma | |
-- params: | |
cod. da turma | |
dt. inicio | |
qtde de aulas | |
periodo | |
nm do instrutor | |
nm curso | |
cod sala | |
-- Verificações: | |
Instrutor existe? | |
Curso existe? | |
Data de início é maior que a data atual? | |
O perído é válido (M, T ou N)? | |
O cod. turma já existe? -- dup_val_on_index | |
Sala existe? -- constraint_violation -- FK. -02291 | |
-- como bonus... utilize exceptions ao invés de | |
-- dbms_output.put_line nas verificações | |
-- Lab09 - RESPOSTA | |
-- Montar uma procedure sp_add_turma | |
CREATE OR REPLACE PROCEDURE sp_add_turma(pCod number, pInicio date, pAulas number, | |
pPeriodo char, pInstrutor varchar, pCurso varchar, pSala char) | |
AS | |
vCodInstrutor number; | |
vCodCurso number; | |
eInstrutor exception; | |
eCurso exception; | |
eInicio exception; | |
ePeriodo exception; | |
constraint_violation exception; | |
pragma exception_init(constraint_violation, -02291); | |
-- constraint_violation2 exception; | |
-- pragma exception_init(constraint_violation2, -022XX); | |
BEGIN | |
IF pInicio < SYSDATE THEN | |
RAISE eInicio; | |
END IF; | |
IF pPeriodo NOT IN ('M', 'T', 'N') THEN | |
RAISE ePeriodo; | |
END IF; | |
BEGIN | |
SELECT cd_instrutor INTO vCodInstrutor FROM tb_instrutores WHERE nm_instrutor = pInstrutor; | |
EXCEPTION | |
WHEN no_data_found THEN | |
RAISE eInstrutor; | |
END; | |
BEGIN | |
SELECT cd_curso INTO vCodCurso FROM tb_cursos WHERE nm_curso = pCurso; | |
EXCEPTION | |
WHEN no_data_found THEN | |
RAISE eCurso; | |
END; | |
INSERT INTO tb_turmas(cd_turma,dt_inicio,dt_fim,tx_periodo,cd_instrutor,cd_curso,cd_sala) | |
VALUES (pCod, pInicio, pInicio + pAulas - 1, pPeriodo, vCodInstrutor, vCodCurso, pSala); | |
EXCEPTION | |
WHEN eInstrutor THEN | |
dbms_output.put_line('O instrutor não existe'); | |
WHEN eCurso THEN | |
dbms_output.put_line('O curso não existe'); | |
WHEN eInicio THEN | |
dbms_output.put_line('Data de início menor que a data atual'); | |
WHEN ePeriodo THEN | |
dbms_output.put_line('Período inválido'); | |
WHEN dup_val_on_index THEN | |
dbms_output.put_line('Cod. Turma já existe'); | |
WHEN constraint_violation THEN | |
dbms_output.put_line('A sala não existe'); | |
END; | |
ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'; | |
BEGIN | |
sp_add_turma (7,'2015-10-10',8,'M','Pedro','PHP','S02'); | |
END; | |
SELECT * FROM tb_turmas; | |
SELECT SYSDATE FROM DUAL; | |
SELECT SYSDATE, SYSDATE + 9 FROM dual; | |
conn sys as sysdba; | |
senha: season | |
create database teste | |
user sys identified by season | |
user system identified by season | |
DEFAULT tablespace; | |
-- WOMEWORK | |
1. Escreva uma função em PL/SQL chamada TamanhoString, que receba um texto como parâmetro e retorne seu tamanho. | |
2. Escreva uma função em PL/SQL chamada ConverteParaMaiuscula, que receba um texto como parâmetro e retorne esse texto em | |
maiúsculo. | |
3. Criar uma procedure que deverá receber o código de um cliente e a partir deste dado imprimir o seu | |
nome, e seu e‐mail. Os dados deverão ser obtidos a partir de uma tabela chamada CLIENTE com as | |
seguintes colunas (COD_CLI,NOME_CLI,EMAIL_CLI). Exemplo: | |
CLIENTE | |
----------------------------------------------- | |
COD_CLI NOME_CLI EMAIL_CLI | |
----------------------------------------------- | |
10 BEATRIZ BERNARDES [email protected] | |
----------------------------------------------- | |
CREATE TABLE CLIENTE ( | |
COD_CLI NUMBER(4) PRIMARY KEY, | |
NOME_CLI VARCHAR2(30), | |
EMAIL_CLI VARCHAR2(30)); | |
INSERT INTO CLIENTE VALUES (10,'BEATRIZ BERNARDES','[email protected]'); | |
4. Criar uma procedure que receberá um RA, um NOME e quatro notas conforme a sequência: | |
(RA,NOME,A1,A2,A3,A4). A partir destes valores deverá efetuar o cálculo da média somando o maior valor | |
entre A1 e A2 às notas A3 e A4 e dividindo o valor obtido por três (achando a média). Se a média for menor | |
que 6 (seis) o aluno estará REPROVADO e se a média for igual ou superior a 6 (seis) o aluno estará | |
APROVADO. A procedure deverá inserir os valores acima numa tabela denominada ALUNO com as | |
seguintes colunas RA,NOME,A1,A2,A3,A4,MEDIA,RESULTADO. Exemplo: | |
ALUNO | |
-------------------------------------------------------- | |
RA NOME A1 A2 A3 A4 MEDIA RESULTADO | |
-------------------------------------------------------- | |
123 ANTONIO ALVES 6.5 3.5 9.5 5.0 7.0 APROVADO | |
-------------------------------------------------------- | |
CREATE TABLE ALUNO ( | |
RA NUMBER(9), | |
NOME VARCHAR2(30), | |
NOTA1 NUMBER(3,1), | |
NOTA2 NUMBER(3,1), | |
NOTA3 NUMBER(3,1), | |
NOTA4 NUMBER(3,1), | |
MEDIA NUMBER(3,1), | |
RESULTADO VARCHAR2(15)); | |
5. Uma empresa oferece um bônus a seus funcionários com base no lucro liquido (tabela LUCRO) obtido | |
durante o ano e no valor do salário do funcionário (tabela SALARIO). O bônus é calculado conforme a | |
seguinte formula: BONUS = LUCRO * 0.01 + SALARIO * 0.05. Crie uma procedure que receba o ano (tabela | |
LUCRO) e número de matricula do funcionário e devolva (imprima) o valor do seu respectivo bônus. | |
LUCRO | |
----------------- | |
ANO VALOR | |
----------------- | |
2007 1200000 | |
2008 1500000 | |
2009 1400000 | |
----------------- | |
SALARIO | |
----------------- | |
MATRICULA VALOR | |
----------------- | |
1001 2500 | |
1002 3200 | |
----------------- | |
CREATE TABLE LUCRO ( | |
ANO NUMBER(4), | |
VALOR NUMBER(9,2)); | |
CREATE TABLE SALARIO ( | |
MATRICULA NUMBER(4), | |
VALOR NUMBER(7,2)); | |
INSERT INTO LUCRO VALUES (2007,1200000); | |
INSERT INTO LUCRO VALUES (2008,1500000); | |
INSERT INTO LUCRO VALUES (2009,1400000); | |
INSERT INTO SALARIO VALUES (1001,2500); | |
INSERT INTO SALARIO VALUES (1002,3200); | |
-- WOMEWORK - Respostas | |
1. Escreva uma função em PL/SQL chamada TamanhoString, que receba um texto como parâmetro e retorne seu tamanho. | |
CREATE OR REPLACE FUNCTION TamanhoString(pString varchar) | |
RETURN number | |
AS | |
vTamanho number; | |
BEGIN | |
vTamanho := LENGTH(pString); | |
RETURN vTamanho; | |
END; | |
SELECT TamanhoString('Teste') FROM dual; | |
2. Escreva uma função em PL/SQL chamada ConverteParaMaiuscula, que receba um texto como parâmetro e retorne esse texto em | |
maiúsculo. | |
CREATE OR REPLACE FUNCTION ConverteParaMaiuscula(pTexto varchar) | |
RETURN varchar | |
AS | |
vTexto varchar(50); | |
BEGIN | |
vTexto := UPPER(pTexto); | |
RETURN vTexto; | |
END; | |
SELECT ConverteParaMaiuscula('Edgar') FROM dual; | |
3. Criar uma procedure que deverá receber o código de um cliente e a partir deste dado imprimir o seu | |
nome, e seu e‐mail. Os dados deverão ser obtidos a partir de uma tabela chamada CLIENTE com as | |
seguintes colunas (COD_CLI,NOME_CLI,EMAIL_CLI). | |
CREATE OR REPLACE PROCEDURE MOSTRA_CLIENTE(pCod NUMBER) | |
IS | |
vCliente CLIENTE%rowtype; | |
BEGIN | |
SELECT * INTO vCliente FROM CLIENTE WHERE COD_CLI = pCod; | |
DBMS_OUTPUT.PUT_LINE(vCliente.NOME_CLI || ' - ' || vCliente.EMAIL_CLI); | |
END MOSTRA_CLIENTE; | |
BEGIN | |
MOSTRA_CLIENTE(10); | |
END; | |
SELECT * FROM CLIENTE; | |
4. Criar uma procedure que receberá um RA, um NOME e quatro notas conforme a sequência: | |
(RA,NOME,A1,A2,A3,A4). | |
CREATE OR REPLACE PROCEDURE CALCULA_MEDIA( | |
pRA NUMBER, | |
pNome VARCHAR, | |
pN1 NUMBER, | |
pN2 NUMBER, | |
pN3 NUMBER, | |
pN4 NUMBER) | |
AS | |
vMaior NUMBER(3,1); | |
vMedia NUMBER(3,1); | |
vResultado VARCHAR(15); | |
BEGIN | |
IF pN1 > pN2 THEN | |
vMaior := pN1; | |
ELSE | |
vMaior := pN2; | |
END IF; | |
vMedia := (vMaior + pN3 + pN4) / 3; | |
IF vMedia < 6 THEN | |
vResultado := 'REPROVADO'; | |
ELSE | |
vResultado := 'APROVADO'; | |
END IF; | |
INSERT INTO ALUNO VALUES(pRA, pNome, pN1, pN2, pN3, pN4, vMedia, vResultado); | |
END; | |
SELECT * FROM ALUNO; | |
123 ANTONIO ALVES 6.5 3.5 9.5 5.0 7.0 APROVADO | |
BEGIN | |
CALCULA_MEDIA(123, 'ANTONIO ALVES',6.5, 3.5, 9.5,5.0); | |
END; | |
5. Uma empresa oferece um bônus a seus funcionários com base no lucro liquido (tabela LUCRO) obtido | |
durante o ano e | |
CREATE OR REPLACE PROCEDURE CALCULA_BONUS( | |
pAno LUCRO.ANO%TYPE, | |
pMatricula SALARIO.MATRICULA%TYPE) | |
AS | |
vLucro LUCRO.VALOR%TYPE; | |
vSalario SALARIO.VALOR%TYPE; | |
vBonus NUMBER(7,2); | |
BEGIN | |
SELECT VALOR INTO vLucro FROM LUCRO | |
WHERE ANO = pAno; | |
SELECT VALOR INTO vSalario FROM SALARIO | |
WHERE MATRICULA = pMatricula; | |
vBonus := (vLucro * 0.01) + (vSalario * 0.05); | |
dbms_output.put_line('Valor do Bonus: ' || vBonus); | |
END; | |
SELECT VALOR FROM LUCRO WHERE ANO = 2007; | |
SELECT VALOR FROM SALARIO WHERE MATRICULA = 1001; | |
BEGIN | |
CALCULA_BONUS(2007,1002); | |
END; | |
-- Criando exceptions para códigos de erro | |
DECLARE | |
eConstraintException exception; | |
pragma exception_init(eConstraintException, -02291); | |
BEGIN | |
INSERT INTO tb_cursos (cd_curso, nm_curso, vl_ch, cd_categoria) | |
VALUES(20,'Curso fake', '40', 89988888); | |
EXCEPTION | |
WHEN eConstraintException THEN | |
dbms_output.put_line('A categoria não existe'); | |
dbms_output.put_line('Usuario: ' || user); | |
dbms_output.put_line('Data: ' || TO_CHAR(sysdate, 'dd/mm/yyyy')); | |
dbms_output.put_line('Erro: ' || sqlcode); | |
dbms_output.put_line('Msg: ' || sqlerrm); | |
WHEN value_error THEN | |
dbms_output.put_line('Erro' || TO_CHAR(SQLERRM(-01438))); | |
dbms_output.put_line('Erro' || TO_CHAR(SQLERRM(-06512))); | |
END; | |
BEGIN | |
dbms_output.put_line('Erro' || TO_CHAR(SQLERRM(-01438))); | |
END; | |
-- Packages | |
-- é um grupo de n procedures, n funcoes, n variaveis, n tipos | |
-- facilita a distribuição e controle de versão | |
-- Funcionalidade nova: Permite variaveis instanciadas na sessao | |
-- Criada em dois passos | |
-- 1o - Declação - cabeçalho - header | |
-- 2o - Programação - corpo - body | |
Package pkg_calculadora | |
procedure soma | |
procedure subtrai | |
function saldo | |
-- ESCOPO HEADER | |
CREATE OR REPLACE PACKAGE <nome> | |
AS | |
END; | |
-- ESCOPO BODY | |
CREATE OR REPLACE PACKAGE BODY <nome> | |
AS | |
END; | |
CREATE OR REPLACE PACKAGE pkg_calculadora | |
AS | |
vTotal number(14, 2) := 0; --> variavel da sessao | |
PROCEDURE soma(x number); | |
PROCEDURE subtrai(x number); | |
FUNCTION saldo RETURN NUMBER; | |
END; | |
CREATE OR REPLACE PACKAGE BODY pkg_calculadora | |
AS | |
PROCEDURE soma(x number) | |
AS | |
BEGIN | |
vTotal := vTotal + x; | |
END; | |
PROCEDURE subtrai(x number) | |
AS | |
BEGIN | |
vTotal := vTotal - x; | |
END; | |
FUNCTION saldo RETURN NUMBER | |
AS | |
BEGIN | |
RETURN vTotal; | |
END; | |
END; | |
-- usando o package | |
-- saldo? | |
SELECT pkg_calculadora.saldo FROM tb_alunos; | |
-- somar ? | |
BEGIN | |
pkg_calculadora.soma(100); | |
END; | |
-- saldo? | |
SELECT pkg_calculadora.saldo FROM dual; -- 100 | |
-- subtrair ? | |
BEGIN | |
pkg_calculadora.subtrai(30); | |
END; | |
-- saldo? | |
SELECT pkg_calculadora.saldo FROM dual; -- 70 | |
-- Listas | |
-- Vetores / Array | |
-- Tabelas indexadas | |
-- Tabelas aninhadas | |
-- vArray | |
-- PHP | |
$array = array(1 => 'Taubate'); | |
-- ESCOPO Tabela Indexada | |
TYPE <nome da lista> IS TABLE OF <tipo(tamanho)> INDEX BY BINARY_INTEGER; | |
TYPE <nome da lista> IS TABLE OF tb_alunos; | |
CREATE OR REPLACE TYPE customer IS TABLE OF customer; | |
DECLARE | |
TYPE listaCidades IS TABLE OF VARCHAR(50) INDEX BY BINARY_INTEGER; | |
TYPE listaEstados IS TABLE OF customer%rowtype INDEX BY BINARY_INTEGER; | |
vCidades listaCidades; | |
vEstados listaEstados; | |
BEGIN | |
vCidades(1) := 'São Paulo'; | |
vCidades(2) := 'Osasco'; | |
vCidades(3) := 'SJCampos'; | |
vCidades(800) := 'Taubaté'; | |
vCidades(-5) := 'Caçapava'; | |
vCidades(-5) := 'Jacareí'; | |
dbms_output.put_line('Quantidade de cidades: ' || vCidades.count); | |
dbms_output.put_line('Cidade escolhida: ' || vCidades(-5)); | |
dbms_output.put_line(vEstados(0).full_name.first_name); | |
END; | |
SELECT c.full_name.first_name FROM customer c; | |
DECLARE | |
type listaSalas IS TABLE OF tb_salas%rowtype INDEX BY BINARY_INTEGER; | |
vSalas listaSalas; | |
BEGIN | |
vSalas(1).cd_sala := 'S08'; | |
vSalas(1).nm_sala := 'Sala 08'; | |
vSalas(1).vl_capacidade := 90; | |
vSalas(2).cd_sala := 'S09'; | |
dbms_output.put_line(vSalas(1).cd_sala); | |
dbms_output.put_line(vSalas(2).cd_sala); | |
END; | |
-- Tabelas aninhadas | |
-- indice sequencial, iniciando em 1 | |
-- necessita ser inicializada | |
DECLARE | |
TYPE listaNumeros IS TABLE OF NUMBER; | |
vMegaSena listaNumeros; | |
BEGIN | |
vMegaSena := listaNumeros(50, 19, 30, 40, 29, 33); | |
vMegaSena(5) := 7; | |
--vMegaSena.extend(10, 5); | |
-- vMegaSena := listaNumeros(0); | |
vMegaSena.extend(1, 1); | |
vMegaSena(7) := 22; | |
dbms_output.put_line('Quantidade: ' || vMegaSena.count); | |
FOR x IN 1 .. vMegaSena.count LOOP | |
dbms_output.put_line('Número: ' || x || ' : ' || vMegaSena(x)); | |
END LOOP; | |
END; | |
-- vArray | |
-- Tem que ser instanciado | |
-- O indice começa com zero | |
-- pode determinar o limite maximo para o array | |
DECLARE | |
TYPE listaString IS VARRAY(5) OF VARCHAR(50); | |
vCidades listaString := listaString(); | |
BEGIN | |
vCidades.extend; | |
vCidades(1) := 'Sao Paulo'; | |
vCidades.extend; | |
vCidades(2) := 'Jacarei'; | |
dbms_output.put_line('Cidade: ' || vCidades.count); | |
END; | |
CREATE OR REPLACE TYPE ListaTelefone AS VARRAY(10) OF VARCHAR(20); | |
ALTER TABLE tb_alunos ADD nr_telefone ListaTelefone; | |
UPDATE tb_alunos | |
SET nr_telefone = ListaTelefone('11 3434-5534','(12) 98844-3434','13 6346-5553') | |
WHERE cd_aluno = 1; | |
DECLARE | |
vNomeAluno varchar(50); | |
vTelefone ListaTelefone; | |
BEGIN | |
SELECT nm_aluno, nr_telefone INTO vNomeAluno, vTelefone | |
FROM tb_alunos | |
WHERE cd_aluno = 1; | |
dbms_output.put_line('Nome do aluno: ' || vNomeAluno); | |
dbms_output.put_line('Quantidade: ' || vTelefone.count || ' telefones'); | |
FOR x IN 1 .. vTelefone.count LOOP | |
dbms_output.put_line(' ' || vTelefone(x)); | |
END LOOP; | |
END; | |
-- TRIGGERS | |
-- Gatilhos | |
-- Blocos que são executados automaticamente conforme eventos do BD | |
-- Triggers do SGBD | |
-- LOGON, LOGOFF, STARTUP, DROP, CREATE, ALTER | |
-- Triggers DML | |
-- INSERT, UPDATE, DELETE | |
-- Triggers Instead Of | |
-- VIEWS | |
-- ESCOPO TRIGGER | |
CREATE OR REPLACE TRIGGER <nome> | |
(<BEFORE OR AFTER OR INSTEAD-OF) <evento> [ON <local>] | |
BEGIN | |
END; | |
Triggers do SGBD | |
AFTER STARTUP | |
AFTER LOGON | |
BEFORE SHUTDOWN | |
BEFORE LOGOFF | |
BEFORE STARTUP --?? | |
AFTER SHUTDOWN --?? | |
TRIGGERS DML | |
:NEW.nm_sala | |
:OLD.nm_sala | |
Triggers DML | |
INSERT UPDATE DELETE | |
:NEW SIM SIM NÃO | |
:OLD NÃO SIM SIM | |
-- Exemplo trigger SGBD | |
-- Evento: 'Usuário logou no banco de dados' | |
-- Evento: 'Usuário saiu do banco de dados' | |
CREATE TABLE tb_log_acessos( | |
dt_acesso DATE DEFAULT SYSDATE, | |
tx_usuario varchar(30), | |
tx_acao varchar(50) | |
); | |
CREATE OR REPLACE TRIGGER tr_usuario_logon | |
AFTER LOGON ON DATABASE | |
BEGIN | |
INSERT INTO aluno.tb_log_acessos(tx_usuario,tx_acao) | |
VALUES (USER, 'usuario logou no banco de dados'); | |
END; | |
CREATE OR REPLACE TRIGGER tr_usuario_logoff | |
BEFORE LOGOFF ON DATABASE | |
BEGIN | |
INSERT INTO aluno.tb_log_acessos(tx_usuario,tx_acao) | |
VALUES (USER, 'usuario saiu do banco de dados'); | |
END; | |
ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'; | |
SELECT * FROM tb_log_acessos; | |
-- Exemplo TRIGGER DML | |
-- produtos | |
-- movimentacao | |
CREATE TABLE tb_produtos( | |
cd_produto number, | |
nm_produto varchar(50), | |
qtd_estoque number | |
); | |
-- cd_operacao === C (compra) ou V (venda) | |
CREATE TABLE tb_movimentacao( | |
cd_operacao char, | |
cd_produto number, | |
qtd_movimento number | |
); | |
INSERT INTO tb_produtos VALUES(1, 'Notebook', 20); | |
INSERT INTO tb_produtos VALUES(2, 'Mouse', 50); | |
INSERT INTO tb_produtos VALUES(3, 'Monitor', 10); | |
INSERT INTO tb_movimentacao VALUES ('C', 1, 10); | |
INSERT INTO tb_movimentacao VALUES ('V', 2, 5); | |
INSERT INTO tb_movimentacao VALUES ('C', 1, 100); | |
INSERT INTO tb_movimentacao VALUES ('V', 1, 50); | |
DELETE FROM tb_movimentacao | |
WHERE cd_operacao = 'V' | |
AND cd_produto = 1 | |
AND qtd_movimento = 50; | |
SELECT * FROM tb_produtos; | |
SELECT * FROM tb_movimentacao; | |
UPDATE tb_movimentacao SET qtd_movimento = 15 | |
WHERE cd_operacao = 'V' AND cd_produto = 2; | |
-- BEFORE UPDATE (por instrução) | |
-- BEFORE UPDATE EACH ROW (por registro) | |
INSERT C -> Adicionar a (+ qtd no estoque + estoque) | |
INSERT V -> Remover a (- qtd no estoque + estoque) | |
UPDATE C -> Adicionar a qtd no estoque (+ qtd no estoque + estoque) | |
UPDATE V -> Remover a qtd no estoque (- qtd no estoque + estoque) | |
DELETE C -> Remover a qtd no estoque | |
DELETE V -> Adicionar a qtd no estoque | |
Triggers DML | |
INSERT UPDATE DELETE | |
:NEW SIM SIM NÃO | |
:OLD NÃO SIM SIM | |
CREATE OR REPLACE TRIGGER tr_movimentacao | |
AFTER INSERT OR UPDATE OR DELETE ON tb_movimentacao | |
FOR EACH ROW | |
BEGIN | |
IF(:NEW.cd_operacao = 'C') THEN | |
UPDATE tb_produtos SET qtd_estoque = qtd_estoque + :NEW.qtd_movimento | |
WHERE cd_produto = :NEW.cd_produto; | |
END IF; | |
IF (:NEW.cd_operacao = 'V') THEN | |
UPDATE tb_produtos SET qtd_estoque = qtd_estoque - :NEW.qtd_movimento | |
WHERE cd_produto = :NEW.cd_produto; | |
END IF; | |
IF (:OLD.cd_operacao = 'C') THEN | |
UPDATE tb_produtos SET qtd_estoque = qtd_estoque - :OLD.qtd_movimento | |
WHERE cd_produto = :OLD.cd_produto; | |
END IF; | |
IF (:OLD.cd_operacao = 'V') THEN | |
UPDATE tb_produtos SET qtd_estoque = qtd_estoque + :OLD.qtd_movimento | |
WHERE cd_produto = :OLD.cd_produto; | |
END IF; | |
END; | |
20 + 10 | |
50 - 15 | |
DROP TRIGGER tr_movimentacao; | |
TRUNCATE TABLE tb_movimentacao; | |
SELECT * FROM tb_produtos; | |
SELECT * FROM tb_movimentacao; | |
20 notebooks (cod 1) | |
C + 10 => 30 notebooks | |
C + 5 => | |
NEW C | |
estoque = (30 + 5) | |
OLD C | |
estoque = (35 - 10) | |
31 /01 -> 50 | |
+ 5 | |
- 5 | |
+ 20 | |
+ 40 | |
- 30 | |
28/02 -> 35 | |
- 5 | |
+ 30 | |
- 80 | |
+ 120 | |
now -> (35 - 5 + 30 - 80 + 120) | |
-- Exemplo de validaçõa com trigger | |
-- uma restrição para a atualização de salário | |
-- o salário novo TEM que ser maior que o atual | |
CREATE OR REPLACE TRIGGER valida_salario | |
BEFORE UPDATE OF VALOR ON SALARIO | |
FOR EACH ROW | |
WHEN (NEW.VALOR < OLD.VALOR) | |
BEGIN | |
RAISE_APPLICATION_ERROR(-20508, 'O salário não pode ser reduzido'); | |
END; | |
SELECT * FROM SALARIO; | |
UPDATE SALARIO SET VALOR = 2000 WHERE MATRICUlA = 1001; | |
http://goo.gl/0S3fY3 | |
-- Lab 10 | |
-- Criar uma trigger para impedir que o salario seja reajustado acima | |
-- de 20% | |
(valor novo - valor atual) > valor atual * 0.20 | |
valor novo > valor atual * 1.20 | |
-- lab 10 - resposta | |
CREATE OR REPLACE TRIGGER valida_aumento | |
BEFORE UPDATE OF VALOR ON SALARIO | |
FOR EACH ROW | |
BEGIN | |
IF (:NEW.VALOR - :OLD.VALOR) > :OLD.VALOR * 0.20 THEN | |
RAISE_APPLICATION_ERROR(-20512, 'O aumento não pode ser maior do que 20%'); | |
END IF; | |
END; | |
CREATE OR REPLACE TRIGGER valida_aumento | |
BEFORE UPDATE OF VALOR ON SALARIO | |
FOR EACH ROW | |
BEGIN | |
IF :NEW.VALOR > :OLD.VALOR * 1.20 THEN | |
RAISE_APPLICATION_ERROR(-20512, 'O aumento não pode ser maior do que 20%'); | |
END IF; | |
END; | |
CREATE OR REPLACE TRIGGER valida_aumento | |
BEFORE UPDATE OF VALOR ON SALARIO | |
FOR EACH ROW | |
WHEN (NEW.VALOR > OLD.VALOR * 1.2) | |
BEGIN | |
RAISE_APPLICATION_ERROR(-20512, 'O aumento não pode ser maior do que 20%'); | |
END; | |
UPDATE SALARIO SET VALOR = 6000 WHERE MATRICULA = 1001; | |
-- TRIGGERS INSTEAD-OF | |
-- as views simples permitem INSERT, UPDATE e DELETE | |
-- as views complexas não permitem INSERT, UPDATE e DELETE | |
-- o que são as views complexas | |
-- JOINS | |
-- GROUP BY | |
-- UNION | |
-- Subqueries | |
-- view simples | |
CREATE OR REPLACE VIEW vw_teste | |
AS | |
SELECT nm_aluno AS NOME_DO_ALUNO FROM tb_alunos; | |
-- views complexas | |
CREATE OR REPLACE VIEW vw_teste | |
AS | |
SELECT * FROM tb_alunos | |
JOIN | |
GROUP BY; | |
-- Soluçao para views complexas | |
-- Criar um TRIGGER INSTEAD-OF que irá tratar o evento escolhido | |
CREATE OR REPLACE VIEW ALUNO.vw_movimentacao | |
AS | |
SELECT | |
cd_operacao, | |
DECODE(cd_operacao, 'C', 'COMPRA', 'V', 'VENDA') as tx_operacao, | |
nm_produto, | |
qtd_movimento | |
FROM ALUNO.tb_movimentacao M | |
JOIN ALUNO.tb_produtos P ON (M.cd_produto = P.cd_produto);-- AND qtd_movimento > 40; | |
SELECT * FROM vw_movimentacao; | |
DELETE FROM vw_movimentacao WHERE nm_produto = 'Mouse'; | |
CREATE VIEW ALUNO.vw_total AS | |
SELECT | |
DECODE(cd_operacao, 'C', 'COMPRA', 'V', 'VENDA') AS tx_operacao, | |
SUM(qtd_movimento) AS total | |
FROM ALUNO.tb_movimentacao | |
GROUP BY DECODE(cd_operacao, 'C', 'COMPRA', 'V', 'VENDA'); | |
SELECT * FROM vw_total; | |
SELECT * FROM tb_movimentacao; | |
DELETE FROM vw_total WHERE tx_operacao = 'VENDA'; | |
CREATE OR REPLACE TRIGGER tr_vw_total | |
INSTEAD OF DELETE ON vw_total | |
FOR EACH ROW | |
BEGIN | |
IF (:OLD.tx_operacao = 'COMPRA') THEN | |
DELETE FROM tb_movimentacao | |
WHERE cd_operacao = 'C'; | |
ELSIF (:OLD.tx_operacao = 'VENDA') THEN | |
DELETE FROM tb_movimentacao | |
WHERE cd_operacao = 'V'; | |
END IF; | |
END; | |
UPDATE SALARIO SET VALOR = 5000 WHERE MATRICUlA = 1001; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment