Arquivos de Categoria: PL/SQL

Bando de Dados II – Aula 15A

Simulado para a prova de Banco de dados II, podendo ser baixado no Github, através do seguinte endereço:

https://github.com/rodrigoksaito/anchieta

 

Anúncios

Banco de Dados II – Aula 13

PERMISSÃO PARA MODO DEBUG

ScreenHunter_114 May. 06 23.47

EXECUÇÃO DA PROCEDURE

ScreenHunter_115 May. 06 23.48

PASSOS PARA FAZER O DEBUG

ScreenHunter_116 May. 07 00.23

EXEMPLO DE CÓDIGO

CREATE OR REPLACE PROCEDURE SP_TESTE_DEBUG
  (p_employee_id_inicial IN EMPLOYEES.EMPLOYEE_ID%TYPE,
   p_employee_id_final   IN EMPLOYEES.EMPLOYEE_ID%TYPE)
IS
  v_employee_id EMPLOYEES.EMPLOYEE_ID%TYPE;
  v_last_name   EMPLOYEES.LAST_NAME%TYPE;
  v_hire_date   EMPLOYEES.HIRE_DATE%TYPE;
  v_contador NUMBER;
  
  CURSOR cur_ret_employees is
    SELECT EMPLOYEE_ID, FIRST_NAME, HIRE_DATE
    FROM EMPLOYEES
    WHERE EMPLOYEE_ID BETWEEN p_employee_id_inicial AND p_employee_id_final;
BEGIN
  v_contador := 0;
  
  FOR r_employees IN cur_ret_employees LOOP
    FETCH cur_ret_employees
    INTO v_employee_id, v_last_name, v_hire_date;
    EXIT WHEN cur_ret_employees%NOTFOUND;
    
    v_contador := v_contador +1;
    
    DBMS_OUTPUT.PUT_LINE('Record    : '|| v_contador);
    DBMS_OUTPUT.PUT_LINE('EmployeeId: '||   v_employee_id);
    DBMS_OUTPUT.PUT_LINE('Last Name : ' ||   v_last_name);
    DBMS_OUTPUT.PUT_LINE('Hire Date : ' ||   v_hire_date);
    DBMS_OUTPUT.PUT_LINE('');
  END LOOP;
  EXCEPTION WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error was detected');
END;
/

TESTE DE DEBUG

  • Não crie bloco anônimo para fazer o teste do debug no código;
  • Nos parâmetros, coloque intervalos pequenos somente para ver o resultado;

TRIGGERS (GATILHOS)

  • Trigger é um bloco PL/SQL que é armazenado no banco de dados e executado em resposta de um específico evento;
  • O banco de dados Oracle executa um trigger automaticamente quando é especificada uma ocorrência de uma condição;
  • Uma trigger pode ser definida em uma tabela, view, schema (dono do schema), ou banco de dados (para todos os usuários)Untitled

TIPOS DE EVENTOS DAS TRIGGERS

  • Podemos escrever triggers que disparam em uma das operações que ocorre no banco de dados:
    • DML (insert, update, delete)
    • DDL (create, alter, drop)
    • Operações no banco como SERVERERROR, LOGON, LOGOFF, STARTUP ou SHUTDOWN;

CENÁRIOS DE APLICAÇÕES PARA IMPLEMENTAÇÃO

  • Podemos utilizar triggers em:
    • Segurança
    • Auditoria
    • Integridade de Dados
    • Integridade Referencial
    • Replicação de dados
    • Dados derivados de cálculos
    • Eventos de Logging

DISPONIBILIDADE DOS TIPOS DE TRIGGERS

  • Em DML simples
    • BEFORE
    • AFTER
    • INSTEAD OF

TIPOS DE EVENTOS DA TRIGGER E CORPO

  • Um tipo de evento da trigger determina como as cláusulas da declaração DML irá executar a trigger. As possibilidade são:
    • INSERT
    • UPDATE [OF COLUMN]
    • DELETE
  • O corpo determina a ação é chamada e é um bloco PL/SQL ou a chamada de uma procedure;

CRIANDO TRIGGER DML

ScreenHunter_117 May. 07 01.00

ESPECIFICANDO O TEMPO DE EXECUÇÃO

  • Voce pode especificar o tempo que a trigger irá ser executada em uma das declarações:
    • BEFORE: Executa o corpo da trigger antes do acionamento do evento DML na tabela;
    • AFTER: Executa o corpo da trigger depois do acionamento do evento DML na tabela;
    • INSTEAD OF: Executa o corpo da trigger ao invés do evento disparado (geralmente um comando DML);

SEQUENCIA DE DISPARO DAS TRIGGERS: MANIPULAÇÃO SIMPLES DE LINHA

  • A sequencia de disparo de uma trigger em uma tabela quando um linha é manipulada:

Untitled2

SEQUENCIA DE DISPARO DAS TRIGGERS: MANIPULAÇÃO DE VÁRIAS LINHAS

  • A sequencia de disparo de uma trigger em uma tabela quando são manipuladas várias linhas:

Untitled3

EXEMPLO DA TRIGGER SECURE_EMP

Untitled4

TESTANDO A TRIGGER SECURE_EMP

Untitled5

USANDO PREDICADOS CONDICIONAIS

CREATE OR REPLACE TRIGGER secure_emp BEFORE
  INSERT OR UPDATE OR DELETE ON employees
BEGIN
  IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
     (TO_CHAR(SYSDATE,'HH24') NOT BETWEEN '08' AND '18') THEN
    IF DELETING THEN RAISE_APPLICATION_ERROR(
       -20502,'Voce pode deletar empregados durante o horario comercial.');
    ELSIF INSERTING THEN RAISE_APPLICATION_ERROR (
       -20500,'Voce pode inserir empregados durante o horario comercial.');
    ELSIF UPDATING ('SALARY') THEN RAISE_APPLICATION_ERROR (
       -20503,'Voce pode atualizar o salary em horario comercial');
    ELSE RAISE_APPLICATION_ERROR(
       -20504,'Voce pode atualizar a tabela empregados durante o horario comercial');
    END IF;
  END IF;
END;

desc employees

insert into employees (EMPLOYEE_ID, LAST_NAME, EMAIL, HIRE_DATE, JOB_ID)
VALUES (207,'TESTE','TESTE',TO_DATE('05/05/2017','MM/DD/YYYY'),'HR_REP')

CRIANDO TRIGGER DE DML DE LINHA

–EXEMPLO 2

CREATE OR REPLACE TRIGGER SALARIO_RESTRITO
  BEFORE INSERT OR UPDATE OF SALARY ON EMPLOYEES
  FOR EACH ROW
BEGIN
  IF NOT (:NEW.job_id IN ('AD_PRES','AD_VP'))
    AND :NEW.salary > 15000 THEN
      RAISE_APPLICATION_ERROR (-20202,
        'Empregado não pode ganhar mais que $15000.');
  END IF;
END;

--teste da chamada
UPDATE employees
SET salary = 15500
WHERE last_name = 'Russell';

USANDO QUALIFICADORES OLD E NEW

  • Quando uma linha é atingida, o motor do run-time PL/SQL cria e popula duas estruturas de dados:
  • OLD: armazena os valores originais do registro processado pela trigger;
  • NEW: contém os novos valores;
  • NEW e OLD tem a mesma estrutura do registro declarado usando %ROWTYPE na tabela a qual a trigger é atachada (criada);

Untitled6

CREATE TABLE AUDIT_EMP (
  USER_NAME        VARCHAR2(30),
  TIME_STAMP       DATE,
  ID               NUMBER(6),
  OLD_LAST_NAME    VARCHAR2(25),
  NEW_LAST_NAME    VARCHAR2(25),
  OLD_TITLE        VARCHAR2(10),
  NEW_TITLE        VARCHAR2(10),
  OLD_SALARY       NUMBER(8,2),
  NEW_SALARY       NUMBER(8,2)
)
/

CREATE OR REPLACE TRIGGER AUDIT_EMP_VALUES
  AFTER DELETE OR INSERT OR UPDATE ON EMPLOYEES
  FOR EACH ROW
BEGIN
  INSERT INTO AUDIT_EMP(USER_NAME, TIME_STAMP, ID,
                        OLD_LAST_NAME, NEW_LAST_NAME,
                        OLD_TITLE,    NEW_TITLE,
                        OLD_SALARY,   NEW_SALARY)
  VALUES (USER, SYSDATE, :OLD.EMPLOYEE_ID,
          :OLD.LAST_NAME, :NEW.LAST_NAME,
          :OLD.JOB_ID, :NEW.JOB_ID,
          :OLD.SALARY, :NEW.SALARY);
END;

--EXMEPLO DE CHAMADA DA FUNÇÃO

INSERT INTO EMPLOYEES (EMPLOYEE_ID, LAST_NAME, JOB_ID, SALARY,
EMAIL, HIRE_DATE)
VALUES (999,'TEMP EMP','SA_REP',6000, 'TEMP EMP', TRUNC(SYSDATE));
/

UPDATE EMPLOYEES
SET SALARY = 7000,
LAST_NAME = 'Smith'
WHERE EMPLOYEE_ID = 999;

SELECT *
FROM AUDIT_EMP;

Exercícios

1. Crie uma tabela chamada empregados2 com a mesma estrutura da tabela employees. Faça uma trigger que a medida que a tabela employees for sido preenchida, essa tabela empregados2 deve ter os mesmos dados;

2. Faça uma trigger que verifique se os dados da tabela empregados2 está sendo alterada. Caso o salário esteja sendo alterado, a trigger não deve permitir gravar o registro;

3. Crie uma tabela chamada empregados3. Copie todos os dados que tenham o job_id = ‘IT_PROG’ da tabela employees para essa tabela. Crie uma outra tabela chamada log_empregados3, contendo as estrutura da tabela empregados3, com dados antes e depois de alterações. Faça uma trigger na tabela empregados3 para fazer essa auditoria;

PACKAGES (Pacotes)

  • Package é um objeto de um schema que agrupa logicamente tipos PL/SQL, variáveis e subprogramas;
  • Packages geralmente são divididos em 2 partes:
  • A especificação (spec)
  • O corpo
  • A especificação é uma interface para a Package. Ela declara os tipos, variáveis, constantes, exceções, cursores, e subprogramas que pode ser referenciados do lado de fora da Package;
  • O corpo define as queries de cursores e o código para os subprogramas;
  • Habilita o servidor Oracle a ler múltiplos objetos na memória de uma vez;

