Arquivos de Categoria: Oracle

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

 

 

 

 

Anúncios

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 10

VIEWS

  • É um objeto lógico que se baseia em uma SELECT, armazenado no banco de dados;
  • Pode ser simples (apenas utilizando uma tabela) ou complexa (podendo ter vários relacionamentos e tipos de joins, grupos, funções de grupo, etc);
  • Podem ter colunas virtuais;
  • Pode fazer restrição de dados (não colocando a coluna desejada na SELECT)
  • Em Views simples, podemos executar comandos DML (insert, update, delete);
  • Em Views complexas, na maioria dos casos, não é possível executar comandos DML (possuem funções, grupos);
  • Recomendado fazer toda a SELECT primeiramente para depois ser encapsulada na VIEW;
  • Sintaxe: CREATE [OR REPLACE] VIEW nome_da_view AS SELECT …
  • Quando utilizado o REPLACE, caso já tenha uma VIEW com o mesmo nome, a mesma irá ser sobrescrita;
  • Com o parâmetro FORCE, pode-se criar a VIEW sem ter necessariamente as tabelas físicas no banco de dados. (na execução, irá dar erro);
  • Com o parâmetro NOFORCE (padrão), pode-se criar a VIEW com tabelas existentes no banco de dados;
  • Com o parâmetro WITH CHECK OPTION, apenas as linhas retornadas na VIEW podem ser alteradas;
  • Com o parâmetro WITH READ ONLY, somente pode ser executada a VIEW sem a possibilidade de executar comandos DML;

EXEMPLOS:

CREATE OR REPLACE VIEW VW_SALARIO_PROG AS
SELECT  EMPLOYEE_ID,
        FIRST_NAME,
        LAST_NAME,
        SALARY * 13 AS SAL_CLT_ANUAL
FROM    EMPLOYEES
WHERE   JOB_ID = 'IT_PROG';

–MOSTRANDO A ESTRUTURA

DESC VW_SALARIO_PROG;

–EXECUTANDO A VIEW

SELECT *
FROM VW_SALARIO_PROG;

EXEMPLO 2

CREATE OR REPLACE VIEW VW_SALARIO_PROG (CODIGO,NOME,SOBRENOME,SALARIO_ANUAL) AS
SELECT  EMPLOYEE_ID,
        FIRST_NAME,
        LAST_NAME,
        SALARY * 13 AS SAL_CLT_ANUAL
FROM    EMPLOYEES
WHERE   JOB_ID = 'IT_PROG';

VIEWS COMPLEXAS

  • As VIEWS complexas geralmente possuem relacionamento com duas ou mais tabelas (Compostas de queries complexas);
  • Na maioria das vezes, não é possível executar instruções DML;
  • Quando a select possui funções de grupo, GROUP BY, DISTINCT, ROWNUM, Expressões (colunas virtuais), colunas NOT NULL não retornadas na VIEW, NÃO podemos executar comandos DML;
  • O parâmetro WITH CHECK OPTION é possível executar instruções INSERT e UPDATE, somente com as linhas que a view pode retornar;
  • Também serve para evitar que os dados seja deletados da tabela, sendo somente deletados pela VIEW que possui o WITH CHECK OPTION;
  • O parâmetro WITH READ ONLY cria uma VIEW que não será possível executar nenhuma instrução DML, sendo somente executada para leitura de dados;
  • DROP VIEW faz a eliminação da view do banco de dados;

EXEMPLO:

CREATE VIEW SALARIOS_FUNC(FUNCAO, MIN_SALARIO, MAX_SALARIO, MED_SALARIO)
AS
SELECT B.JOB_TITLE,
       MIN(A.SALARY),
       MAX(A.SALARY),
       AVG(A.SALARY)
FROM   EMPLOYEES A
       NATURAL JOIN JOBS B
GROUP BY B.JOB_TITLE;

 
SELECT *
FROM SALARIOS_FUNC;

SELECT * FROM DEPARTMENTS;

CREATE OR REPLACE VIEW VW_DEPTO_60
AS
SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 60
WITH CHECK OPTION CONSTRAINT CK_DEPTO_60;