VANTAGENS DO USO DAS PACKAGES

  • Modularidade: Encapsulando construtores relacionados;
  • Fácil manutenção: mantendo logicamente funcionalidades relacionadas juntas;
  • Fácil projeto de aplicação: Codificando e compilando a especificação e o corpo separadamente;
  • Escondendo informação:
    • Somente as declarações na Especificação da Package são visíveis e acessíveis para aplicações;
    • Construtores privados no corpo da Package são escondidos e inacessíveis;
    • Toda codificação é escondida no corpo da Package;
  • Adição de funcionalidades: Persistência de variáveis públicas e cursores;
  • Melhor desempenho:
    • Toda a Package é carregada para a memória quando uma Package é referenciada na primeira vez;
    • Há uma única cópia na memória para todos os usuários;
    • A hierárquia de dependência é simplificada;
    • Overloading: Múltiplos subprogramas com o mesmo nome;

COMPONENTES DE UMA PACKAGE PL/SQL

Untitled

VISIBILIDADE INTERNA E EXTERNA DOS COMPONENTES DA PACKAGE

Untitled2

CRIANDO A ESPECIFICAÇÃO DA PACKAGE

Untitled3

  • Variáveis declaradas na especificação da Package são inicializados NULL por padrão;
  • Todos os construtores declarados na especificação da Package são visíveis a usuários que tem privilégios na Package;

CRIANDO A ESPECIFICAÇÃO DA PACKAGE NO SQL DEVELOPER

Untitled4

CRIANDO O CORPO DA PACKAGE NO SQL DEVELOPER

Untitled5

EXEMPLO DE ESPECIFICAÇÃO DA PACKAGE

CREATE OR REPLACE PACKAGE COMM_PKG IS
V_STD_COMM NUMBER := 0.10; --INICIALIZADO COM 0.10
PROCEDURE RESET_COMM(P_NEW_COMM NUMBER);
END COMM_PKG;
/
  • V_STD_COMM é variável pública global inicializada com 0.10;
  • RESET_COMM é procedure publica usada para resetar a comissão padrão baseada em algumas regras de negócio; Será implementadado no corpo da Package;

CRIANDO O CORPO DA PACKAGE

Untitled6

  • Identificadores definidos como privado o corpo da Package e não visível do lado de fora do corpo da package;
  • Todos construtores privados precisam ser declarados antes de eles serem referenciados;
  • Construtores públicos são visíveis para todo o corpo da Package;

EXEMPLO DE CORPO DA PACKAGE

CREATE OR REPLACE PACKAGE BODY COMM_PKG IS
  FUNCTION VALIDATE(P_COMM NUMBER) RETURN BOOLEAN IS
    V_MAX_COMM  EMPLOYEES.COMMISSION_PCT%TYPE;
  BEGIN
    SELECT  MAX(COMMISSION_PCT)
    INTO    V_MAX_COMM
    FROM    EMPLOYEES;
    RETURN (P_COMM BETWEEN 0.0 AND V_MAX_COMM);
  END VALIDATE;

  PROCEDURE RESET_COMM(P_NEW_COMM NUMBER) IS
  BEGIN
    IF VALIDATE(P_NEW_COMM) THEN
      V_STD_COMM := P_NEW_COMM; -- RESETA A VARIAVEL PUBLICA
    ELSE
      RAISE_APPLICATION_ERROR (-20210,'COMISSAO RUIM');
    END IF;
  END RESET_COMM;
END COMM_PKG;
/

CHAMANDO SUBPROGRAMAS DA PACKAGE

EXECUTE COMM_PKG.RESET_COMM(0.15);

Exercícios

  1. Faça uma Package que faça a Insert de funcionários (employees) e Select por ID. Deve conter também uma função que retorne o nome completo do funcionário, passando por parâmetro o ID. Faça os devidos testes de chamadas;
  1. Crie uma Package que faça o Insert, Update, Delete, e Select por ID do Departamento e outra Select pelo Nome do Departamento. Para fazer Inserção e atualização, é necessário verificar se o nome do departamento não exista na tabela. Em caso de um departamento já existente, exiba uma mensagem para ser exibido pelo ambiente chamador. Faça os devidos testes de chamadas;

 

Video 01

Banco de Dados II – Aula 12

MANIPULANDO EXCEÇÕES

  • Quando desenvolvemos procedures que são chamadas de outras procedures, devemos ter ciência dos processamentos e exceções de não processamento nas transações e chamadas de procedures;
  • Quando uma exceção é levantada na chamada de uma procedure, o controle vai imediatamente para a seção de exceção daquele bloco.
  • Uma exceção é considera processada se a exceção fornece um manipulador para a exceção levantada;
  • Quando uma exceção ocorre e é manipulada, o seguinte fluxo de código ocorre:
    • A exceção é erguida/levantada;
    • O controle é transferido para o manipulador de exceção;
    • O bloco é terminado;
    • O bloco/programa chamador continua a executar como se nada tivesse acontecido;

Sem título

EXEMPLO

CREATE OR REPLACE PROCEDURE add_department (p_name   VARCHAR2,
                                            p_mgr    NUMBER,
                                            p_loc    NUMBER) IS
BEGIN
  INSERT INTO departments(department_id,
                          department_name,
                          manager_id,
                          location_id)
  VALUES (departments_seq.NEXTVAL,
          p_name,
          p_mgr,
          p_loc);

  DBMS_OUTPUT.PUT_LINE('Departamento adicionado: ' || p_name);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Erro: adicionando departamento:' || p_name);
END add_department;
/

–CRIANDO UMA PROCEDURE PARA CHAMADA

CREATE OR REPLACE PROCEDURE CREATE_DEPARTMENTS IS
BEGIN
  add_department('Midia',100,1800);
  add_department('Edicao',99,1800);
  add_department('Propaganda',101,1800);
END;
/

–VERIFICANDO DADOS

SELECT * FROM DEPARTMENTS;

SET SERVEROUTPUT ON;

EXECUTE CREATE_DEPARTMENTS;

SELECT EMPLOYEE_ID
FROM   EMPLOYEES
WHERE  EMPLOYEE_ID IN (100,99,101);

ERRO GERADO DA CHAMADA DA PROCEDURE

Sem título2

MANIPULANDO EXCEÇÕES

  • Se uma exceção não é manipulada, então todos as declarações DML na chamada da procedure são feitas ROLLBACK, não efetivando nenhuma alteração em dados;
  • Declarações DML que não são afetadas são declarações que foram executadas antes da chamada do código PL/SQL a qual exceções não são manipuladas;

EXEMPLO

–EXEMPLO DE EXCEÇÕES NAO MANIPULADAS

SET SERVEROUTPUT ON;

CREATE OR REPLACE PROCEDURE add_department_noex (p_name VARCHAR2,
                                                 p_mgr  NUMBER,
                                                 p_loc  NUMBER ) IS
BEGIN
  INSERT INTO DEPARTMENTS (department_id,      
                           department_name,
                           manager_id,
                           location_id)
  VALUES(DEPARTMENTS_SEQ.NEXTVAL, p_name,
         p_mgr, p_loc);
  DBMS_OUTPUT.PUT_LINE('Departamento adicionado: ' || p_name);
END add_department_noex;
/

–CRIACAO DA PROCEDURE CHAMADORA

CREATE OR REPLACE PROCEDURE create_departments_noex IS
BEGIN
  add_department_noex('Midia 2',100,1800);
  add_department_noex('Edicao 2',99,1800);
  add_department_noex('Propaganda 2',101,1800);
END;

–CHAMADA DA PROCEDURE NOEX

EXECUTE create_departments_noex;

SELECT * FROM DEPARTMENTS;
  • Perceba que neste último exemplo, sem o tratamento de exceção, uma única linha não consistente não deixou que as demais linhas fossem incluídas na tabela;

Sem título3

EXCLUSÃO DE PROCEDURES

  • Para se fazer a exclusão de uma procedure, utilizamos o comando:
    • DROP PROCEDURE
  • Verifique antes na documentação se essa procedure não está sendo utilizada por nenhuma aplicação;
  • Caso você apague uma procedure que é chamada por outros objetos, o ORACLE não irá alertá-lo sobre isso;
  • As procedures ou objetos que são dependentes da procedure apagada ficam em estado “pendentes”;

Sem título4

VISUALIZANDO INFORMAÇÕES DE PROCEDURES UTILIZANDO DICIONARIO DE DADOS DAS VIEWS

  • O código fonte de subprogramas PL/SQL é armazenado no dicionário de dados;
  • Para ver os códigos armazenados, execute select nas declarações seguidas das tabelas:
    • Tabela USER_SOURCE mostra o código PL/SQL do seu dono;
    • Tabela ALL_SOURCE mostra o código a qual você tem direito concedido de EXECUTE pelo dono do subprograma;
DESCRIBE USER_SOURCE;

select * from USER_SOURCE;

DESCRIBE ALL_SOURCE;

select * from ALL_SOURCE;

LOOPS (LAÇOS)

  • Loops são repetições de um determinado trecho de código, ou seja, as instruções são executadas por várias vezes;
  • Em PL/SQL existem três tipos de loops;
    • LOOP BÁSICO (LAÇO);
    • LOOP FOR (PARA);
    • LOOP WHILE (ENQUANTO)

EXEMPLO DE LOOP BÁSICO

–LOOPS BASICO

DESCRIBE DEPARTMENTS;

DECLARE
  v_max_department_id  number;
  v_novo_departamento  departments.department_name%TYPE;
  v_contador           number := 1;
BEGIN
  SELECT MAX(DEPARTMENT_ID)
  INTO       v_max_department_id
  FROM      DEPARTMENTS;
  
  v_novo_departamento := '&NovoDepto';

  LOOP
    v_novo_departamento := v_novo_departamento || v_contador;
    
    INSERT INTO DEPARTMENTS(DEPARTMENT_ID, DEPARTMENT_NAME)
    VALUES (v_max_department_id + v_contador, v_novo_departamento);
    
    v_contador := v_contador + 1;
    
    EXIT WHEN v_contador > 4;
  END LOOP;
END;
/

–VERIFIQUE OS RESULTADOS

select * from departments;

EXEMPLO DE LOOP WHILE

DECLARE
  v_max_department_id  number;
  v_novo_departamento  departments.department_name%TYPE;
  v_contador           number := 1;
BEGIN
  SELECT MAX(DEPARTMENT_ID)
  INTO       v_max_department_id
  FROM      DEPARTMENTS;

  v_novo_departamento := '&NovoDepto';

  WHILE v_contador < 4 LOOP
    v_novo_departamento := v_novo_departamento || v_contador;
    INSERT INTO DEPARTMENTS(DEPARTMENT_ID, DEPARTMENT_NAME)
    VALUES (v_max_department_id + v_contador, v_novo_departamento);
    v_contador := v_contador + 1;
END LOOP;
END;
/

–VERIFIQUE OS RESULTADOS

select * from departments;

EXEMPLO DE LOOP FOR

DECLARE
  v_max_department_id   number;
  v_novo_departamento  departments.department_name%TYPE;
  v_contador            number := 1;
BEGIN
  SELECT MAX(DEPARTMENT_ID)
  INTO       v_max_department_id
  FROM      DEPARTMENTS;

  v_novo_departamento := '&NovoDepto';

  FOR I IN 1..3 LOOP
    v_novo_departamento := v_novo_departamento || v_contador;
    
    INSERT INTO DEPARTMENTS(DEPARTMENT_ID, DEPARTMENT_NAME)
    VALUES (v_max_department_id + v_contador, v_novo_departamento);

    v_contador := v_contador + 1;
  END LOOP;
END;
/

–VERIFIQUE OS RESULTADOS

select * from departments;

INSTRUÇÃO CONTINUE

  • É utilizado dentro de um dos tipos de loops;
  • Faz com que a condição do laço seja avaliada antes de terminar o bloco do loop;
  • Oferece aos programadores a habilidade de transferir o controle para a próxima interação;

EXEMPLO DE CONTINUE

SET SERVEROUTPUT ON;
DECLARE
  v_soma SIMPLE_INTEGER :=0;
BEGIN
  FOR i IN 1..10 LOOP
    v_soma := v_soma + 1;
    DBMS_OUTPUT.PUT_LINE('A soma é: ' || v_soma);
    CONTINUE WHEN i > 6;
    v_soma := v_soma +1;
    DBMS_OUTPUT.PUT_LINE('Sem entrar continue, soma é: ' || v_soma);
  END LOOP;
END;
/

DATATYPE

  • Datatypes são tipo de dados que possuem múltiplos valores, ou seja, pode-se armazenar vários dados em uma única variável, que ao contrário do tipos char, number, date, podem armazenar somente 1 por vez;
  • Podem ser do tipos RECORD e COLLECTION;

RECORDS e COLLECTIONS

  • RECORD é quando queremos armazenar um valor com diferentes tipos de dados em uma única ocorrência naquele momento;
  • COLLECTION é quando queremos armazenar alguns valores do mesmo tipo de dado (record);

Sem título5

  • RECORD contém um ou mais componentes, também conhecidos como campos de qualquer tipo escalar (number, char, date, etc);
  • São similares a estrutura da linguagem C;
  • Trata uma coleção de campos como uma unidade lógica;

ESTRUTURA DE UM RECORD

Sem título6

MANUPILAÇÃO DOS RECORDS

  • Notação de um campo individual:
    • CLI_RECORD.NOME;
  • Atribuindo um valor ao record:
    • CLI_RECORD.NOME := ‘JOAO DA SILVA’;

ATRIBUTO %ROWTYPE

  • Declara uma variável de acordo com uma coleção de colunas de uma tabela uma view;
  • Campos de um RECORD tem que ter mesmos nomes e tipos de colunas de uma tabela ou view;

EXEMPLO DE  %ROWTYPE

SET SERVER_OUTPUT ON;
DECLARE
  TYPE EMP_REC IS RECORD (
  v_sal       number(8),
  v_minsal    number(8) default 1000,
  v_hire_date employees.hire_date%TYPE,
  v_emp1      employees%ROWTYPE);
  v_meurec EMP_REC;
BEGIN
  v_meurec.v_sal := v_meurec.v_minsal + 500;
  v_meurec.v_hire_date := sysdate;

  SELECT  *
  INTO    v_meurec.v_emp1
  FROM    employees
  WHERE   EMPLOYEE_ID = 100;

  DBMS_OUTPUT.PUT_LINE(v_meurec.v_emp1.last_name || ' ' ||
  to_char(v_meurec.v_hire_date) || ' ' ||
  to_char(v_meurec.v_sal));
END;
/

CURSORES

  • Toda instrução SQL que é executada no Servidor Oracle é associado um cursor individual;
  • Cursor implícito é declarado e gerenciado pelo PL/SQL;
  • Cursor explícito é declarado e gerenciado pelo programador;

CURSORES EXPLICITOS

Sem título7

CONTROLANDO CURSORES EXPLÍCITOS

Sem título8

DECLARANDO CURSORES

  • Não incluir INTO na declaração do cursor, pois o carregamento dos valores será feita após o FETCH;
  • Caso queira que seja processado em uma determinada sequencia, utilize ORDER BY;
  • Um cursor pode suportar SELECTs com JOINS;
SET SERVEROUTPUT ON;
DECLARE
  CURSOR c_emp_cursor is
    SELECT  employee_id, last_name
    FROM    employees
    WHERE   department_id = 30;
  v_empno employees.employee_id%TYPE;
  v_lname employees.last_name%TYPE;
BEGIN
  OPEN c_emp_cursor;
  FETCH c_emp_cursor INTO v_empno, v_lname;
  DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
END;
/

CURSORES COM LOOP

SET SERVEROUTPUT ON;
DECLARE
  CURSOR c_emp_cursor is
    SELECT  employee_id, last_name    
    FROM    employees WHERE   department_id = 30;
    v_empno employees.employee_id%TYPE;
    v_lname employees.last_name%TYPE;
BEGIN
  OPEN c_emp_cursor;
  
  LOOP
    FETCH c_emp_cursor INTO v_empno, v_lname;

    EXIT WHEN c_emp_cursor%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
  END LOOP;

  CLOSE c_emp_cursor ;
END;
/

LOOP FOR COM CURSORES

SET SERVEROUTPUT ON;
DECLARE
  CURSOR c_emp_cursor IS
    SELECT employee_id, last_name FROM employees
    WHERE department_id = 30;
BEGIN
  FOR emp_record IN c_emp_cursor
  LOOP
    DBMS_OUTPUT.PUT_LINE(emp_record.employee_id ||' '||   emp_record.last_name);
  END LOOP;
END;
/

STATUS DE CURSORES

Sem título9

UTILIZAÇÃO DO %ISOPEN

SET SERVEROUTPUT ON;
DECLARE
  CURSOR c_emp_cursor is
    SELECT  employee_id, last_name
    FROM    employees
    WHERE   department_id = 30;
  v_empno employees.employee_id%TYPE;
  v_lname employees.last_name%TYPE;
BEGIN
  IF NOT c_emp_cursor%ISOPEN THEN
    OPEN c_emp_cursor;
  END IF;
  
  LOOP
    FETCH c_emp_cursor INTO v_empno, v_lname;
    EXIT WHEN c_emp_cursor%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
  END LOOP;
END;
/

UTILIZAÇÃO DO %ROWCOUNT e %NOTFOUND

SET SERVEROUTPUT ON;
DECLARE
  CURSOR c_emp_cursor is
    SELECT  employee_id, last_name FROM    employees
    WHERE   department_id = &cod_departamento;
  v_emp_record c_emp_cursor%ROWTYPE;
BEGIN
  OPEN c_emp_cursor;
  LOOP
    FETCH c_emp_cursor INTO v_emp_record;
    EXIT WHEN c_emp_cursor%ROWCOUNT > 10 OR
    
    c_emp_cursor%NOTFOUND;
    
    DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id
    || ' ' || v_emp_record.last_name);
  END LOOP;
  CLOSE c_emp_cursor;
END;
/

FUNÇÕES

  • É um bloco PL/SQL nomeado que retorna um valor;
  • Pode ser armazenado no banco de dados como um objeto de schema para execuções repetidas;
  • É chamada como parte de uma expressão ou é usada para fornecer um valor de parâmetro para outro subprograma;
  • Pode ser agrupadas em pacotes do PL/SQL;
  • O bloco PL/SQL precisa ter ao menos uma declaração de retorno (RETURN);
  • É criado com o comando CREATE FUNCTION;
  • Apesar de parâmetros OUT e IN OUT serem modos que podem utilizar as funções, não é uma boa prática utilizá-las em funções;
  • No entanto, se você precisa retornar mais de um valor de uma função, considere retornar valores compostos de estrutura de dados como um registro ou tabela PL/SQL;

DIFERENÇAS ENTRE PROCEDURES E FUNÇÕES

PROCEDURES FUNCTIONS
Executa como declaração PL/SQL Chamado com uma parte de uma expressão
Não contém cláusula RETURN no cabeçalho Precisa conter um RETURN no cabeçalho
Pode passar valores (se precisar) usando parâmetros output Precisa retornar um valor simples
Pode conter a declaração RETURN sem um valor Precisa conter ao menos uma declaração RETURN

VISÃO GERAL DA CRIAÇÃO E EXECUÇÃO DE FUNÇÕES

Sem título10

CRIANDO E CHAMANDO UMA FUNÇÃO

–CRIANDO A FUNÇÃO

CREATE OR REPLACE FUNCTION get_sal
  (p_id IN employees.employee_id%TYPE)
RETURN NUMBER IS
  v_sal employees.salary%TYPE := 0;
BEGIN
  SELECT salary
  INTO   v_sal
  FROM   employees
  WHERE  employee_id = p_id;
  
  RETURN v_sal;
END get_sal;
/

–CHAMANDO A FUNÇÃO EM UMA EXPRESSAO
–COM UM VALOR DE PARAMETRO

SET SERVEROUTPUT ON;

EXECUTE dbms_output.put_line(get_sal(100));

DIFERENTES MÉTODOS PARA SE EXECUTAR UMA FUNÇÃO

–EXEMPLO 1

VARIABLE b_salary NUMBER

EXECUTE :b_salary := get_sal(100);

PRINT b_salary;

–EXEMPLO 2

SET SERVEROUTPUT ON

DECLARE
  sal employees.salary%TYPE;