SELECT *
FROM VW_DEPTO_60;


--IRA ATUALIZAR
UPDATE VW_DEPTO_60
SET SALARY = SALARY + 1
WHERE DEPARTMENT_ID = 60;

SELECT * FROM VW_DEPTO_60;

 

--NAO IRÁ ATUALIZAR
UPDATE VW_DEPTO_60
SET DEPARTMENT_ID = 20
WHERE EMPLOYEE_ID = 103;

 

CREATE OR REPLACE VIEW VW_DEPTO_20 (ID, NOME, CARGO)
AS
SELECT EMPLOYEE_ID,
       FIRST_NAME,
       JOB_ID
FROM   EMPLOYEES
WHERE  DEPARTMENT_ID = 20
WITH READ ONLY;


SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 20;


DELETE FROM VW_DEPTO_20
WHERE ID = 202;

ÍNDICES

  • Índice serve para que dados sejam organizados para melhorar o processo de procura em tabelas;
  • É um dos objetos do banco de dados, que pode ser criado pelo usuário ou pelo Oracle;
  • Para campos do tipo Primary Key ou Unique, as chaves são criadas automaticamente pelo Oracle;
  • Os índices ocupam mais espaço no banco de dados, sendo marcadores que permitem que os dados sejam acessados rapidamente;
  • Pode-se criar ou eliminar índices em uma tabela a qualquer momento;
  • Quando uma tabela é excluída, todos os índices dessa tabela também é excluída;
  • Os índices exclusivos são criados exclusivamente pelo Oracle, quando definimos as colunas PRIMARY KEY ou UNIQUE. Podem ser criados manualmente, mas é recomendado que o Oracle faça esse gerenciamento;
  • Índices NÃO EXCLUSIVOS são criados pelos usuários, a qual tem a finalidade de aumentar a performance das consultas;
  • Os índices exclusivos são criados exclusivamente pelo Oracle, quando definimos as colunas PRIMARY KEY ou UNIQUE. Podem ser criados manualmente, mas é recomendado que o Oracle faça esse gerenciamento;
  • Índices NÃO EXCLUSIVOS são criados pelos usuários, a qual tem a finalidade de aumentar a performance das consultas;
  • Um índice pode ter mais de uma coluna;
  • A ordem das colunas influenciam na performance do retorno das linhas;
  • A utilização correta dos índices influencia também na performance de retorno das linhas (duas ou mais colunas);

SINTAXE:

CREATE INDEX NOME_INDICE ON NOME_TABELA(COLUNA1, ...);

DROP INDEX NOME_INDICE;
  • Aconselhável criar um índice quando:
    • Quando NÃO existirem muitos valores nulos na coluna consultada;
    • Quando as colunas forem muito utilizadas na cláusula WHERE;
    • Quando o retorno de registros representa em torno de 2% a 4% (para tabelas com grande quantidade de registros);
    • Colunas que possuem faixas de valores, como datas (que são utilizadas no WHERE);
  • Aconselhável a NÃO criar um índice quando:
    • Quando a tabela sofre comandos DML frequentemente (por exemplo, quando registros são inseridos, todos os índices da tabela também precisarão ser atualizados);
    • Tabelas com poucos registros;
    • Quando o retorno de registros na maioria das consultas equivalerem a menos de 4% dos registros;
  • Sempre que criar índices, é necessário avaliar se haverá mais consultas ou mais inserções/atualizações na tabela;

Exemplo:

CREATE INDEX IDX_PRIMEIRONOME ON EMPLOYEES(FIRST_NAME);
SELECT *
FROM EMPLOYEES
WHERE FIRST_NAME = 'Valli';

DROP INDEX IDX_PRIMEIRONOME;

CREATE INDEX IDX_PRIMEIROSEGUNDONOME ON EMPLOYEES (FIRST_NAME,LAST_NAME);

SELECT *
FROM EMPLOYEES
WHERE FIRST_NAME = 'Bruce';


SELECT *
FROM EMPLOYEES
WHERE FIRST_NAME = 'Bruce'
AND LAST_NAME = 'Ernst';
 

DROP INDEX IDX_PRIMEIROSEGUNDONOME;