BEGIN
  sal := get_sal(100);
  DBMS_OUTPUT.PUT_LINE('o SALÁRIO É: ' || sal);
END;
/

–EXEMPLO 3

EXECUTE dbms_output.put_line   (get_sal(100));

–EXEMPLO 4

SELECT  JOB_ID, GET_SAL(EMPLOYEE_ID)
FROM    EMPLOYEES;

TABELA DO DICIONÁRIO DE DADOS

  • Podemos utilizar a tabela USER_OBJECTS para identificar os tipos de objetos que o usuário corrente tem acesso;
SELECT   object_name,
         object_type
FROM     user_objects;

EXEMPLO DE FUNÇÃO COM COMPARAÇÕES

CREATE OR REPLACE FUNCTION check_sal
  RETURN Boolean IS
  v_dept_id   employees.department_id%TYPE;
  v_empno     employees.employee_id%TYPE;
  v_sal       employees.salary%TYPE;
  v_avg_sal   employees.salary%TYPE;
BEGIN
  v_empno := 205;
  SELECT  salary, department_id
  INTO    v_sal, v_dept_id,
  FROM    employees
  WHERE   employee_id = v_empno;

  SELECT  avg(salary)
  INTO    v_avg_sal
  FROM    employees
  WHERE   department_id = v_dept_id;

  IF v_sal > v_avg_sal THEN
    RETURN TRUE;
  ELSE
    RETURN FALSE;
  END IF;

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RETURN NULL;
END;

MOSTRANDO POSSÍVEIS ERROS

–mostrando onde estão os possíveis erros

SHOW ERRORS FUNCTION check_sal

--SERÁ MOSTRADO POSSIVELMENTE

LINE/COL ERROR
-------- ----------------------------------
9/3      PL/SQL: SQL Statement ignored
11/3     PL/SQL: ORA-00936: missing expression

AJUSTE DA FUNÇÃO

–ajuste a seguinte parte da função

SELECT  salary,
        department_id
INTO    v_sal,
        v_dept_id

CHAMADA DA FUNÇÃO

–chamada da função

SET SERVEROUTPUT ON;
BEGIN
  IF (check_sal IS NULL) THEN
  DBMS_OUTPUT.PUT_LINE('A função retornou NULL devido a exceção');
  ELSIF (check_sal) THEN
    DBMS_OUTPUT.PUT_LINE('Salario > média');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Salario < média');
  END IF;
END;
/

PASSANDO PARAMETROS PARA UMA FUNÇÃO

CREATE OR REPLACE FUNCTION check_sal
  (p_empno employees.employee_id% TYPE)
RETURN Boolean IS
  v_dept_id   employees.department_id%TYPE;
  v_sal       employees.salary%TYPE;
  v_avg_sal   employees.salary%TYPE;
BEGIN
  SELECT  salary, department_id
  INTO    v_sal, v_dept_id
  FROM    employees
  WHERE   employee_id = p_empno;
  
  SELECT  avg(salary)
  INTO    v_avg_sal
  FROM    employees
  WHERE   department_id = v_dept_id;

  IF v_sal > v_avg_sal THEN
    RETURN TRUE;
  ELSE
    RETURN FALSE;
  END IF;

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RETURN NULL;
END;
/

CHAMADA DA FUNÇÃO COM PARAMETROS

SET SERVEROUTPUT ON;
BEGIN
  DBMS_OUTPUT.PUT_LINE('Checando o empregado 205');
  
  IF (check_sal(205) IS NULL) THEN
    DBMS_OUTPUT.PUT_LINE('A função retornou NULL devido   a exceção');
  ELSIF (check_sal(205)) THEN
    DBMS_OUTPUT.PUT_LINE('Salario > média');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Salario < média');   END IF;   DBMS_OUTPUT.PUT_LINE('Checando o empregado 70');      IF (check_sal(70) IS NULL) THEN     DBMS_OUTPUT.PUT_LINE('A função retornou NULL devido     a exceção');   ELSIF (check_sal(70)) THEN     DBMS_OUTPUT.PUT_LINE('Salario > média');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Salario < média');
  END IF;
END;
/

Exercícios

  1. Crie uma função, que passado 2 parâmetros do tipo number, (o valor do primeiro parâmetro deve ser menor que o segundo) retorne o valor do maior salário encontrado. Os parâmetros passados são correspondentes aos códigos dos empregados. Essa função deve tratar erro, caso o primeiro parâmetro seja maior que o segundo parâmetro. No ambiente chamador, mostre o valor encontrado;
  1. Crie uma função, que passado um parâmetro do tipo number e outro do tipo data, que retorne a quantidade de tempo que o empregado está na empresa em anos que o valor deve ser arredondado. Os parâmetros passados são correspondentes ao códigos do empregados e a data de admissão. No ambiente chamador, deve-se chamar a função através de um comando select;
  1. Crie uma função, que passado um parâmetro do tipo number, retorne se o funcionário tem o job_id igual a “IT_PROG” ou “PU_CLERCK”. O parâmetro passado é correspondente ao código do funcionário. No ambiente chamador, deve ser impresso se o funcionário tem ou não tem o job_id igual a “IT_PROG” ou “PU_CLERCK”;
  1. Crie uma função, que passado um parâmetro do tipo number, retorne a quantidade de funcionário que existem em um determinado departamento. O parâmetro passado é correspondente ao departamento. No ambiente chamador, é necessário estar impresso o código do departamento e a quantidade de funcionários;

Vídeo – Parte 1

Vídeo – Parte 2

Vídeo – Parte 3

 

 

 

 

Banco de Dados II – Aula 11

INTRODUÇÃO AO PL/SQL

  • PL/SQL é uma linguagem de programação em blocos;
  • Uma unidade de programa pode ser Nomeada ou Não Nomeada;
  • Blocos Não Nomeados também são conhecidos como blocos anônimos;

Sintaxe geral:

[DECLARE]
declaration_statements
BEGIN
execution_statements
[EXCEPTION]
exception_handling_statements
END;

  • Em uma declaração de blocos, podem ser definidos tipos de dados, estruturas, variáveis;
  • Estruturas também podem ser localmente chamadas de funções, procedimentos e cursores;
  • BEGIN e END são palavras reservadas, com o uso opcional da palavra EXCEPTION
  • O mínimo código de um bloco anônimo é:
BEGIN
NULL;
END;
/
  • A exceção do bloco de manipulação permite você gerenciar exceções; 
  • Blocos nomeados têm uma ligeira diferença dos blocos não nomeados, porque os blocos nomeados ficam armazenados no banco de dados;
  • Blocos nomeados tem também uma sessão de declaração, chamado como header (cabeçalho);
  • O nome e a lista de parâmetros são chamados de uma assinatura de uma sub-rotina;
  • As mesmas regras são aplicadas para os corpos dos objetos (bodies); 

Exemplo de bloco nomeado:

PROCEDURE procedure_name
( parameter1 [IN][OUT] [NOCOPY] sql_data_type | plsql_data_type
, parameter2 [IN][OUT] [NOCOPY] sql_data_type | plsql_data_type
, parameter(n+1) [IN][OUT] [NOCOPY] sql_data_type | plsql_data_type )
[ AUTHID {DEFINER | CURRENT_USER}]
declaration_statements
BEGIN
  execution_statements
[EXCEPTION]
  exception_handling_statements
END;
/

Habilitando OUTPUT em um bloco PL/SQL:

  • Escreva antes do bloco PL/SQL:
  SET SERVEROUTPUT ON;

Use o pacote (package) pré-definido DBMS_OUTPUT   
Exemplo do DBMS_OUTPUT  :

DBMS_OUTPUT.PUT_LINE ('O primeiro nome de funcionário é ' || v_fname);
... 
  • Escreva antes do bloco PL/SQL:
  SET SERVEROUTPUT ON;

Use o pacote (package) pré-definido DBMS_OUTPUT.PUT_LINE(‘string’) 

Exemplo:

SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE  ('IMPRESSAO DE LINHA  USANDO PUT_LINE');
END;
/  

CONFIGURAÇÃO DO SERVEROUTPUT

–CONFIGURANDO O AMBIENTE, QTD DE BUFFER SET SERVEROUTPUT ON SIZE 1000000;

DBMS_OUTPUT.ENABLE(1000000); 
DBMS_OUTPUT.DISABLE; 

–EXEMPLO

BEGIN DBMS_OUTPUT.PUT('LINHA '); 
  DBMS_OUTPUT.PUT('UM.'); 
  DBMS_OUTPUT.NEW_LINE; 
  DBMS_OUTPUT.PUT_LINE('LINHA DOIS.'); 
END; 
/

TIPO BOLEANO

  • O tipo boleado de dados por ter três possibilidade de valores: TRUE, FALSE e NULL;
  • Pode ser declarado como e exemplo a seguir;
SET SERVEROUTPUT ON;
DECLARE
  var1 BOOLEAN;
  var2 BOOLEAN NOT NULL := TRUE;
  var3 BOOLEAN NOT NULL := FALSE;
BEGIN
  DBMS_OUTPUT.PUT_LINE(CASE WHEN var1 THEN 'TRUE'
                         WHEN var1 IS NULL THEN 'NULL'
                         ELSE 'FALSE'
                       END );

  DBMS_OUTPUT.PUT_LINE(CASE WHEN var2 THEN 'TRUE'
                       WHEN var2 IS NULL THEN 'NULL'
                       ELSE 'FALSE'
                     END);

  DBMS_OUTPUT.PUT_LINE(CASE WHEN var3 THEN 'TRUE'
                       WHEN var3 IS NULL THEN 'NULL'
                       ELSE 'FALSE'
                     END);
END;
/

CARACTERES E STRINGS

  • O tamanho da string é declarado pelo número de bytes ou caracteres;
  • Qualquer tentativa de armazenamento maior que o tamanho suportado, pode ser tratado com exceção;
SET SERVEROUTPUT ON;
DECLARE
  c CHAR(32767) := ' ';
  v VARCHAR2(32767) := ‘ ';
BEGIN
  DBMS_OUTPUT.PUT_LINE(' c é ['|| LENGTH(c)||']');
  DBMS_OUTPUT.PUT_LINE(' v é ['|| LENGTH(v)||']');
  v := v || ' ';
  DBMS_OUTPUT.PUT_LINE(' v é ['|| LENGTH(v)||']');
END;
/