SEQUENCES

  • Sequence é um dos objetos utilizados para armazenamento de números sequenciais em uma determinada ordem definida na sua criação;
  • Geralmente, é utilizado na criação de PRIMARY KEYS, em número sequenciais;
  • A utilização desse recurso garante que as chaves primárias não se repetirão;
  • É um objeto independente de qualquer tabela;
  • Geralmente, é associado a uma tabela para seguir uma sequencia, porém nada impede de ser utilizado em mais de uma tabela;
  • A sintaxe de criação da SEQUENCE é:
CREATE SEQUENCE NOME_SEQUENCE INCREMENT BY QUANTIDADE

[MAXVALUE VALOR_MAXIMO]
[MINVALUE VALOR_MINIMO]
[CYCLE]
[CACHE QUANTIDADE];
  • O incremento padrão é de 1 em 1;
  • O parâmetro CYCLE é utilizado quando a numeração chega ao valor máximo (maxvalue) e o número é reiniciado novamente;
  • O padrão na criação da SEQUENCE é NOCYCLE;
  • O parâmetro CACHE já define uma determinada quantidade de números reservados, para que seja mais rápido a utilização das sequencias (mais performance). O padrão é quantidade de 20;
  • Quando utilizamos SEQUENCES, podemos utilizar as pseudocolunas NEXVAL, que retorna o próximo número disponível da sequencia; Mesmo que tenha várias sessões diferentes utilizando a mesma sequence (ainda em transação), o valor nunca se repete;
  • Quando utilizamos SEQUENCES, podemos utilizar as pseudocolunas CURRVAL, que retorna o valor atual da sequence daquela seção; Só irá funcionar depois de ter utilizado o NEXTVAL na mesma sessão;
  • O Oracle não sabe qual é o valor corrente da sessão antes de ter executado o NEXTVAL;
  • Para se utilizar o NEXTVAL e CURRVAL:
    • Pode ser utilizada em uma SELECT, a menos que ela seja uma subquery;
    • Pode ser utilizada no comando VALUES do INSERT;
    • Pode ser utilizada no comando SET do UPDATE;
    • No SELECT de uma subquery para realizar um INSERT;
  • NÃO se pode utilizar o NEXTVAL e CURRVAL:
    • Em um SELECT em uma VIEW;
    • Em um SELECT, com DISTINCT, ORDER BY, GROUP BY ou HAVING;
    • Em uma coluna definida com o valor DEFAULT;
    • Em uma subquery em um DELETE, UPDATE ou em um SELECT;
  • Quando utilizamos o parâmetro CACHE QUANTIDADE, o Oracle coloca em cache essa quantidade para que se tenha mais performance na utilização da sequence. O padrão é com a quantidade de 20;
  • É indicado quando se tem tabelas que sofram grande quantidade de inserções de dados;
  • Depois que a sequence é gerada, o numero não é reaproveitado.
  • As sequences são geradas independentes que a transação termine com COMMIT ou ROLLBACK;
  • Falhas no sistema do Oracle também podem perder os valores que estão no cache;
  • Quando utilizamos uma sequence para várias tabelas, os números não irão ser sequencias para as tabelas utilizadas;
  • Podemos utilizar o comando ALTER e DROP para se fazer alteração e exclusão da sequence respectivamente;
  • Quando alteramos uma sequence, apenas os próximos números são alterados;
  • Não é possível alterar o START WITH de uma sequence, porém pode-se dar drop e create novamente;
  • Apenas quem tem permissão de DROP ANY SEQUENCE e o dono podem alterar as sequences;

EXEMPLOS:

CREATE TABLE TESTE_SEQUENCIA (
  CODIGO NUMBER(10) NOT NULL PRIMARY KEY,
  NOME   VARCHAR(30)
);

DESC TESTE_SEQUENCIA;

SELECT * FROM TESTE_SEQUENCIA;

CREATE SEQUENCE SQ_TESTE_01
INCREMENT BY 10
START WITH 100
MAXVALUE 300
NOCACHE
NOCYCLE;

–UTILIZANDO O NEXVAL

INSERT INTO TESTE_SEQUENCIA (CODIGO, NOME)
VALUES (SQ_TESTE_01.NEXTVAL, 'SAITO');

--VERIFICANDO O VALOR INSERIDO NA TABELA
SELECT SQ_TESTE_01.CURRVAL FROM DUAL;
SELECT * FROM TESTE_SEQUENCIA;

INSERT INTO TESTE_SEQUENCIA (CODIGO, NOME)
VALUES (SQ_TESTE_01.NEXTVAL, 'ANCHIETA');

--VERIFICANDO O VALOR DA SEQUENCE
SELECT SQ_TESTE_01.CURRVAL FROM DUAL;

--ELIMITANDO UMA SEQUENCE
DROP SEQUENCE SQ_TESTE_01;

SINONIMOS

  • SINONIMO é um dos objetos utilizados para se fazer referencia a outro objeto. Geralmente, grande nomes de tabelas podem ser referenciadas com um nome menor ou referencia a objetos de outros usuários podem ser feitos acessos mais facilmente;
  • Sinônimo público pode ser acesso por qualquer usuário e o sinônimo privado pode ser acesso somente pelo seu criador;
  • Os sinônimos não podem acessar objetos que estão dentro de uma PACKAGE;
  • Para sinônimos privados, o nome deve ser único, diferente de outros objetos deste mesmo usuário;

SINTAXE:

CREATE SYNONYM NOME_SINONIMO
FOR NOME_OBJETO

DROP SYNONYM NOME_SINONIMO

EXEMPLOS:

--com erro, pois o usuário hr nao terá privilégio
CREATE PUBLIC SYNONYM TESTE_SIN FOR TESTE_TABELA ;

--excluindo o sinonimo publico
DROP PUBLIC SYNONYM TESTE_SIN;

--criacao do sinonimo privado
CREATE SYNONYM TESTE_SIN FOR TESTE_TABELA;

SELECT * FROM TESTE_SIN;

--excluindo do sinonimo
DROP SYNONYM TESTE_SIN;

Exercícios

  1. Crie uma View chamada VW_EMPREGADOS_DEPTOS, que mostre os dados da tabela employees, tendo os campos código, nome e sobrenome concatenado (espaço entre eles), e email, onde os JOB_IDS sejam IT_PROG e PU_CLERK;
  1. Prove se é possível fazer inserção de dados através da view criada no exercício 1; Explique o porque de conseguir ou não conseguir;
  1. Crie uma view chamada VW_EMPREGADOSPORTEMPO, CONTENDO o código do empregado, nome, data de admissão que estejam admitidos entre os damos de 2003 e 2005. Crie com o parâmetro WITH CHECK OPTION;
  1. Insira 3 linhas de dados pela view criada no exercício 3, e explique se você conseguiu inserir ou não esses dados;
  1. Crie uma view chamada EMPREGADOS_DEP, que utilize uma tabela com a seguinte estrutura: DEPENDENTES(EMPLOYEE_ID NUMBER(6), COD_DEP NUMBER(2), NOME_DEP VARCHAR(30), DATA_NASC DATE), onde EMPLOYEE_ID E COD_DEP são chaves primárias. A visão deve conter o código de dependente, o nome e a data de nascimento do dependente. Atenção: A tabela ainda não existe. NÃO CRIE A TABELA. Utilize o parâmetro correto para se fazer a view;
  1. Crie uma sequence chamada SQ_NUMERO_DEP, iniciando pelo numero 10, incremento de 5 em 5, tamanho mínimo 10, tamanho máximo de 500, com 30 números em cache;
  1. Crie a tabela dependentes do exercício 5, e faca a inserção de 5 dependentes, utilizando a sequence do exercício 6;
  1. Crie um índice chamado IDX_DEP_NOME na tabela dependentes, no campo NOME_DEP;

Video

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

Banco de Dados II – Aula 06