O TIPO CHAR E VARCHAR

  • O tipo CHAR é baseado em um tamanho fixo de strings. O padrão é o tamanho de 1 byte, podendo chegar até a 32.767;
  • Em colunas CHAR, o máximo permitido são 4000 bytes;
  • A Oracle recomenda utilizar CLOB ou LONG para colunas;
  • O tipo VARCHAR2 tem base em tamanhos variados;
  • VARCHAR2 pode chegar até 32.767 bytes de tamanho;

EXEMPLO DO TIPO CHAR

--tipo char
SET SERVEROUTPUT ON;
DECLARE
  var1 CHAR;
  var2 CHAR(10);
  var3 CHAR(10 BYTE);
  var4 CHAR(10 CHAR);
BEGIN
  var1 := 'a'; var2 := 'b'; var3 := 'c'; var4 := 'd';
  DBMS_OUTPUT.PUT_LINE(' var1 é ['|| LENGTH(var1)||']');
  DBMS_OUTPUT.PUT_LINE(' var2 é ['|| LENGTH(var2)||']');
  DBMS_OUTPUT.PUT_LINE(' var3 é ['|| LENGTH(var3)||']');
  DBMS_OUTPUT.PUT_LINE(' var4 é ['|| LENGTH(var4)||']');
END;
/

EXEMPLO DO TIPO VARCHAR2
--tipo varchar2
SET SERVEROUTPUT ON;
DECLARE
  var1 VARCHAR2; --erro
  var2 VARCHAR2(10);
  var3 VARCHAR2(10 BYTE);
  var4 VARCHAR2(10 CHAR);
BEGIN
  var1 := 'A'; var2 := 'AB'; var3 := 'ABC'; var4 := 'ABCD';
  DBMS_OUTPUT.PUT_LINE(' var1 é ['|| LENGTH(var1)||']');
  DBMS_OUTPUT.PUT_LINE(' var2 é ['|| LENGTH(var2)||']');
  DBMS_OUTPUT.PUT_LINE(' var3 é ['|| LENGTH(var3)||']');
  DBMS_OUTPUT.PUT_LINE(' var4 é ['|| LENGTH(var4)||']');
END;
/

OS TIPOS DATE, TIME, INTERVAL

Sem título

EXEMPLO DO DATE

SET SERVEROUTPUT ON;
DECLARE
  var1 DATE;
  var2 DATE := SYSDATE;
  var3 DATE := SYSDATE +1;
  var4 DATE := '29-FEB-08';
BEGIN
  DBMS_OUTPUT.PUT_LINE(' var1 é ['|| var1 ||']');
  DBMS_OUTPUT.PUT_LINE(' var2 é ['|| var2 ||']');
  DBMS_OUTPUT.PUT_LINE(' var3 é ['|| var3 ||']');
  DBMS_OUTPUT.PUT_LINE(' var4 é ['|| var4 ||']');
END;
/

O TIPO TIMESTAMP

  • É um subtipo extendido de DATE, que oferece mais precisão no tempo;
  • SYSTIMESTAMP oferece o tempo mais preciso dependendo da plataforma;

EXEMPLO DO TIMESTAMP

SET SERVEROUTPUT ON;
DECLARE
  d DATE := SYSTIMESTAMP;
  t TIMESTAMP(3) := SYSTIMESTAMP;
BEGIN
  DBMS_OUTPUT.PUT_LINE('DATE      ['||d||']');
  DBMS_OUTPUT.PUT_LINE('TO_CHAR['||TO_CHAR(d,'DD-MON-YY HH24:MI:SS') ||']');
  DBMS_OUTPUT.PUT_LINE('TIMESTAMP ['||t||']');
END;
/

CARACTERES UNICODES

  • Caracteres unicodes servem para suportar globalização;
  • Globalização é a utilização de caracteres que suportam múltiplos conjuntos de caracteres;
  • A codificação AL16UTF16 ou UTF8 são oferecidas pelo Oracle;
  • AL16UTF16 utiliza 2 bytes por caracter;
  • UTF8 utiliza 3 bytes por caracter;
  • NCHAR é o tipo de dado UNICODE;
  • Pode armazenar até o tamanho de 16.383 (32.767 / 2);
  • NVARCHAR2 é o equivalente ao VARCHAR2;

Sem título2Ref: https://docs.oracle.com/cd/B19306_01/server.102/b14225/ch6unicode.htm

O TIPO NUMBER

  • Há 4 principais tipos de números no Oracle: BINARY_INTEGER, IEEE 754 (BINARY_DOUBLE e BINARY_FLOAT), O NUMBER e PLS_INTEGER;
  • BINARY_INTEGER e PLS_INTEGER são idênticos, suportando a -2.147.483.648 a 2.147.483.647;

ATRIBUINDO VALORES À VARIÁVEIS DINAMICAMENTE

  • No ambiente SQL Developer, podemos fazer a atribuição de variáveis através do símbolo “&” (e comercial sem aspas);
--EXEMPLO DE ATRIBUIÇÃO DE VARIÁVEIS
SET SERVEROUTPUT ON;
DECLARE
  var1  number;   var2  number;   soma  number;
BEGIN
  DBMS_OUTPUT.PUT_LINE('Digite valor 1:');
  var1 := &Valor1;
  
  DBMS_OUTPUT.PUT_LINE('Digite valor 2:');
  var2 := &Valor2;
  
  DBMS_OUTPUT.PUT_LINE('Valor 1:' || var1);
  
  DBMS_OUTPUT.PUT_LINE('Valor 2:' || var2);
  
  soma := var1 + var2;
  
  DBMS_OUTPUT.PUT_LINE('Soma:' || soma);
END;
/

EXEMPLO DE DECLARAÇÃO DE TIPOS DE VARIÁVEIS
SET serveroutput ON;
DECLARE
  nIdFuncionario binary_integer;
  nSalario NUMBER(10, 2);  nAcrescimo FLOAT;
BEGIN
  nidfuncionario := 25;
  nSalario       := 1500;
  nAcrescimo     := 0.25;
  dbms_output.put_line('O novo salário do funcionário: ' || nSalario * (1 + nAcrescimo));
END;

--VARIAVEIS NUMBER, FLOAT, BINARY_INTEGER

SET SERVEROUTPUT ON;
DECLARE
  v_FUNCIONARIO_ID  BINARY_INTEGER;
  v_SALARIO NUMBER(10,2); v_ACRESCIMO  FLOAT;
BEGIN
  v_FUNCIONARIO_ID := 10; v_SALARIO := 2000;
  v_ACRESCIMO := 0.10;
 
DBMS_OUTPUT.PUT_LINE('O novo salario do funcionario: '
  || v_FUNCIONARIO_ID || ' terá acrescimo de '
  || v_SALARIO * v_ACRESCIMO);
END;

--VARIAVEIS BOOLEAN
SET SERVEROUTPUT ON;
DECLARE
  v_FUNCIONARIO_ID  BINARY_INTEGER;
  v_SALARIO         NUMBER(10,2);
  v_SAL_EM_REAL     BOOLEAN;
BEGIN
  v_FUNCIONARIO_ID := 10;
  v_SALARIO := 2000;
  v_SAL_EM_REAL := TRUE;
  IF v_SAL_EM_REAL THEN
    DBMS_OUTPUT.PUT_LINE('O salario do funcionario: '
      || v_FUNCIONARIO_ID || ' é de  '
      || v_SALARIO || ' em reais');
  ELSE
    DBMS_OUTPUT.PUT_LINE('O salario do funcionario: '
      || v_FUNCIONARIO_ID || ' é de  '
      || v_SALARIO || ' em dolares');
  END IF;
END;
/

CONSTANTES

  • É similar a uma variável, porém valores não podem ser atribuídos durante o bloco de código;
  • A palavra CONSTANT reserva é colocada depois do nome da variável e antes do tipo da variável;
  • Pode ser definida por qualquer tipo de dados disponível para variáveis;
  • Para utiliza-la, tenha certeza de que o valor não será alterado;
EXEMPLO DE CONSTANTES
--irá gerar erro
SET SERVEROUTPUT ON;
DECLARE
  v_SALARIO CONSTANT number(4);
BEGIN
  v_SALARIO := 1000;
  dbms_output.put_line (v_SALARIO);
END;
/

 
--irá funcionar
SET SERVEROUTPUT ON;
DECLARE
  v_SALARIO CONSTANT number(4) := 1000;
BEGIN
  dbms_output.put_line (v_SALARIO);
END;
/

VARIÁVEIS NOT NULL

  • É possível declarar em PL/SQL variáveis NOT NULL;
  • No decorrer do código, esta variável deverá ter algum valor, não podendo ser nula;
  • É declarado na seção DECLARE, sendo que a variável precisa ter um valor associado;

EXEMPLO DE VARIÁVEIS NOT NULL

--erro
SET SERVEROUTPUT ON;
DECLARE
  v_FUNCIONARIO_ID BINARY_INTEGER NOT NULL := 10;
  v_SALARIO        NUMBER(10,2) := 1000;
BEGIN
  v_FUNCIONARIO_ID := NULL;
  DBMS_OUTPUT.PUT_LINE('Funcionario: ' || v_FUNCIONARIO_ID);
  v_SALARIO := NULL;
  DBMS_OUTPUT.PUT_LINE('Salario : ' || v_SALARIO);
END;
/ 

--correto
SET SERVEROUTPUT ON;
DECLARE
  v_FUNCIONARIO_ID BINARY_INTEGER NOT NULL := 10;
  v_SALARIO        NUMBER(10,2) := 1000;
BEGIN
  DBMS_OUTPUT.PUT_LINE('Funcionario: ' || v_FUNCIONARIO_ID);
  v_SALARIO := NULL;
  DBMS_OUTPUT.PUT_LINE('Salario : ' || v_SALARIO);
END;
/

EXEMPLO DE IF..THEN.. ELSE

-- IF THEN ELSE
SET SERVEROUTPUT ON;
DECLARE
  v_SALARIO         NUMBER(10,2);
BEGIN
  v_SALARIO := &Salario;
  IF v_SALARIO BETWEEN 0 AND 1000 THEN
    DBMS_OUTPUT.PUT_LINE('Salario baixo:  ' || v_SALARIO);
  ELSIF v_SALARIO BETWEEN 1001 AND 2000 THEN
    DBMS_OUTPUT.PUT_LINE('Salario médio:  ' || v_SALARIO);
  ELSE
    DBMS_OUTPUT.PUT_LINE('Salario alto:  ' || v_SALARIO);
  END IF;