SUBQUERIES

  • Subqueries são divisões de uma instrução SELECT, a qual estarão separados entre parentes;
  • Servem geralmente para resolver problemas que teriam que ser feitas com 2 consultas;
  • Também utilizada quando um resultado encontrado é base de condição para uma outra consulta;
  • A ordem de execução da SUBQUERY depende de como ela é escrita;
  • Para as SUBQUERIES mais simples, são executadas as mais internas para depois ser executado a mais externa. Esse tipo de subquerie também é conhecida como NÃO-CORRELACIONADA;
  • Há também SUBQUERIES quer dependem tanto da query externa quando interna para ser executada.
  • É quando existe um relacionamento entre as QUERIES, ou seja, para cada linha da query mais externa, depende do resultado de uma linha (ou mais) de uma query mais interna. É também chamada de CORRELACIONADA;
  • Não é necessário utilizar order by em queries mais internas;
  • As subconsultas devem estar entre parênteses;
  • Tome cuidado com subconsultas que retornam várias linhas utilizando operadores que suporte somente uma única linha;
  • Exemplo de um problema que exigiria 2 consultas:
    • Qual(is) funcionário(s) que ganham igual ou mais que o funcionário Bruce do departamento 60?
SELECT    FIRST_NAME,
          SALARY,
          DEPARTMENT_ID
FROM      EMPLOYEES
WHERE     DEPARTMENT_ID = 60;
  • No método tradicional, primeiro precisamos saber o quanto o funcionário Bruce ganha:
SELECT  FIRST_NAME,
        SALARY,
        DEPARTMENT_ID
FROM      EMPLOYEES
WHERE   FIRST_NAME = 'Bruce';
  • Depois de encontrar o valor do salário de Bruce, colocamos o valor na cláusula SELECT:
SELECT    FIRST_NAME,
          SALARY,
          DEPARTMENT_ID
FROM      EMPLOYEES
WHERE     SALARY >= 6000
          AND DEPARTMENT_ID = 60;
  • Podemos resolver da seguinte forma:
SELECT    FIRST_NAME,
          SALARY,
          DEPARTMENT_ID
FROM      EMPLOYEES
WHERE     DEPARTMENT_ID = 60
          AND SALARY >= (SELECT  SALARY
                         FROM    EMPLOYEES
                         WHERE   FIRST_NAME = 'Bruce');

TIPOS DE SUBQUERIES

  • Subqueries podem retornar uma única linha, várias linhas e várias colunas;
  • Quando a subquerie retorna uma única linha, podemos utilizar os operadores =, <, >, <>, <= ou >=;
  • Quando a subquerie retorna várias linhas, temos que utilizar o IN, ALL ou ANY (uma ou mais linhas)
  • As subqueries (internas) podem também utilizar funções de grupo (min, max, avg, …), com isso, a subquerie retornará um única linha;
  • Subqueries são recursos poderosos do comando SELECT, que basicamente podemos ter retornar qualquer informação do banco de dados;
  • Basicamente, é possível utilizar subquerie em qualquer cláusula de uma SELECT;
  • Caso a subconsulta não retorna registros, nenhum valor será retornado para toda a SELECT;

EXEMPLO 1:

SELECT  FIRST_NAME, JOB_ID,SALARY,
        DEPARTMENT_ID
FROM    EMPLOYEES
WHERE   JOB_ID =     (SELECT JOB_ID
                      FROM EMPLOYEES
                      WHERE EMPLOYEE_ID = 111)
        AND SALARY > (SELECT SALARY
                      FROM   EMPLOYEES
                      WHERE  EMPLOYEE_ID = 110);

EXEMPLO 2:

SELECT  FIRST_NAME, JOB_ID,SALARY,
        DEPARTMENT_ID
        FROM    EMPLOYEES
        WHERE   JOB_ID      = (SELECT JOB_ID
                               FROM EMPLOYEES
                               WHERE EMPLOYEE_ID = 111)
                AND SALARY <= (SELECT SALARY
                               FROM   EMPLOYEES
                               WHERE  EMPLOYEE_ID = 110);

EXEMPLO 3

SELECT  FIRST_NAME,         JOB_ID,
        SALARY,         DEPARTMENT_ID
FROM    EMPLOYEES
WHERE   SALARY =  (SELECT MIN(SALARY)
                   FROM   EMPLOYEES);

EXEMPLO 4:

SELECT   JOB_ID, AVG(SALARY)
FROM     EMPLOYEES
GROUP BY JOB_ID
HAVING   AVG(SALARY) = (SELECT  MIN(AVG(SALARY))
                        FROM   EMPLOYEES
                        GROUP BY JOB_ID);

EXEMPLO 5 (ERRO)

SELECT  EMPLOYEE_ID, LAST_ANME
FROM    EMPLOYEES
WHERE   SALARY = (SELECT MIN(SALARY)
                  FROM    EMPLOYEES
                  GROUP BY DEPARTMENT_ID);

EXEMPLO 6 (RETORNO NULO)

SELECT  EMPLOYEE_ID, LAST_NAME
FROM    EMPLOYEES
WHERE   COMMISSION_PCT = (SELECT COMMISSION_PCT
                          FROM    EMPLOYEES
                          WHERE FIRST_NAME = 'Santiago');

SUBQUERIES DE VÁRIAS LINHAS

  • Quando temos em uma Subquerie que retorna várias linhas, temos que verificar qual o operador que podemos utilizar. O operador precisa ser compatível com a quantidade de retorno;
  • Quando temos essa situação, temos que utilizar os operadores IN, ANY e ALL;

EXEMPLO DE IN

SELECT  JOB_ID, FIRST_NAME, SALARY
FROM    EMPLOYEES
WHERE   SALARY IN (SELECT MIN(SALARY)
                   FROM EMPLOYEES
                   GROUP BY JOB_ID)
ORDER BY JOB_ID;

EXEMPLO DE ANY

SELECT    EMPLOYEE_ID,   FIRST_NAME,
          JOB_ID, SALARY
FROM    EMPLOYEES
WHERE   SALARY < ANY (SELECT SALARY
                      FROM EMPLOYEES
                      WHERE JOB_ID = 'IT_PROG')
        AND JOB_ID <> 'IT_PROG'
ORDER BY SALARY DESC;

EXEMPLO DE ALL

SELECT    EMPLOYEE_ID,   FIRST_NAME,
          JOB_ID,   SALARY
FROM      EMPLOYEES
WHERE     SALARY > ALL (SELECT SALARY
                        FROM EMPLOYEES
                        WHERE JOB_ID = 'IT_PROG')
              AND JOB_ID <> 'IT_PROG'
ORDER BY SALARY DESC;

OPERADORES DE CONJUNTO

  • São utilizados geralmente para se fazer a união de duas ou mais queries
  • Trará um único resultado da consulta obtida;
  • Geralmente, precisam ser compatíveis os tipos e quantidade de colunas;
  • Podemos utilizar os seguintes comandos de operadores de conjunto: UNION, UNION ALL, INTERSECT, MINUS;

UNION: Retorna todas as linhas distintas das consultas que estarão envolvidas, precisando ter quantidade de colunas e tipos iguais; UNION ALL: Retorna todas as linhas (inclusive as duplicadas) das consultas que estarão envolvidas, precisando ter quantidade de quantidade de colunas e tipos iguais; Se possível, utilize o UNION ALL ao invés de UNION, pois ele tem mais performance no retorno de dados;

INTERSECT: Retorna todas as linhas das consultas que estarão envolvidas, presentes em ambas consultas (ou demais consultas); MINUS: Retorna todas as linhas que estão na primeira consulta que não estão na segunda consulta;

ORDEM DE EXECUÇÃO DOS OPERADORES

  • Para o ORACLE, não há um operador que tenha prioridade de primeira execução;
  • A ordem padrão de execução é de cima para baixo;
  • A ordem de execução pode ter colocação de prioridade colocando parênteses;

UNION

  • Retorna o resultados de duas ou mais consultas, eliminando resultados repetidos;
  • A repetição de resultados é considerada toda a tupla;
  • Os tipos de dados e quantidade de colunas devem ser os mesmos entre as queries;
  • Não é necessário ter o mesmo nome de colunas entre as queries;
  • Valores duplicados não serão ignorados (o comando irá retirar valores repetidos)
  • O operador IN é executado antes do operador UNION;
  • Será feito um ORDER BY automático da primeira coluna;

EXEMPLO DE UNION