END;
/

Exercícios

  1. Crie uma bloco anônimo que leia três variáveis do tipo number e aponte mostre os números digitados e o maior número dentre os três;
  1. Crie um bloco anônimo que leia 2 variáveis do tipo number, mostre os dois números digitados e mostre o resultado da soma, multiplicação, subtração e divisão desses dois números;
  1. Crie um bloco anônimo que leia 2 variáveis do tipo number, e leia qual operação o usuário deseja fazer, escolhendo entre os símbolos (+, -, /, *). O símbolo escolhido deve ser apresentado o resultado dentre os dois números;
  1. Crie um bloco anônimo que leia 3 frases de até 100 caracteres, mostre as frases digitadas, mostre quantos caracteres cada frase possui, e mostre a soma da quantidade de caracteres total das tres frases;
  1. Crie um bloco anônimo que leia 2 datas, mostrando a quantidade de dias, meses e anos dentre essas datas. (Pode fazer arredondamento caso necessário). Observação, a Data Inicial precisa ser menor que a data final;
  1. Crie um bloco nomeado que tenha 3 parametros de entrada do tipo number e que mostre o menor número dos 3 argumentos passados;
  1. Crie um bloco nomeado que tenha 2 parametros de entrada do tipo nvarchar, e mostre quantos bytes cada parâmetro está ocupando;
  1. Crie um bloco nomeado que tenha 2 parametros de entrada, uma do tipo number e outra do tipo date, e que mostre a data mais o parâmetro do tipo number e a data menos o parâmetro do tipo number;

PROCEDURES EM PL/SQL

  • São tipos de sub-programas que executam uma ação;
  • Pode ser armazenado em um banco como um objeto de schema;
  • Provê reusabilidade e fácil manutenção;
  • Pode aceitar parâmetros;
  • A procedure é compilada e armazenada no banco de dados como um schema de objeto;
  • Um bloco de comandos PL/SQL pode aceitar variáveis de substituição;
SET SERVEROUTPUT ON
DECLARE
  my_var VARCHAR2(30);
BEGIN
  my_var := '&input';
  dbms_output.put_line('Hello '|| my_var );
END;
/
  • O operador de atribuição é “:=” (sem aspas);
  • Strings são delimitadas por aspas simples;
  • Declara-se variáveis na seção DECLARE;
  • Os tipos de variáveis utilizadas são as mesmos tipos de variáveis utilizados nas tabelas do Oracle;
SET SERVEROUTPUT ON
DECLARE
  my_var VARCHAR2(10);
BEGIN
  my_var := '&input';
  dbms_output.put_line('Hello '|| my_var );
EXCEPTION
  WHEN others THEN
    dbms_output.put_line(SQLERRM);
END;
/
  • Em PL/SQL, é possível fazer tratamentos de erros com a cláusula EXCEPTION;
  • A função SQLERRM irá capturar o erro, e é possível mostrar os erros através do comando de impressão;
  • SQLERRM retorna a mensagem de erro associado ao número do erro;
  • Quando estamos codificando em linguagens de programação, é normal que tenhamos que seguir algumas regras de convenção de nomes;
  • Elas servem para que se tenha padronização em na codificação dos programas;
  • Não há uma regra clara sobre o uso de nomeações padrão. Caso não tenha, é importante adotar uma;

EXEMPLO DE CONVENSÃO DE NOMES EM PL/SQL

Sem título4

PARAMETROS E SEUS MODOS

  • São declaradas depois dos subprogramas no header da procedure;
  • Passa dados entre o ambiente de chamada e o subprograma;
  • São usados como variáveis locais, mas são dependentes do modo em que são tratados
  • IN é o modo padrão que passa os valores do ambiente de chamada para o subprograma;
  • OUT é o modo de retorno do valor para o ambiente chamador;
  • IN OUT é o modo que passa valores do ambiente de chamada, a qual pode retornar o valor modificado (o mesmo parâmetro);

Sem título5

PARAMETRO FORMAL

  • Variáveis locais declaradas na lista de parâmetros da especificação do subprograma;

PARAMETRO ATUAL

  • Ou também conhecidos como argumentos: Valores literais, variáveis e expressões são usadas na lista de parâmetros que chamam o subprograma (procedure)

MODOS DOS PARAMETROS

  • O tipo dos parâmetros pode ser especificado sem o tamanho do seu tipo;
  • Podem ser utilizados:
  • O tipo explicito do dado;
  • Usando a definição %TYPE;
  • Usando a definição %ROWTYPE;
  • Um ou mais parâmetros formais podem ser declarados, cada um separados por virgula;

COMPARAÇÃO DOS MODOS DOS PARAMETROS

  • IN é o padrão se não há especificação na declaração;
  • OUT e IN OUT precisam ser explicitamente especificados na declaração dos parâmetros;
  • No parâmetro formal IN não pode ser atribuído um valor e não pode ser modificado no corpo da procedure. Por padrão, o parâmetro IN é passado por referencia
  • Um parâmetro IN pode ser atribuído por um valor padrão na declaração do parâmetro formal, em caso do ambiente chamador não fornecer um valor para o parâmetro se o valor padrão é aplicado;
  • OUT ou IN OUT precisam ser atribuídos um valor antes do retorno do ambiente chamador.
  • OUT e IN OUT não podem ser atribuídos valores padrão;

COMPARAÇÃO DOS MODOS DOS PARAMETROS

Não pode ser atribuído um valor padrão

IN OUT IN OUT
Modo padrão Precisa ser especificado Precisa ser especificado
Valor é passado para o subprograma Valor é retornado para o ambiente chamador Valor é passado para o subprograma; valor é retornado para o ambiente chamador
Parâmetros formais e atuais como uma constante Variáveis não inicializáveis Variáveis inicializáveis
Parâmetro atual pode ser literal, expressão, constantes, ou variáveis inicializáveis Precisa ser uma variável Precisa ser uma variável
Pode ser atribuído um valor padrão Não pode ser atribuído um valor padrão

EXEMPLO DE USO DO PARÂMETRO IN

--EXEMPLO DO PARAMETRO IN
CREATE OR REPLACE PROCEDURE previsao_salario (p_id   in employees.employee_id%TYPE, p_percent in NUMBER)
IS
BEGIN
  UPDATE  EMPLOYEES
  SET     SALARY = SALARY * (1 + p_percent /100)
  WHERE  EMPLOYEE_ID = p_id;
END previsao_salario;
/
 
--CONFERINDO O VALOR ANTERIOR
SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 176;

--ESTA É A CHAMADA
EXECUTE previsao_salario(176,10);

--CONVERINDO O VALOR POSTERIOR
SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 176;

--ABANDOMANDO ALTERAÇÕES
ROLLBACK;

EXEMPLO DE USO DO PARÂMETRO OUT 
--EXEMPLO DO PARAMETRO OUT
CREATE OR REPLACE PROCEDURE QUERY_EMP (p_id     IN  employees.employee_id%TYPE,
                                       p_name   OUT employees.last_name%TYPE,
                                       p_salary OUT employees.salary%TYPE ) IS
BEGIN
  SELECT  last_name, salary
  INTO    p_name,    p_salary
  FROM    employees
  WHERE   employee_id = p_id;
END QUERY_EMP;
/

--CHAMADA DA PROCEDURE EXEMPLO OUT

SET SERVEROUTPUT ON
DECLARE
  v_emp_name employees.last_name%TYPE;
  v_emp_sal  employees.salary%TYPE;
BEGIN
  QUERY_EMP(171,v_emp_name, v_emp_sal);
  DBMS_OUTPUT.PUT_LINE(v_emp_name || ' ganha ' ||
    to_char(v_emp_sal, '$999,999.00'));
END;
/

PARÂMETRO IN OUT

  • O parametro IN OUT pode ser passado um valor para a procedure que pode ser atualizado, ou seja, o valor do mesmo parametro pode ser atualizado durante o processamento nas linhas da procedure;

EXEMPLO DE PARÂMETRO IN OUT

CREATE OR REPLACE PROCEDURE format_phone
(p_phone_no IN OUT VARCHAR2) IS
BEGIN
p_phone_no := '('   || SUBSTR(p_phone_no,1,3) ||
')  ' || SUBSTR(p_phone_no,4,3) ||
'-'   || SUBSTR(p_phone_no,7);
END format_phone;
/

–CHAMADA DA PROCEDURE IN OUT

VARIABLE b_phone_no VARCHAR2(15)
EXECUTE :b_phone_no := '8006330575'
PRINT b_phone_no
EXECUTE format_phone(:b_phone_no)
PRINT b_phone_no

PASSAGEM DE PARAMETROS

  • Quando chamamos um subprograma, você pode escrever os parâmetros atuais usando as seguintes notações:
    • Posicional: lista dos parâmetros atuais na mesma ordem do que os parâmetros formais;
    • Nomeado: Lista dos parâmetros atuais em ordem arbitrária, usando o operador => para associar a nomeação do parâmetro formal com o parâmetro atual;
    • Misto: Lista de alguns parâmetros atuais como posicionais e alguns como nomeados;
  • Antes do Oracle Database 11g, somente a notação posicional era suportada nas chamadas das SQL´s;
  • A partir da versa 11g, notações nomeadas e mistos podem ser usadas para especificar argumentos na chamada para sub-rotinas de declarações do PL/SQL;

–PASSAGEM DE PARAMETRO ATUAIS

CREATE OR REPLACE PROCEDURE add_dept(p_name in  departments.department_name%TYPE,
                                     p_loc  in  departments.location_id%TYPE) IS
BEGIN
  INSERT INTO departments(department_id,
                          department_name,
                          location_id)
  VALUES (departments_seq.NEXTVAL, p_name, p_loc);
END add_dept;


--PASSAGEM DE NOTAÇÃO POSICIONAL
EXECUTE add_dept('TRAINING',2500);

--PASSAGEM DE NOTAÇÃO NOMEADA
EXECUTE add_dept(p_loc=>2400, p_name=>'EDUCATION');

USANDO O PARAMETRO OPCIONAL DEFAULT

  • Define um valor padrão para o parâmetro;
  • Provê flexibilidade por combinação posicional e nomeada na sintaxe da passagem de parâmetros;

ALTERANDO A PROCEDURE add_dept

–PARAMETRO DEFAULT

CREATE OR REPLACE PROCEDURE add_dept
(p_name departments.department_name%TYPE :='Desconhecido',
p_loc  departments.location_id%TYPE DEFAULT 1700 )
IS
BEGIN
INSERT INTO departments  (department_id,
department_name,
location_id)
VALUES (departments_seq.NEXTVAL, p_name, p_loc);
END add_dept;
/

CHAMADA DA PROCEDURE add_dept

--chamando a procedure
EXECUTE add_dept;

EXECUTE add_dept('PROPAGANDA',p_loc=>1200);

EXECUTE add_dept(p_loc=>1200);

--conferindo os dados inseridos
select * from departments;
  • Você pode chamar procedures usando blocos anônimos;
  • Voce precisa ser dono da procedure ou ter privilégio de EXECUTE;

Exercícios

  1. Crie uma bloco nomeado (procedure), que passado 2 parâmetros do tipo number, (o valor do primeiro parâmetro deve ser menor que o segundo) retorne todos os funcionários código, nome concatenado com o sobrenome, salário e departamento que o salário esteja entre esses dois parametros
  2. Crie um bloco nomeado (procedure), que passado um parâmetro do tipo data, retorne o código, sobrenome, nome, data de admissão e departamento de funcionários, onde a data de admissão seja maior ou igual ao parâmetro passado. O parâmetro deve ser uma data válida;
  3. Crie um bloco nomeado (procedure), que passado um parâmetro do tipo string, retorne o código, nome concatenado com o sobrenome dos funcionários, onde a letra do parâmetro deve ser substituída pela string “STAR”; Exemplo: o usuário passa a letra A, todos as letras do nome e sobrenome QUE CONTENHAM A deve ser substituída por STAR.
  4. Crie um bloco nomeado (procedure), que passado um parâmetro do string, retorne o código e nome concatenado com o sobrenome dos funcionários, onde o nome deve ser iniciado com o parâmetro digitado. Deve-se mostrar quantos caracteres tem o nome e separar cada sílaba com o caracter “-“;
  5. Crie um bloco nomeado que não tenha passagem de parâmetros, que faça a inclusão automática de um departamento cada vez que for acionada; Observação: o nome do departamento pode ser concatenado com outro dado para não se repetir (mesmo que o nome não tenha tanto sentido);
  6. Crie um bloco nomeado que passe um parâmetro do tipo inteiro e outro do tipo string, e que esses parâmetros tenham os valores padrão 100 e ‘IP_PROG’, retornando os registros que tenham o employee_id e job_id iguais aos dos parâmetros passados. Caso o usuário passe valor aos parâmetros, é necessário respeitar o valor passado para se ter maior prioridade. Caso não sejam passados, os parâmetros padrões serão utilizados. Arrume a procedure para que pelo menos se tenha um registro retornado caso não seja passado nenhum parâmetro;

 

Referência:
ORACLE DATABASE 11g PL/SQL Programming
Develop Robust, Database-Driven
PL/SQL Application
Michael McLaughlin – Mc Graw Hill

Vídeo 1

Vídeo 2

 

Banco de Dados II – Aula 09

Criando uma table space e usuário no Oracle 11 XE

Necessário entrar com a permissão de system, ou admin diretamente pelo SQL Plus.

Pode-se salvar o arquivo diretamente no diretório home do usuário oracle e executar o script através do SQL Plus*

create tablespace banco1 datafile '/u01/app/oracle/oradata/XE/banco1.dbf' size 10m autoextend on next 5m maxsize 50m online permanent extent management local autoallocate segment space management auto;

create user banco1 identified by banco1 default tablespace banco1 temporary tablespace temp;

grant create session, connect, resource to banco1;

alter user banco1 quota unlimited on banco1; 

connect banco1/banco1;

Até o momento, foi criado a table space chamada de banco1, um usuário banco1 com a senha banco1 e dados permissões de acesso ao usuário banco1

Após a conexão, podemos criar a as tabelas abaixo, fazendo as inserções de dados abaixo como exemplo:

CREATE TABLE DEPTO (
  CDDEPTO CHAR(02) PRIMARY KEY,
  NMDEPTO VARCHAR(30),
  RAMAL NUMBER(3)
);

CREATE TABLE CARGO (
  CDCARGO CHAR(02) PRIMARY KEY,
  NMCARGO VARCHAR(30),
  VRSALARIO NUMBER(8,2)
);

CREATE TABLE FUNCIONARIO (
  NRMATRIC NUMBER(04) PRIMARY KEY,
  NMFUNC   VARCHAR(30),
  DTADM    DATE,
  SEXO     CHAR(01),
  CDCARGO  CHAR(02),
  CDDEPTO  CHAR(02),
  CONSTRAINT FK_FUNC_CDCARGO FOREIGN KEY(CDCARGO) REFERENCES CARGO(CDCARGO),
  CONSTRAINT FK_FUNC_CDDEPTO FOREIGN KEY(CDDEPTO) REFERENCES DEPTO(CDDEPTO)
);


INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C1','COZINHEIRA',350);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C3','AUX ESCRITORIO',450);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C7','VIGIA',450);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C2','MECANICO',750);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C5','GERENTE',2300);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C4','ESCRITURARIO',600);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C8','PROGRAMADOR',NULL);
INSERT INTO CARGO (CDCARGO, NMCARGO, VRSALARIO) VALUES ('C9','ANALISTA_DE_SISTEMAS',2100);
COMMIT;


INSERT INTO DEPTO (CDDEPTO, NMDEPTO, RAMAL) VALUES ('D1','ADMINISTRACAO',221);
INSERT INTO DEPTO (CDDEPTO, NMDEPTO, RAMAL) VALUES ('D2','OFICINA',235);
INSERT INTO DEPTO (CDDEPTO, NMDEPTO, RAMAL) VALUES ('D3','SERVICOS GERAIS',243);
INSERT INTO DEPTO (CDDEPTO, NMDEPTO, RAMAL) VALUES ('D4','VENDAS',258);
COMMIT;


INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1001,'JOAO SAMPAIO','10-AUG-93','M','C2','D2');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1004,'LUCIO TORRES','02-MAR-94','M','C2','D2');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1034,'ROBERTO PEREIRA','23-MAY-92','M','C3','D1');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1021,'JOSE NOGUEIRA','10-NOV-94','M','C3','D1');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1029,'RUTH DE SOUZA','05-JAN-93','F','C1','D3');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1095,'MARIA DA SILVA','03-SEP-92','F','C4','D1');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1023,'LUIZ DE ALMEIDA','12-JAN-93','M','C2','D2');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1042,'PEDRO PINHEIRO','29-JUL-94','M','C4','D1');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1048,'ANA SILVEIRA','01-JUN-93','F','C5','D1');
INSERT INTO FUNCIONARIO (NRMATRIC, NMFUNC, DTADM, SEXO, CDCARGO, CDDEPTO) 
	VALUES (1015,'PAULO RODRIGUES','17-AUG-92','M','C2','D2');
COMMIT;

OBJETOS DO ORACLE

TABELA: tem a principal função armazenar dados;

VIEW: objeto que encapsula uma instrução select, podendo ter uma ou mais tabelas;

SEQUENCE: Gera uma sequencia numérica;

INDICE: Utilizado para melhorar a performance em consultas;

SINONIMO: apelido para objetos de dados;

TABELAS

É possível fazer a criação online;

Após ter sido criada, é possível modificar a sua estrutura;

Importante ter uma estimativa de tamanho para evitar que o banco de dados trave;

Nomes devem ter até 30 caracteres, começando com uma letra;

Nomes das tabelas podem ser: a-z, A-Z, 0-9, _ (underline);

Os caracteres # e $ podem também serem utilizados em nomes de tabelas, porém não recomendados pela Oracle;

É possível ter nomes iguais de objetos desde que sejam de usuários diferentes;

Não se deve utilizar palavras reservadas do Oracle (CREATE, TABLE, ALTER, USER, INSERT, etc);

Em tabelas, não há case-sensitive;

CREATE TABLE

Para se criar tabelas, é necessário que o usuário conectado tenha privilégios ;

CREATE TABLE CLIENTES (
  COD_CLI NUMBER(5),
  NOME_CLI VARCHAR2(30)
);

TIPOS DE DADOS

As colunas de uma tabela precisa ser definida com um tipo de dados, pois será tratado posteriormente pelo banco de dados;

VARCHAR2: utilizado para armazenar tipos de caracteres alfa-numéricos (aceitando letras e números), podendo ser definido de 1 a 4000 caracteres; A quantidade de bytes utilizada é da quantidade de caracteres + 1 (especifica o tamanho da string)

CHAR: permite armazenar caracteres alfa-numéricos, podendo ser definido de 1 a 2000 caracteres, com tamanho fixo (exemplos: CPF, CEP, CNPJ);

NUMBER: permite armazenar números inteiros ou decimais (precisão e escala m,n), que varia de 1 a 38. Exemplo NUMBER(10,2), pode armazenar 8 inteiros e 2 decimais;

DATE: permite armazenar data e hora que pode variar de 01/01/4712 AC até 31/12/9999 DC;

LONG: permite armazenar caracteres de até 2 GB (evite usar LONG – somente para compatibilidades passadas). Utilize LOB;

CLOB: permite armazenar caracteres de até 4 GB;

RAW(tamanho): permite armazenar dados binários brutos;

LONG RAW: armazena dados binários de tamanho variável de até 2 GB;

BLOB: Dados binários de até 4 GB;

BFILE: Armazena arquivos binários em arquivos externos ao banco de dados de até 4 GB;

ROWID: permite armazenar o endereço físico exclusivo de uma linha em uma tabela correspondente. Toda a tabela tem um ROWID, controlado pelo ORACLE. Pode-se acessar executando SELECT ROWID;

LONG: O tipo de dados LONG não pode ser copiado para outra tabela através de uma subquery; A coluna LONG não pode ser incluída no GROUP BY ou ORDER BY; É limitado a 1 coluna LONG por tabela; Não pode ser definida como CONSTRAINTS; Utilize CLOB em vez de LONG;

TIMESTAMP: É uma extensão do tipo DATE, armazenando até o segundo e fração de segundos;Pode especificar o fuso horário;
Exemplo:
TIMESTAMP WITH LOCAL TIME ZONE;
TIMESTAMP WITH TIME ZONE;