SELECT  EMPLOYEE_ID, JOB_ID
FROM    EMPLOYEES
UNION
SELECT  EMPLOYEE_ID, JOB_ID
FROM    JOB_HISTORY;

UNION ALL

  • Retorna o resultados de duas ou mais consultas, INCLUSIVE resultados repetidos;
  • Possui as mesmas diretivas do UNION;
  • NÃO ordena o resultado pela primeira coluna;
  • O operador DISTINCT não pode ser utilizado;
  • O retorno é mais rápido que a utilização do UNION;

EXEMPLO DE UNION ALL

SELECT  EMPLOYEE_ID, JOB_ID
FROM    EMPLOYEES
UNION ALL
SELECT  EMPLOYEE_ID, JOB_ID
FROM    JOB_HISTORY;

SELECT    EMPLOYEE_ID,
JOB_ID,
DEPARTMENT_ID
FROM    EMPLOYEES

UNION ALL
SELECT    EMPLOYEE_ID,
JOB_ID,
DEPARTMENT_ID
FROM    JOB_HISTORY;

INTERSECT

  • Retorna as linhas que estejam em duas ou mais consultas, ou seja, somente os resultados iguais das consultas são retornados pelo operador;
  • Faz a intersecção dos resultados de todas as consultas;
  • É necessário ter o mesmo número e tipos de colunas;
  • A ordem das consultas não influenciam no resultado;
  • O INTERSECT não ignora valores nulos;

EXEMPLO DE INTERSECT
pre class=”brush: sql; title: ; notranslate” title=””>
SELECT  EMPLOYEE_ID, JOB_ID
FROM    EMPLOYEES
INTERSECT SELECT  EMPLOYEE_ID, JOB_ID
FROM    JOB_HISTORY;

 

MINUS

  • Retorna as linhas da primeira consulta que NÃO estão na segunda consulta;
  • Faz a “subtração” de linhas entre a primeira e segunda consulta;
  • Caso tenha mais de duas consultas, a resolução é feita de cima para baixo;
  • É necessário ter o mesmo número e tipo de colunas nas consultas;
  • A alteração das consultas influencia no resultado final;
  • Todas as colunas da cláusula WHERE precisam estar na cláusula SELECT;
  • EXEMPLO DE MINUS
    SELECT  EMPLOYEE_ID, JOB_ID
    FROM    EMPLOYEES
    MINUS
    SELECT  EMPLOYEE_ID, JOB_ID
    FROM    JOB_HISTORY;
    

  • DIRETRIZES GERAIS

  • Para qualquer operador, o número de colunas e os tipos de dados devem ser equivalentes entre as consultas;
  • A utilização de parênteses altera a sequencia de execução dos operadores;
  • ORDER BY só pode ser usada no final da instrução;
  • ORDER BY aceitará somente os nomes das colunas da primeira consulta ou a notação posição;
  • O nome das colunas são considerados os da primeira consulta;
  • Tuplas duplicadas são eliminadas automaticamente, com exceção de UNION ALL;
  • Por padrão, as saídas são ordenadas em ordem crescente, com exceção de UNION ALL;
  • Quando o número de colunas não são correspondentes entre as consultas, é possível resolver com NULL, ou com uma constante do mesmo tipo equivalente;
  • É possível adicionar uma coluna virtual para ordenação de linhas entre as consultas;
  • EXEMPLO DE TIPOS DE DADOS
    SELECT  DEPARTMENT_ID, NULL AS LOCATION,
    HIRE_DATE
    FROM    EMPLOYEES
    UNION
    SELECT  DEPARTMENT_ID,  LOCATION_ID,
    TO_DATE(NULL)
    FROM    DEPARTMENTS;
    

    EXEMPLO DE ORDEM

    SELECT    DEPARTMENT_ID, HIRE_DATE,
    2 AS ORDEM
    FROM    EMPLOYEES
    UNION
    SELECT    DEPARTMENT_ID,  TO_DATE(NULL),
    1 AS ORDEM
    FROM    DEPARTMENTS
    ORDER BY ORDEM;
    
learningdatabase.com.br

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

Aprendendo Programação

Algorítmos, Linguagem 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()

ROMANO DBA

Administração de Bancos de Dados

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