INTERVAL YEAR TO MONTH: É usado para armazenar diferença entre dois valores de datas/horários, levando-se em conta somente o mês e o ano;
Exemplo:
INTERVAL ’12-5’ YEAR(2) TO MONTH;
Grava um intervalo de doze anos e cinco meses;

INTERVAL YEAR TO MONTH
Exemplo:
INTERVAL ’231’ MONTH(2);
Grava um intervalo de 231;

INTERVAL ’543’ YEAR; Retorna erro, pois não foi definido o ano e o padrão para ano são de 2 dígitos;

INTERVAL DAY TO SECOND: armazena um período em dias, horas, minutos e segundos
Exemplo:
INTERVAL ’2 3:20:10.222’ DAY TO SECOND(3);
Grava 2 dias, 3 horas, 20 minutos, 10 segundos e 222 milhares de segundo;

INTERVAL ’7 5:12’ DAY TO MINUTE;
Grava 7 dias, 5 horas e 12 minutos;
Exemplo:
INTERVAL ’235 5 DAY(3) TO HOUR;
Grava 235 dias e 5 horas;

INTERVAL ’11:12:10.2222222’ HOUR TO SECOND(7);
Grava 11 horas, 12 minutos e 10,2222222 segundos;

EXEMPLOS DE CRIAÇÃOD DE TABELA USANDO OS TIPOS DE DADOS

CREATE TABLE TESTE_DADOS (
  CODIGO      NUMBER(10),
  NOME        VARCHAR(30),
  CEP         CHAR(8),
  NASCIMENTO DATE,
  SALARIO     NUMBER(10,2)
);

INSERT INTO TESTE_DADOS (CODIGO, NOME, CEP, NASCIMENTO, SALARIO)
VALUES
(1,'TESTE DE NOME','12548963',TO_DATE('07/15/2010','MM/DD/YYYY'),1501.45);

SELECT * FROM TESTE_DADOS;

CREATE TABLE TESTE_TABELA (
  HORA_ATUAL TIMESTAMP(7)
);

INSERT INTO TESTE_TABELA(HORA_ATUAL)
VALUES (SYSDATE);

SELECT * FROM TESTE_TABELA;

CREATE TABLE TABELA_INTERVALOS(
  INTERVALO_ANO INTERVAL YEAR(3) TO MONTH,
  INTERVALO_DIA INTERVAL DAY(3) TO SECOND
);

INSERT INTO TABELA_INTERVALOS(INTERVALO_ANO, INTERVALO_DIA)
VALUES (INTERVAL '120' MONTH(3),
        INTERVAL '180' DAY(3)
);

SELECT INTERVALO_ANO, INTERVALO_DIA
FROM TABELA_INTERVALOS;

SELECT TO_CHAR(SYSDATE+INTERVALO_ANO,'DD-MON-YYYY'),
               SYSDATE+INTERVALO_DIA AS intervalo_dia
FROM TABELA_INTERVALOS;

CONSTRAINTS

São regras que são impostas no nível de tabela (ou coluna), que no geral, impedem a inserção, atualização e deleção de dados indevidos;

As mais importantes são: NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK;

Sempre que possível, nomeie as CONSTRAINS. Caso não, o ORACLE dá o nome à constraint de “SYS_…”;

Aconselhável criar as constraints logo na criação da tabela, porém podem ser criadas posteriormente;

Podem ser definidas em nível de tabela ou coluna;

CONSTRAINT NOT NULL

Serve para que uma determinada coluna não tenha valores nulos;
Por padrão, as colunas são NULL;
EXEMPLO:
CREATE TABLE NOME_TABELA(
NOME_COL TIPO_COL NOT NULL
);

CONSTRAINT UNIQUE

Serve para que uma determinada coluna (ou colunas) tenha valores únicos, podendo ter valores nulos;

As PRIMARY KEYS implicitamente são UNIQUE;

CONSTRAINT PRIMARY KEY

Serve para que uma coluna (ou colunas) tenham valores diferente entre tuplas, sendo valores únicos e não nulos;
É limitada a ser criado uma única PK por tabela, que pode ter várias colunas (todas as colunas precisam ser não nulas);
É automaticamente criado um índice, para melhor pesquisar os registros;

CONSTRAINT FOREIGN KEY

Serve para garantir a integridade dos relacionamentos entre as tabelas;
Para ser criada, é necessário ter uma PK ou UNIQUE de outra tabela;
Pode-se utilizar os comandos abaixo para se fazer exclusão de dados em cascata:
ON DELETE CASCADE;
ON DELETE SET NULL;

CONSTRAINT CHECK

Serve para fazer a checagem de um determinado dado antes da ação na tabela;
Algumas das expressões NÃO podem ser utilizadas com CHECK: SYSDATE, UID, USER e USERENV, ou a pseudocolunas como: CURRVAL, NEXTVAL, LEVEL e ROWNUM e consultas que fazem referencia a outros valores em outra linhas;

EXEMPLOS:

–nivel coluna

CREATE TABLE EMPREGADOS (
COD NUMBER(6) CONSTRAINT COD_EMP_PK PRIMARY KEY,
NOME VARCHAR2(30)
);

EXEMPLO:

–nivel tabela

CREATE TABLE EMPREGADOS (
COD NUMBER(6),
NOME VARCHAR2(30),
CONSTRAINT COD_EMP_PK PRIMARY KEY(COD)
);


CREATE TABLE TABELA_CONSTRAINTS (
ID NUMBER(10),
COD_EMP NUMBER(10),
NAO_NULO NUMBER(10) NOT NULL,
COLUNA_UNICA DATE,
COLUNA_CHECK NUMBER(10,2),
CONSTRAINT ID_PK PRIMARY KEY(ID),
CONSTRAINT UK_UNIQUE01 UNIQUE(COLUNA_UNICA),
CONSTRAINT FK_COD_EMP FOREIGN KEY(COD_EMP)
REFERENCES EMPLOYEES(EMPLOYEE_ID) ON DELETE CASCADE,
CONSTRAINT CK_COL01 CHECK (COLUNA_CHECK > 10)
);

INSERT INTO TABELA_CONSTRAINTS VALUES (10,100, NULL, NULL,10);

INSERT INTO TABELA_CONSTRAINTS VALUES (10,100, 10, NULL,10);

INSERT INTO TABELA_CONSTRAINTS VALUES (10,100, 3,TO_DATE('15/10/2015','DD/MM/YYYY') ,11);

SELECT * FROM TABELA_CONSTRAINTS;

CONSTRAINTS DEFAULT

Define um valor padrão de uma coluna quando não for especificado nenhum valor (null implícito);
Pode ser usado funções de linhas como SYSDATE e o USER;
Não pode usar o nome de outra coluna como referencia;
O valor padrão precisa ter o mesmo tipo da coluna;

EXEMPLO DE DEFAULT

CREATE TABLE TESTE_DEFAULT (
ID NUMBER(10),
DATA DATE DEFAULT SYSDATE
);

INSERT INTO TESTE_DEFAULT (ID) VALUES (1);
INSERT INTO TESTE_DEFAULT (ID) VALUES (2);
INSERT INTO TESTE_DEFAULT (ID) VALUES (3);
INSERT INTO TESTE_DEFAULT (ID) VALUES (4);
INSERT INTO TESTE_DEFAULT (ID) VALUES (5);

SELECT * FROM TESTE_DEFAULT

CRIANDO UMA TABELA COM UMA SUBQUERY

Serve para criar rapidamente uma tabela com dados selecionado pela query;
Quando se tem expressões, é obrigatório o uso de alias;

EXEMPLO DE CREATE SELECT

CREATE TABLE TESTE_SUBSELECT AS
SELECT EMPLOYEE_ID, FIRST_NAME, HIRE_DATE, SALARY * 12 AS SAL
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 90;

DESC TESTE_SUBSELECT;

ALTER TABLE

Serve para fazer manutenção em tabelas já existentes, podendo modificar colunas, criar novas colunas, eliminar colunas, adicionar valor default às colunas;

EXEMPLO ALTER TABLE

ALTER TABLE TESTE_DEFAULT
ADD NOME_USER VARCHAR2(30);

UPDATE TESTE_DEFAULT SET NOME_USER = USER;

SELECT * FROM TESTE_DEFAULT;

ALTER TABLE TESTE_DEFAULT
MODIFY NOME_USER VARCHAR2(20) NOT NULL;

ALTER TABLE TESTE_DEFAULT
RENAME COLUMN NOME_USER TO NOME_USER2;

ALTER TABLE TESTE_DEFAULT
RENAME TO TESTE_DEFAULT2

SELECT * FROM TESTE_DEFAULT2

DROP TABLE

Serve para eliminar uma tabela com todos os seus dados e índices;
Após ser executado, transações pendentes são submetidos a um COMMIT, efetivando as transações;

EXEMPLO DE DROP TABLE

DROP TABLE TESTE_DEFAULT2

EXERCICIOS

Faça um script que contenha a criação de uma tablespace (schema), usuário para o schema criado, associação do usuário com o schema, chamando a tablespace de banco999 e o usuário de banco999, fazendo com que o usuário banco999 seja dono de outros objetos criados;

Crie os seguites objetos dentro desse schema:

ScreenHunter_519 Apr. 23 14.00

Posteriormente faça as seguintes inserções de dados:

ScreenHunter_520 Apr. 23 14.00

Video 1

 
Video 2

learningdatabase.com.br

Tecnologias em Banco de Dados Relacionais, Modelagem de dados dimencionais, tecnologias SQL Servere e Oracle

Aprendendo Programação

Algorítmos, C, C++,Pascal, Python, R

WikiDBA

by Virendra Yaduvanshi - Microsoft SQL Server Database Architect | Consultant | Blogger | Specialist | DBA | Speaker

Blog - Fabiano Neves Amorim

SELECT * FROM [Coisas Da Minha Cabeça] WHERE dbo.fn_TempoParaPost() < dbo.fn_TempoLivre()

Tércio Costa, Oracle Developer, OCE SQL, ACE Associate

Guia de estudos para certificação ORACLE SQL(1Z0-047, 1Z0-051, 1Z0-061 e 1Z0-071) e PL/SQL(1Z0-144, 1Z0-146 e 1Z0-148)

Strate SQL

Data Adventures with an Architect