Professional Documents
Culture Documents
de PL/SQL
Guia do Aluno
D64254BP10
Edição 1.0
Agosto de 2011
D73724
Autor Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos
reservados.
Brian Pottle
Isenção de Responsabilidade
Redatores
Vijayalakshmi Narasimhan
Daniel Milne
Editor
Veena Narasimhan
Índice
I Introdução
Objetivos da Lição I-2
Objetivos do Curso I-3
Esquema Human Resources (HR) Usado Neste Curso I-4
Agenda do Curso I-5
Informações da Conta Usada em Sala de Aula I-6
Apêndices Usados Neste Curso I-7
Ambientes de Desenvolvimento PL/SQL I-8
O que É o Oracle SQL Developer? I-9
Codificando PL/SQL no SQL*Plus I-10
Codificando PL/SQL no Oracle JDeveloper I-11
Documentação de SQL e PL/SQL do Oracle 11g I-12
Sumário I-13
Visão Geral do Exercício I: Conceitos Básicos I-14
iii
2 Declarando Variáveis PL/SQL
Objetivos 2-2
Agenda 2-3
Uso de Variáveis 2-4
Requisitos para Nomes de Variáveis 2-5
Tratando de Variáveis no Código PL/SQL 2-6
Declarando e Inicializando Variáveis PL/SQL 2-7
Delimitadores em Literais de String 2-9
Agenda 2-10
Tipos de Variáveis 2-11
Diretrizes para Declarar e Inicializar Variáveis PL/SQL 2-13
Diretrizes para Declarar Variáveis PL/SQL 2-14
Convenções de Nomeação das Estruturas PL/SQL Usadas Neste Curso 2-15
Tipos de Dados Escalares 2-16
Tipos de Dados Escalares Básicos 2-17
Declarando Variáveis Escalares 2-21
Atributo %TYPE 2-22
Declarando Variáveis com o Atributo %TYPE 2-24
Declarando Variáveis Booleanas 2-25
Variáveis de Tipo de Dados LOB 2-26
Tipos de Dados Compostos: Registros e Conjuntos 2-27
Agenda 2-28
Variáveis de Bind 2-29
Fazendo Referência a Variáveis de Bind 2-31
Usando AUTOPRINT com Variáveis de Bind 2-32
Questionário 2-33
Sumário 2-34
Exercício 2: Visão Geral 2-35
iv
Blocos Aninhados 3-15
Blocos Aninhados: Exemplo 3-16
Escopo e Visibilidade da Variável 3-17
Usando um Qualificador com Blocos Aninhados 3-19
Desafio: Determinando o Escopo de Variáveis 3-20
Agenda 3-22
Operadores no Código PL/SQL 3-23
Operadores no Código PL/SQL: Exemplos 3-24
Diretrizes de Programação 3-25
Usando Recuos no Código 3-26
Questionário 3-27
Sumário 3-28
Exercício 3: Visão Geral 3-29
v
Instrução IF 5-5
Instrução IF Simples 5-7
Instrução IF THEN ELSE 5-8
Cláusula IF ELSIF ELSE 5-9
Valor NULL em Instrução IF 5-10
Agenda 5-11
Expressões CASE 5-12
Expressões CASE: Exemplo 5-13
Expressões CASE Pesquisadas 5-14
Instrução CASE 5-15
Tratando Valores Nulos 5-16
Tabelas Lógicas 5-17
Expressões Booleanas ou Expressão Lógica? 5-18
Agenda 5-19
Controle Iterativo: Instruções de LOOP 5-20
Loops Básicos 5-21
Loop Básico: Exemplo 5-22
Loops WHILE 5-23
Loops WHILE: Exemplo 5-24
Loops FOR 5-25
Loops FOR: Exemplo 5-27
Regras de Loop FOR 5-28
Sugestão de Utilização de Loops 5-29
Loops Aninhados e Labels 5-30
Loops Aninhados e Labels: Exemplo 5-31
Instrução CONTINUE do Código PL/SQL 5-32
Instrução CONTINUE do Código PL/SQL: Exemplo 1 5-33
Instrução CONTINUE do Código PL/SQL: Exemplo 2 5-34
Questionário 5-35
Sumário 5-36
Exercício 5: Visão Geral 5-37
vi
Estrutura de Registros PL/SQL 6-9
Atributo %ROWTYPE 6-10
Criando um Registro PL/SQL: Exemplo 6-12
Vantagens do Uso do Atributo %ROWTYPE 6-13
Outro Exemplo do Atributo %ROWTYPE 6-14
Inserindo um Registro com %ROWTYPE 6-15
Atualizando uma Linha de Tabela com um Registro 6-16
Agenda 6-17
Arrays Associativos (Tabelas INDEX BY) 6-18
Estrutura de Array Associativo 6-19
Etapas para a Criação de um Array Associativo 6-20
Criando e Acessando Arrays Associativos 6-21
Usando Métodos da Tabela INDEX BY 6-22
Opção da Tabela de Registros INDEX BY 6-23
Opção da Tabela de Registros INDEX BY: Exemplo 2 6-24
Tabelas Aninhadas 6-25
VARRAY 6-27
Resumo dos Tipos de Conjunto 6-28
Questionário 6-29
Sumário 6-30
Exercício 6: Visão Geral 6-31
vii
Cursores com Parâmetros 7-24
Agenda 7-26
Cláusula FOR UPDATE 7-27
Cláusula WHERE CURRENT OF 7-29
Questionário 7-30
Sumário 7-31
Exercício 7: Visão Geral 7-32
8 Tratando Exceções
Objetivos 8-2
Agenda 8-3
O Que É uma Exceção? 8-4
Tratando a Exceção: Exemplo 8-5
Fundamentos das Exceções com PL/SQL 8-6
Tratando Exceções 8-7
Tipos de Exceção 8-8
Agenda 8-9
Sintaxe para Interceptar Exceções 8-10
Diretrizes para Interceptar Exceções 8-12
Interceptando Erros Predefinidos do Oracle Server 8-13
Interceptando Erros Não Predefinidos do Oracle Server 8-16
Interceptação de Erro Não Predefinido: Exemplo 8-17
Funções para Interceptar Exceções 8-18
Interceptando Exceções Definidas pelo Usuário 8-20
Propagando Exceções em um Sub-bloco 8-22
Procedure RAISE_APPLICATION_ERROR 8-23
Questionário 8-26
Sumário 8-27
Exercício 8: Visão Geral 8-28
viii
Função: Sintaxe 9-12
Criando uma Função 9-13
Chamando uma Função 9-14
Especificando Parâmetros para a Função 9-15
Chamando a Função com um Parâmetro 9-16
Questionário 9-17
Sumário 9-18
Exercício 9: Visão Geral 9-19
A Exercícios e Soluções
ix
D Usando o SQL*Plus
Objetivos D-2
Interação entre SQL e SQL*Plus D-3
Instruções SQL Versus Comandos do SQL*Plus D-4
SQL*Plus: Visão Geral D-5
Efetuando Login no SQL*Plus D-6
Exibindo a Estrutura da Tabela D-7
Comandos de Edição do SQL*Plus D-9
Usando LIST, n e APPEND D-11
Usando o Comando CHANGE D-12
Comandos de Arquivo do SQL*Plus D-13
Usando os Comandos SAVE e START D-14
Comando SERVEROUTPUT D-15
Usando o Comando SPOOL do SQL*Plus D-16
Usando o Comando AUTOTRACE D-17
Resumo D-18
E Usando o JDeveloper
Oracle JDeveloper E-2
Database Navigator E-3
Criando uma Conexão E-4
Navegando por Objetos de Banco de Dados E-5
Executando Instruções SQL E-6
Criando Unidades de Programa E-7
Compilando E-8
Executando uma Unidade de Programa E-9
Eliminando uma Unidade de Programa E-10
Janela Structure E-11
Janela Editor E-12
Application Navigator E-13
Disponibilizando Procedures Java Armazenados E-14
Publicando Java em PL/SQL E-15
Como Posso Obter Mais Informações sobre o JDeveloper 11g? E-16
F Cursores REF
Variáveis de Cursor F-2
Usando Variáveis de Cursor F-3
Definindo os Tipos REF CURSOR F-4
Usando as Instruções OPEN-FOR, FETCH e CLOSE F-7
Exemplo de Extração com o Comando Fetch F-10
x
Introdução
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos da Lição
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos da Lição
Esta lição apresenta uma visão geral do curso e de seu fluxo. Você conhecerá o esquema do
banco de dados e as tabelas utilizadas no curso. O curso lhe apresenta componentes como SQL,
PL/SQL, recursos de compilação e também ferramentas como o SQL Developer usadas neste
curso.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos do Curso
Este curso apresenta os conceitos básicos de PL/SQL. Você conhecerá a sintaxe, os blocos e as
estruturas de programação PL/SQL e também as vantagens de fazer a integração do SQL com
essas estruturas. Você aprenderá a criar unidades de programa PL/SQL e a executá-las com
eficiência. Além disso, você aprenderá a usar o SQL Developer como ambiente de
desenvolvimento para PL/SQL. Você também será ensinado a projetar unidades de programa
reutilizáveis, como procedures e funções.
DEPARTAMENTOS LOCAIS
department_id location_id
department_name street_address
manager_id postal_code
location_id cidade
state_province
country_id
JOB_HISTORY
employee_id
start_date FUNCIONÁRIOS
employee_id
end_date
first_name
job_id
last_name PAÍSES
department_id
email country_id
phone_number country_name
hire_date region_id
job_id
salário
commission_pct
JOBS manager_id
job_id department_id
job_title
min_salary REGIÕES
max_salary region_id
region_name
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Dia 1:
I. Introdução
1. Introdução à Linguagem PL/SQL
2. Declarando Variáveis PL/SQL
3. Criando Instruções Executáveis
4. Interagindo com o Oracle Database Server: Instruções
SQL em Programas PL/SQL
5. Criando Estruturas de Controle
Dia 2:
6. Trabalhando com Tipos de Dados Compostos
7. Usando Cursores Explícitos
8. Tratando Exceções
9. Apresentando Procedures e Funções Armazenados
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SQL Developer
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Esta lição apresenta a linguagem PL/SQL e as estruturas de programação PL/SQL. Você
também aprenderá as vantagens do código PL/SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
PL/SQL:
• Significa a extensão Procedural Language do código SQL
• É a linguagem padrão de acesso a dados da Oracle
Corporation para bancos de dados relacionais
• Integra totalmente as estruturas procedurais com o código
SQL
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
PL/SQL:
• Fornece uma estrutura de blocos para as unidades
executáveis do código. A manutenção do código é
facilitada com uma estrutura bem definida.
• Fornece estruturas procedurais, como:
– Variáveis, constantes e tipos de dados
– Estruturas de controle, como instruções condicionais e loops
– Unidades de programa reutilizáveis, que são criadas uma
vez e executadas várias vezes
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
procedural
Procedural Statement
Executor
PL/SQL
Mecanismo PL/SQL
SQL
Oracle Server
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SQL 1
SQL 2
…
SQL
IF...THEN
SQL
ELSE
SQL
END IF;
SQL
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• DECLARE (opcional)
– Variáveis, cursores e exceções definidas pelo usuário
• BEGIN (obrigatório)
– Instruções SQL
– Instruções PL/SQL
• EXCEPTION (opcional)
– Ações a serem executadas
quando ocorrerem exceções
• END; (obrigatório)
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tipos de Blocos
Um programa PL/SQL inclui um ou mais blocos. Esses blocos podem estar totalmente separados
ou aninhados em outro bloco.
Existem três tipos de blocos que formam um programa PL/SQL:
• Procedures
• Funções
• Blocos anônimos
Procedures: São objetos nomeados que contêm instruções SQL e/ou PL/SQL.
Funções: São objetos nomeados que contêm instruções SQL e/ou PL/SQL. Diferentemente de
um procedure, uma função retorna um valor de um tipo de dados especificado.
Blocos anônimos
Blocos anônimos são blocos não nomeados. Eles são declarados em linha no momento da
aplicação em que eles deverão ser executados, e serão compilados cada vez que a aplicação for
executada. Esses blocos não são armazenados no banco de dados. Eles são passados para o
mecanismo PL/SQL para execução durante o runtime. Os triggers dos componentes do Oracle
Developer consistem nesses blocos.
Se quiser executar novamente o mesmo bloco, você terá de recriá-lo. Você não poderá chamar o
bloco que criou anteriormente porque os blocos são anônimos e não existem mais depois que são
executados.
Oracle Database: Fundamentos de PL/SQL 1 - 13
Tipos de Blocos (continuação)
Subprogramas
Os subprogramas complementam os blocos anônimos. Eles são blocos PL/SQL nomeados
armazenados no banco de dados. Como eles são nomeados e armazenados, você poderá chamá-
los sempre que desejar, dependendo da sua aplicação. Você pode declará-los como procedures
ou funções. Em geral, o procedure é usado para realizar uma ação e a função para calcular e
retornar um valor.
Os subprogramas podem ser armazenados no nível do servidor ou da aplicação. Usando os
componentes do Oracle Developer (Forms, Reports), você pode declarar procedures e funções
como parte da aplicação (um form ou relatório) e chamá-los a partir de outros procedures,
funções e triggers dentro da mesma aplicação, sempre que necessário.
Estruturas de Servidor
Estruturas de Ferramentas de Banco de Dados
Blocos anônimos Blocos anônimos
Procedures de aplicações Procedures armazenados
ou funções ou funções
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Estruturas de Programa
A tabela a seguir resume várias estruturas de programa PL/SQL que usam blocos PL/SQL
básicos. As estruturas de programa estão disponíveis com base no ambiente em que são
executadas.
Bloco de Descrição Disponibilidade
Programa
Blocos anônimos Blocos PL/SQL não nomeados incorporados a Todos os ambientes PL/SQL
uma aplicação ou executados interativamente
Tipos de objetos Tipos de dados compostos definidos pelo usuário Servidor Oracle e ferramentas do
que fazem encapsulamento de uma estrutura de Oracle Developer
dados juntamente com funções e procedures
necessários para manipular os dados
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SET SERVEROUTPUT ON
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SET SERVEROUTPUT ON
Pressione F5 para
executar o comando e o
bloco PL/SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
a. Verdadeiro
b. Falso
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: b
Um bloco PL/SQL consiste em três seções:
• Declarativa (opcional): A seção declarativa começa com a palavra-chave DECLARE e
termina quando a seção executável começa.
• Executável (obrigatória): A seção executável obrigatória começa com a palavra-chave
BEGIN e termina com END. É essencial que esta seção tenha, no mínimo, uma instrução.
Observe que END é seguido de um ponto e vírgula. A seção executável de um bloco
PL/SQL pode, por sua vez, conter inúmeros blocos PL/SQL.
• Tratamento de exceções (opcional): A seção de exceções opcional é aninhada dentro da
seção executável. Essa seção começa com a palavra-chave EXCEPTION.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
A linguagem PL/SQL possui recursos de programação que funcionam como extensões à
linguagem SQL. A linguagem SQL, que não é procedural, torna-se procedural com as estruturas
de programação PL/SQL. As aplicações PL/SQL podem ser executadas em qualquer plataforma
ou sistema operacional em que o Oracle Server seja executado. Nesta lição, você aprendeu a
criar blocos PL/SQL básicos.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
2-2 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você já aprendeu sobre blocos PL/SQL básicos e suas seções. Nesta lição, você conhecerá os
identificadores válidos e inválidos. Você aprenderá a declarar e inicializar variáveis na seção
declarativa de um bloco PL/SQL. A lição descreve os vários tipos de dados. Você conhecerá
também o atributo %TYPE e suas vantagens.
• Apresentando variáveis
• Examinando tipos de dados de variável e o atributo %TYPE
• Examinando variáveis de bind
2-3 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SELECT
first_name,
department_id
INTO Jennifer v_fname
v_fname,
v_deptno
FROM …
10 v_deptno
2-4 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Uso de Variáveis
Com o código PL/SQL, você pode declarar variáveis e depois usá-las em instruções procedurais
e códigos SQL.
As variáveis são usadas principalmente para o armazenamento de dados e a manipulação de
valores armazenados. Considere a instrução PL/SQL no slide. A instrução recupera
first_name e department_id da tabela. Se precisar manipular first_name ou
department_id, você precisará armazenar o valor recuperado. As variáveis são usadas para
armazenar temporariamente o valor. Os valores armazenados nessas variáveis podem ser usados
para processar e manipular os dados. As variáveis podem armazenar qualquer objeto PL/SQL,
como variáveis, tipos, cursores e subprogramas.
Reutilização é outra vantagem da declaração de variáveis. Após as variáveis serem declaradas,
você poderá usá-las repetidamente em uma aplicação, fazendo referência a elas diversas vezes
em várias instruções.
Um nome de variável:
• Deve começar com uma letra
• Pode conter letras ou números
• Pode conter caracteres especiais (como $, _ e #)
• Não pode conter mais de 30 caracteres
• Não deve conter palavras reservadas
2-5 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
As variáveis são:
• Declaradas e inicializadas (opcionalmente) na seção
declarativa
• Valores novos designados e usados na seção executável
• Transmitidas como parâmetros para subprogramas
PL/SQL
• Usadas para armazenar a saída de um subprograma
PL/SQL
2-6 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
Exemplos:
DECLARE
v_hiredate DATE;
v_deptno NUMBER(2) NOT NULL := 10;
v_location VARCHAR2(13) := 'Atlanta';
c_comm CONSTANT NUMBER := 1400;
2-7 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_myName VARCHAR2(20);
BEGIN
1
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
v_myName := 'John';
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
END;
/
DECLARE
v_myName VARCHAR2(20):= 'John';
2 BEGIN
v_myName := 'Steven';
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
END;
/
2-8 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_event VARCHAR2(15);
BEGIN
v_event := q'!Father's day!';
DBMS_OUTPUT.PUT_LINE('3rd Sunday in June is :
'|| v_event );
v_event := q'[Mother's day]';
DBMS_OUTPUT.PUT_LINE('2nd Sunday in May is :
'|| v_event );
END;
/
Saída
resultante
2-9 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Apresentando variáveis
• Examinando tipos de dados de variável e o atributo %TYPE
• Examinando variáveis de bind
2 - 10 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Variáveis PL/SQL:
– Escalar
– Referência
– LOBs (large objects)
– Composta
• Variáveis não PL/SQL: Variáveis de bind
2 - 11 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tipos de Variáveis
Toda variável PL/SQL tem um tipo de dados, que especifica um formato de armazenamento,
constraints e uma faixa válida de valores. A linguagem PL/SQL suporta várias categorias de
tipos de dados, incluindo os tipos escalares, de referência, LOBs (large objects) e compostos.
• Tipos de dados escalares: Os tipos de dados escalares armazenam um único valor. O
valor depende do tipo de dados da variável. Por exemplo, a variável v_myName do
exemplo da seção “Declarando e Inicializando Variáveis PL/SQL” (desta lição) é do tipo
VARCHAR2. Portanto, v_myName pode armazenar um valor de string. O código PL/SQL
também suporta variáveis booleanas.
• Tipos de dados de referência: Os tipos de dados de referência armazenam valores,
chamados ponteiros, que apontam para um local de armazenamento.
• Tipos de dados LOB: Os tipos de dados LOBs armazenam valores, chamados
localizadores, que especificam a localização de objetos grandes (como imagens gráficas)
que são armazenados fora da tabela.
• Tipos de dados compostos: Os tipos de dados compostos estão disponíveis quando você
utiliza variáveis PL/SQL de conjunto e de registro . Conjuntos e registros PL/SQL
contêm elementos internos que você pode tratar como variáveis individuais.
As variáveis que não são PL/SQL contêm variáveis de linguagem host declaradas em programas
pré-compiladores, campos de tela em aplicações Forms e variáveis de host. Você conhecerá as
variáveis de host posteriormente nesta lição.
Para obter mais informações sobre LOBs, consulte PL/SQL User’s Guide and Reference.
TRUE 15-JAN-09
Branca de Neve
Há muito tempo,
em um reino muito distante,
vivia uma princesa chamada
Branca de Neve. . .
Atlanta
256120.08
2 - 12 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 13 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 14 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 15 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
TRUE 15-JAN-09
O preguiçoso
deseja e coisa nenhuma
alcança; mas o desejo do
diligente será satisfeito.
256120.08 Atlanta
2 - 16 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• CHAR [(maximum_length)]
• VARCHAR2 (maximum_length)
• NUMBER [(precision, scale)]
• BINARY_INTEGER
• PLS_INTEGER
• BOOLEAN
• BINARY_FLOAT
• BINARY_DOUBLE
2 - 17 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• DATE
• TIMESTAMP
• TIMESTAMP WITH TIME ZONE
• TIMESTAMP WITH LOCAL TIME ZONE
• INTERVAL YEAR TO MONTH
• INTERVAL DAY TO SECOND
2 - 19 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Exemplos:
DECLARE
v_emp_job VARCHAR2(9);
v_count_loop BINARY_INTEGER := 0;
v_dept_total_sal NUMBER(9,2) := 0;
v_orderdate DATE := SYSDATE + 7;
c_tax_rate CONSTANT NUMBER(3,2) := 8.25;
v_valid BOOLEAN NOT NULL := TRUE;
...
2 - 21 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 22 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Atributo %TYPE
Em geral, as variáveis PL/SQL são declaradas para conter e manipular dados armazenados no
banco de dados. Ao declarar variáveis PL/SQL para armazenar valores de colunas, assegure-se
de que a variável tenha o tipo de dados e a precisão corretos. Caso contrário, ocorrerá um erro
PL/SQL durante a execução. Se você precisar projetar subprogramas extensos, isso poderá tomar
muito tempo e gerar erros.
Em vez de codificar o tipo de dados e a precisão de uma variável, você pode usar o atributo
%TYPE
para declarar uma variável de acordo com outra variável ou
coluna do banco de dados declarada anteriormente. O atributo %TYPE é usado com mais
frequência quando o valor armazenado na variável tem origem em uma tabela do banco de
dados. Se usar o atributo %TYPE para declarar uma variável, você deverá prefixá-lo com a tabela
do banco de dados e o nome da coluna. Caso você faça referência a uma variável previamente
declarada, use como prefixo o nome da variável declarada anteriormente na variável que está
sendo declarada.
identifier table.column_name%TYPE;
Exemplos
...
v_emp_lname employees.last_name%TYPE;
...
...
v_balance NUMBER(7,2);
v_min_balance v_balance%TYPE := 1000;
...
2 - 24 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 25 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Livro
(CLOB)
Foto
(BLOB)
Filme
(BFILE)
NCLOB
2 - 26 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Conjuntos PL/SQL:
1 SMITH 1 5000
2 JONES 2 2345
3 NANCY 3 12
4 TIM 4 3456
VARCHAR2 NUMBER
PLS_INTEGER PLS_INTEGER
2 - 27 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Apresentando variáveis
• Examinando tipos de dados de variável e o atributo
%TYPE
• Examinando variáveis de bind
2 - 28 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 29 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Variáveis de Bind
As variáveis de bind são as criadas em um ambiente de host. Por esse motivo, às vezes elas são
chamadas de variáveis de host.
Usos de Variáveis de Host
As variáveis de bind são criadas no ambiente e não na seção declarativa de um bloco
PL/SQL. Portanto, as variáveis de bind são acessíveis mesmo após a execução do bloco. Quando
criadas, as variáveis de bind podem ser usadas e manipuladas por vários subprogramas. Elas
podem ser usadas em instruções SQL e blocos PL/SQL como qualquer outra variável. Essas
variáveis podem ser especificadas como valores de runtime para subprogramas PL/SQL ou
podem ser retornadas por eles.
Observação: Uma variável de bind é de ambiente, mas não é uma variável global.
Criando Variáveis de Bind
Para criar uma variável de bind no SQL Developer, use o comando VARIABLE. Por exemplo,
declare uma variável do tipo NUMBER e VARCHAR2 assim:
VARIABLE return_code NUMBER
VARIABLE return_msg VARCHAR2(30)
Exibindo Valores em Variáveis de Bind
É possível fazer referência à variável de bind usando o SQL Developer e exibir seu valor usando
o comando PRINT.
Oracle Database: Fundamentos de PL/SQL 2 - 29
Variáveis de Bind (continuação)
Exemplo
É possível fazer referência a uma variável de bind em um programa PL/SQL colocando dois-
pontos antes da variável.
Por exemplo, o bloco PL/SQL a seguir cria e usa a variável de bind b_result. A saída
resultante do comando PRINT é mostrado abaixo do código.
Observação: Se você estiver criando uma variável de bind do tipo NUMBER, não será possível
especificar a precisão e a escala. No entanto, é possível especificar o tamanho de strings de
caracteres. Um NUMBER do Oracle é armazenado da mesma forma, qualquer que seja a sua
dimensão. O Oracle Server usa o mesmo número de bytes para armazenar 7, 70 e .0734. Não é
conveniente calcular o tamanho da representação numérica Oracle partindo do formato do
número, por isso o código sempre aloca os bytes necessários. Com strings de caracteres, o
usuário tem que especificar o tamanho para que o número de bytes necessário possa ser alocado.
Exemplo:
VARIABLE b_emp_salary NUMBER
BEGIN
SELECT salary INTO :b_emp_salary
FROM employees WHERE employee_id = 178;
END;
/
PRINT b_emp_salary
SELECT first_name, last_name
FROM employees
WHERE salary=:b_emp_salary;
Saída
2 - 31 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 - 32 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
O atributo %TYPE:
a. É usado para declarar uma variável de acordo com uma
definição de coluna do banco de dados
b. É usado para declarar uma variável de acordo com um
conjunto de colunas de uma tabela ou view do banco de
dados
c. É usado para declarar uma variável de acordo com a
definição de outra variável declarada
d. Tem como prefixo o nome da tabela do banco de dados e
o nome da coluna ou da variável declarada
2 - 33 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a, c, d
O Atributo %TYPE
Em geral, as variáveis PL/SQL são declaradas para conter e manipular dados armazenados no
banco de dados. Ao declarar variáveis PL/SQL para armazenar valores de colunas, assegure-se
de que a variável tenha o tipo de dados e a precisão corretos. Caso contrário, ocorrerá um erro
PL/SQL durante a execução. Se você precisar projetar subprogramas extensos, isso poderá tomar
muito tempo e gerar erros.
Em vez de codificar o tipo de dados e a precisão de uma variável, você pode usar o atributo
%TYPE
para declarar uma variável de acordo com outra variável ou
coluna do banco de dados declarada anteriormente. O atributo %TYPE é usado com mais
frequência quando o valor armazenado na variável tem origem em uma tabela do banco de
dados. Se usar o atributo %TYPE para declarar uma variável, você deverá prefixá-lo com a tabela
do banco de dados e o nome da coluna. Caso você faça referência a uma variável previamente
declarada, use como prefixo o nome da variável declarada anteriormente na variável que está
sendo declarada. A vantagem de %TYPE é que não será necessário alterar a variável caso a
coluna seja alterada. Além disso, se a variável for usada em um cálculo, você não precisará se
preocupar com a sua precisão.
O Atributo %ROWTYPE
O atributo %ROWTYPE é usado para declarar um registro que possa armazenar uma linha inteira
de uma tabela ou view. Você aprenderá sobre esse atributo na lição “Trabalhando com Tipos de
Dados Compostos.”
Oracle Database: Fundamentos de PL/SQL 2 - 33
Sumário
2 - 34 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Um bloco PL/SQL anônimo é uma unidade básica não nomeada de um programa PL/SQL. Ele
consiste em um conjunto de instruções SQL ou PL/SQL para executar uma função lógica. A
parte declarativa é a primeira parte de um bloco PL/SQL e é usada para declarar objetos como
variáveis, constantes, cursores e definições de situações de erro chamadas de exceções.
Nesta lição, você aprendeu a declarar variáveis na seção declarativa. Você conheceu algumas
diretrizes para declaração de variáveis. E aprendeu a inicializar variáveis ao declará-las.
A parte executável de um bloco PL/SQL é a parte obrigatória e contém instruções SQL e
PL/SQL para consultar e manipular dados. Você aprendeu a inicializar variáveis na seção
executável, a como utilizá-las e a manipular seus valores.
2 - 35 Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você aprendeu a declarar variáveis e criar instruções executáveis em um bloco PL/SQL. Nesta
lição, você aprenderá como as unidades lexicais formam um bloco PL/SQL. Você aprenderá a
criar blocos aninhados. Você também aprenderá sobre o escopo e a visibilidade das variáveis nos
blocos aninhados e a qualificar variáveis com labels.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Unidades lexicais:
• São blocos de construção para qualquer bloco PL/SQL
• São sequências de caracteres, incluindo letras, dígitos,
tabulações, espaços, quebras de linha e símbolos
• Podem ser classificadas como:
– Identificadores: v_fname, c_percent
– Delimitadores: ; , +, -
– Literais: John, 428, True
– Comentários: --, /* */
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Símbolos compostos
Símbolo Significado
<> Operador de desigualdade
!= Operador de desigualdade
|| Operador de concatenação
-- Indicador de comentário de uma única linha
/* Delimitador de início de comentário
*/ Delimitador de fim de comentário
:= Operador de designação
Observação: Esse é apenas um subconjunto, e não uma lista completa dos delimitadores.
• Literais: Qualquer valor designado a uma variável é um literal. Qualquer valor de
caractere, numérico, booleano ou de data que não seja um identificador é um literal. Os
literais são classificados como:
- Literais de caractere: Todos os literais de string têm o tipo de dados CHAR ou
VARCHAR2 e são, portanto, chamados de literais de caractere (por exemplo, John e
12C).
- Literais numéricos: Um literal numérico representa um valor inteiro ou real (por
exemplo, 428 e1.276).
- Literais booleanos: Os valores designados a variáveis booleanas são literais
booleanos. TRUE, FALSE e NULL são literais booleanos ou palavras-chave.
• Comentários: Em programação, convém explicar o que um trecho de código está tentando
obter. No entanto, quando você inclui a explicação em um bloco PL/SQL, o compilador
não pode interpretar essas instruções. Portanto, deve haver um modo de indicar que essas
instruções não precisam ser compiladas. Os comentários são usados principalmente com
essa finalidade. Qualquer instrução comentada não será interpretada pelo compilador.
- Dois hífens (--) são usados para uma única linha de comentário.
- Os delimitadores inicial e final do comentário (/* e*/) são usados para comentar
várias linhas.
Oracle Database: Fundamentos de PL/SQL 3 - 5
Diretrizes e Sintaxe de Blocos PL/SQL
• Usando Literais
– Os literais de caractere e de data devem ser delimitados por aspas simples.
– Os números podem estar em valores simples ou em notação científica.
v_name := 'Henderson';
• Formatando código: as instruções podem abranger várias linhas.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Comentando o Código
Comente o código para documentar cada fase e para ajudar a depuração. No código PL/SQL:
• Normalmente, o comentário de uma única linha é iniciado por dois hífens (--)
• Você também pode colocar um comentário entre os símbolos /* e */
Observação: No caso de comentários de várias linhas, você pode iniciar cada linha do
comentário com dois hífens ou usar o formato de comentário em bloco.
Os comentários são estritamente informativos e não impõem condições ou comportamento na
lógica ou nos dados. Comentários bem colocados são extremamente importantes para a
legibilidade do código e a sua manutenção futura.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Iniciando no 11g:
DECLARE
v_new_id NUMBER;
BEGIN
v_new_id := my_seq.NEXTVAL;
END;
/
Antes do 11g:
DECLARE
v_new_id NUMBER;
BEGIN
SELECT my_seq.NEXTVAL INTO v_new_id FROM Dual;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Blocos Aninhados
Por ser procedural, a linguagem PL/SQL permite aninhar instruções. É possível aninhar blocos
onde quer que uma instrução executável seja permitida, transformando, então, o bloco aninhado
em uma instrução. Se a seção executável tiver código para muitas funcionalidades logicamente
relacionadas para suportar vários requisitos de negócios, você poderá dividir a seção executável
em blocos menores. A seção de exceções também pode conter blocos aninhados.
DECLARE
v_outer_variable VARCHAR2(20):='GLOBAL VARIABLE';
BEGIN
DECLARE
v_inner_variable VARCHAR2(20):='LOCAL VARIABLE';
BEGIN
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
END;
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
DBMS_OUTPUT.PUT_LINE('Child''s Name: '||v_child_name);
END;
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
BEGIN <<outer>>
DECLARE
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '
||outer.v_date_of_birth);
DBMS_OUTPUT.PUT_LINE('Child''s Name: '||v_child_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
END;
END;
END outer;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Observação: O uso de labels não se limita ao bloco externo. Você pode pôr label em qualquer
bloco.
BEGIN <<outer>>
DECLARE
v_sal NUMBER(7,2) := 60000;
v_comm NUMBER(7,2) := v_sal * 0.20;
v_message VARCHAR2(255) := ' eligible for commission';
BEGIN
DECLARE
v_sal NUMBER(7,2) := 50000;
v_comm NUMBER(7,2) := 0;
v_total_comp NUMBER(7,2) := v_sal + v_comm;
BEGIN
1 v_message := 'CLERK not'||v_message;
outer.v_comm := v_sal * 0.30;
END;
2 v_message := 'SALESMAN'||v_message;
END;
END outer;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Lógicos
• Aritméticos
• Concatenação Iguais aos do SQL
• Parênteses para controlar
a ordem das operações
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Operator Operation
** Exponenciação
+, - Identidade, negação
*, / Multiplicação, divisão
+, -, || Adição, subtração, concatenação
=, <, >, <=, >=, <>, !=, ~=, ^=, Comparação
IS NULL, LIKE, BETWEEN, IN
NOT Negação lógica
AND Conjunção
OR Inclusão
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Diretrizes de Programação
Siga as diretrizes de programação mostradas no slide para produzir um código claro e reduzir a
manutenção ao desenvolver um bloco PL/SQL.
Convenções de Código
A tabela a seguir fornece diretrizes para criar código em caracteres maiúsculos ou minúsculos
para ajudar a distinguir palavras-chave de objetos nomeados.
BEGIN DECLARE
IF x=0 THEN deptno NUMBER(4);
y:=1; location_id NUMBER(4);
END IF; BEGIN
END; SELECT department_id,
/ location_id
INTO deptno,
location_id
FROM departments
WHERE department_name
= 'Sales';
...
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
IF x > y THEN
max := x;
ELSE
max := y;
END IF;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a
Funções SQL no Código PL/SQL
O código SQL oferece várias funções predefinidas que podem ser usadas em instruções SQL. A
maioria delas (como funções de uma única linha de número e caractere, de conversão de tipo de
dados e de data e timestamp) é válida em expressões PL/SQL.
Estas funções não estão disponíveis em instruções procedurais:
• DECODE
• Funções de grupo: AVG, MIN, MAX, COUNT, SUM, STDDEV e VARIANCE
As funções de grupo aplicam-se a grupos de linhas de uma tabela e, por isso, estão
disponíveis apenas em instruções SQL de um bloco PL/SQL. As funções aqui mencionadas
são apenas um subconjunto da lista completa.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Como PL/SQL é uma extensão do código SQL, as regras gerais de sintaxe que se aplicam ao
SQL também se aplicam à linguagem PL/SQL.
Um bloco pode ter inúmeros blocos aninhados definidos dentro de sua parte executável. Os
blocos definidos dentro de um bloco são chamados de sub-blocos. Só é possível aninhar blocos
na parte executável de um bloco. Como a seção de exceções também faz parte da seção
executável, ela também pode conter blocos aninhados. Assegure escopo e visibilidade corretos
para as variáveis quando usar blocos aninhados. Evite usar identificadores iguais nos blocos pais
e filhos.
A maioria das funções disponíveis no código SQL também é válida em expressões PL/SQL. As
funções de conversão convertem um valor de um tipo de dados para outro. Os operadores de
comparação comparam uma expressão com outra. O resultado é sempre TRUE, FALSE ou
NULL. Normalmente, os operadores de comparação são usados em instruções de controle
condicional e na cláusula WHERE de instruções de manipulação de dados SQL. Os operadores
relacionais permitem comparar arbitrariamente expressões complexas.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Nesta lição, você aprenderá a incorporar instruções-padrão SELECT, INSERT, UPDATE,
DELETE e MERGE em blocos PL/SQL. Aprenderá a incluir códigos DLL (Data Definition
Language) e instruções de controle de transação em PL/SQL. Você compreenderá a necessidade
dos cursores e as diferenças entre os dois tipos de cursores. A lição também apresentará os
vários atributos de cursores SQL que podem ser usados com cursores implícitos.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_sum_sal NUMBER(10,2);
v_deptno NUMBER NOT NULL := 60;
BEGIN
SELECT SUM(salary) -- group function
INTO v_sum_sal FROM employees
WHERE department_id = v_deptno;
DBMS_OUTPUT.PUT_LINE ('The sum of salary is ' || v_sum_sal);
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
hire_date employees.hire_date%TYPE;
sysdate hire_date%TYPE;
employee_id employees.employee_id%TYPE := 176;
BEGIN
SELECT hire_date, sysdate
INTO hire_date, sysdate
FROM employees
WHERE employee_id = employee_id;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Ambiguidades de Nomeação
Em instruções SQL potencialmente ambíguas, os nomes das colunas dos bancos de dados têm
precedência sobre os nomes das variáveis locais.
O exemplo mostrado no slide é definido assim: Recupere a data de admissão e a data de hoje da
tabela employees para o funcionário cujo employee_id é176. Esse exemplo gera uma
exceção durante o runtime não tratada porque, na cláusula WHERE, os nomes das variáveis
PL/SQL são iguais aos nomes das colunas do banco de dados na tabela employees.
A instrução DELETE a seguir remove todos os funcionários da tabela employees, cujo
sobrenome não seja nulo (não apenas “King”), porque o Oracle Server pressupõe que ambas as
ocorrências de last_name na cláusula WHERE se referem à coluna do banco de dados:
DECLARE
last_name VARCHAR2(25) := 'King';
BEGIN
DELETE FROM employees WHERE last_name = last_name;
. . .
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Convenções de Nomeação
Evite ambiguidade na cláusula WHERE seguindo uma convenção de nomeação que diferencie os
nomes de colunas do banco de dados dos nomes de variáveis PL/SQL.
• As colunas de banco de dados e os identificadores devem ter nomes distintos.
• Podem ocorrer erros de sintaxe porque o código PL/SQL verifica primeiro se há uma
coluna na tabela do banco de dados.
Observação: Não há possibilidade de ambiguidade na cláusula SELECT pois qualquer
identificador na cláusula SELECT deve ser um nome de coluna do banco de dados. Não há
possibilidade de ambiguidade na clásula INTO pois os identificadores na cláusula INTO devem
ser variáveis PL/SQL. Só há possibilidade de confusão na cláusula WHERE.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
INSERT
MERGE
UPDATE
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
BEGIN
INSERT INTO employees
(employee_id, first_name, last_name, email,
hire_date, job_id, salary)
VALUES(employees_seq.NEXTVAL, 'Ruth', 'Cores',
'RCORES',CURRENT_DATE, 'AD_ASST', 4000);
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Inserindo Dados
No exemplo do slide, uma instrução INSERT é usada dentro de um bloco PL/SQL para inserir
um registro na tabela employees. Ao usar o comando INSERT em um bloco PL/SQL, você
pode:
• Usar funções SQL como USER e CURRENT_DATE
• Gerar valores de chave primária usando sequências existentes de banco de dados
• Derivar valores no bloco PL/SQL
Observação: Os dados da tabela employees devem permanecer inalterados. Embora a tabela
employees não seja somente para leitura, não é permitido fazer inserções, atualizações e
deleções nesta tabela para garantir a consistência de saída, como mostrado no arquivo
code_04_15_s.sqldo código de exemplo.
...
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Atualizando Dados
É possível haver ambiguidade na cláusula SET da instrução UPDATE porque, embora o
identificador à esquerda do operador de designação seja sempre uma coluna do banco de dados,
o identificador à direita pode ser uma coluna do banco de dados ou uma variável PL/SQL.
Lembre-se de que, se os nomes de colunas e de identificadores foram iguais na cláusula WHERE,
o Oracle Server primeiro procurará o nome no banco de dados.
Lembre-se de que a cláusula WHERE é usada para determinar as linhas que são afetadas. Se
nenhuma linha for modificada, não ocorrerá erro (ao contrário do que acontece com a instrução
SELECT no código PL/SQL).
Observação: As designações de variáveis PL/SQL sempre usam := e as designações de colunas
SQL sempre usam =.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Deletando Dados
A instrução DELETE remove linhas indesejadas da tabela. Se a cláusula WHERE não for usada,
todas as linhas de uma tabela poderão ser removidas desde que não haja constraints de
integridade.
BEGIN
MERGE INTO copy_emp c
USING employees e
ON (e.employee_id = c.empno)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email = e.email,
. . .
WHEN NOT MATCHED THEN
INSERT VALUES(e.employee_id, e.first_name, e.last_name,
. . .,e.department_id);
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Intercalando Linhas
A instrução MERGE insere ou atualiza linhas de uma tabela usando dados de outra tabela. Cada
linha é inserida ou atualizada na tabela de destino, de acordo com uma condição equijoin.
O exemplo mostrado faz a correspondência da coluna empno da tabela copy_emp com a
coluna employee_id da tabela employees. Se for encontrada uma correspondência, a linha
será atualizada para corresponder à linha da tabela employees. Se a linha não for encontrada,
ela será inserida na tabela copy_emp.
O exemplo completo de uso da instrução MERGE em um bloco PL/SQL é mostrado na próxima
página.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Cursor SQL
Você já aprendeu que é possível incluir instruções SQL em um bloco PL/SQL para retornar uma
única linha. Os dados recuperados pela instrução SQL devem ser armazenados em variáveis por
meio da cláusula INTO.
Onde o Oracle Server Processa as Instruções SQL?
O Oracle Server aloca uma área de memória particular chamada área de contexto para processar
instruções SQL. É efetuado parse na instrução SQL e ela é processada nessa área. Todas as
informações necessárias para o processamento e aquelas recuperadas após o processamento são
armazenadas nessa área. Você não tem controle sobre essa área porque ela é internamente
gerenciada pelo Oracle Server.
Um cursor é um ponteiro para a área de contexto. No entanto, esse cursor é implícito e
gerenciado automaticamente pelo Oracle Server. Quando o bloco executável executa uma
instrução SQL, o bloco PL/SQL cria um cursor implícito.
Tipos de Cursores
Há dois tipos de cursores:
• Implícitos: Um cursor implícito é criado e gerenciado pelo Oracle Server. Você não tem
acesso a ele. O Oracle Server cria esse cursor quando precisa executar uma instrução SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_rows_deleted VARCHAR2(30)
v_empno employees.employee_id%TYPE := 176;
BEGIN
DELETE FROM employees
WHERE employee_id= v_empno;
v_rows_deleted := (SQL%ROWCOUNT ||
' row deleted.');
DBMS_OUTPUT.PUT_LINE (v_rows_deleted);
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: b
Cláusula INTO
A cláusula INTO é obrigatória e ocorre entre as cláusulas SELECT e FROM. Ela é usada para
especificar os nomes das variáveis que armazenam os valores que o código SQL retorna da
cláusula SELECT. Especifique uma variável para cada item selecionado. A ordem das variáveis
deve corresponder aos itens selecionados.
Use a cláusula INTO para preencher as variáveis PL/SQL ou as variáveis de host.
As Consultas Devem Retornar Apenas uma Linha
As instruções SELECT contidas em um bloco PL/SQL recaem na classificação ANSI de SQL
incorporada, para a qual se aplica a seguinte regra: As consultas devem retornar apenas uma
linha. Uma consulta que retorne mais de uma linha ou nenhuma linha gera um erro.
O bloco PL/SQL gerencia esses erros gerando exceções-padrão, que podem ser tratadas na seção
de exceções do bloco com as exceções NO_DATA_FOUND e TOO_MANY_ROWS. Inclua uma
condição WHERE na instrução SQL para que a instrução retorne uma única linha. Você
aprenderá sobre o tratamento de exceções mais adiante no curso.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Comandos DML e instruções de controle de transação podem ser usados em programas PL/SQL
sem restrição. Entretanto, os comandos DDL não podem ser usados diretamente.
Uma instrução SELECT de um bloco PL/SQL pode retornar apenas uma linha. É obrigatório o
uso da cláusula INTO para armazenar os valores recuperados pela instrução SELECT.
Um cursor é um ponteiro para a área da memória. Há dois tipos de cursores. Os cursores
implícitos são criados e gerenciados internamente pelo Oracle Server para executar as instruções
SQL. É possível usar atributos de cursores SQL com esses cursores para determinar o resultado
da instrução SQL. Os cursores explícitos são declarados pelos programadores.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você aprendeu a criar blocos PL/SQL contendo as seções declarativa e executável. Aprendeu
também a incluir expressões e instruções SQL no bloco executável.
Nesta lição, você aprenderá a usar estruturas de controle, como instruções IF, expressões CASE
e estruturas LOOP em um bloco PL/SQL.
loop
for
while
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Usando instruções IF
• Usando instruções CASE e expressões CASE
• Construindo e identificando instruções de loop
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Instrução IF
A estrutura da instrução IF do código PL/SQL é semelhante à das instruções IF de outras
linguagens procedurais. Ela permite que o código PL/SQL realize ações seletivamente com base
em condições.
Na sintaxe:
Observação: ELSIF e ELSE são opcionais em uma instrução IF. Pode haver qualquer número
de palavras-chave ELSIF, mas apenas uma palavra-chave ELSE na instrução IF. END IF
marca o fim de uma instrução IF e deve ser encerrada por um ponto-e-vírgula.
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
END IF;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Instrução IF Simples
Exemplo de Instrução IF Simples
O slide mostra um exemplo de uma instrução IF simples com a cláusula THEN.
• A variável v_myage é inicializada com 31.
• A condição para a instrução IF retorna FALSE porque v_myage não é menor que 11.
• Com isso, o controle nunca atinge a cláusula THEN.
Adicionando Expressões Condicionais
Uma instrução IF pode ter várias expressões condicionais relacionadas com operadores lógicos,
como AND, OR e NOT.
Por exemplo:
IF (myfirstname='Christopher' AND v_myage <11)
…
A condição usa o operador AND e, portanto, será avalidada como TRUE somente se ambas as
condiçções forem avaliadas como TRUE. Não há limitação explícita em relação ao número de
expressões condicionais. Entretanto, essas instruções devem estar relacionadas a operadores
lógicos adequados.
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSIF v_myage < 20 THEN
DBMS_OUTPUT.PUT_LINE(' I am young ');
ELSIF v_myage < 30 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my twenties');
ELSIF v_myage < 40 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my thirties');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am always young ');
END IF;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_myage number;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Usando instruções IF
• Usando instruções CASE e expressões CASE
• Construindo e identificando instruções de loop
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
CASE selector
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
[ELSE resultN+1]
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Expressões CASE
A expressão CASE retorna um resultado baseado em uma ou mais alternativas. Para retornar o
resultado, a expressão CASE usa um seletor, que é uma expressão cujo valor é usado para
retornar uma entre várias alternativas. O seletor é seguido de uma ou mais cláusulas WHEN, que
são verificadas sequencialmente. O valor do seletor determina qual resultado será retornado.
Caso o valor do seletor seja igual ao valor de uma expressão da cláusula WHEN, essa cláusula
WHEN será executada e esse resultado será retornado.
O código PL/SQL também fornece uma expressão CASE pesquisada, que tem esta forma:
CASE
WHEN search_condition1 THEN result1
WHEN search_condition2 THEN result2
...
WHEN search_conditionN THEN resultN
[ELSE resultN+1]
END;
Uma expressão CASE pesquisada não possui seletor. Além disso, as cláusulas WHEN em
expressões CASE contêm condições de pesquisa que retornam um valor booleano em vez de
expressões que possam retornar um valor de qualquer tipo.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_grade CHAR(1) := UPPER('&grade');
v_appraisal VARCHAR2(20);
BEGIN
v_appraisal := CASE
WHEN v_grade = 'A' THEN 'Excellent'
WHEN v_grade IN ('B','C') THEN 'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| v_grade || '
Appraisal ' || v_appraisal);
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Instrução CASE
Lembre-se do uso da instrução IF. É possível incluir n instruções PL/SQL na cláusula THEN e
também na cláusula ELSE. Da mesma forma, é possível incluir instruções na instrução CASE,
que é mais legível do que várias instruções IF e ELSIF.
Como uma Expressão CASE Difere de uma Instrução CASE
Uma expressão CASE avalia a condição e retorna um valor, enquanto uma instrução CASE
avalia a condição e executa uma ação. A instrução CASE pode ser um bloco PL/SQL inteiro.
• Instruções CASE são finalizadas com END CASE;
• Expressões CASE são finalizadas com END;
A saída do código de exemplo do slide é a seguinte:
Observação: Enquanto uma instrução IF não é capaz de executar algo (todas as condições
devem ser falsas e a cláusula ELSE não é obrigatória), uma instrução CASE deve executar uma
instrução PL/SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
TRUE TRUE FALSE NULL TRUE TRUE TRUE TRUE TRUE FALSE
FALSE FALSE FALSE FALSE FALSE TRUE FALSE NULL FALSE TRUE
NULL NULL FALSE NULL NULL TRUE NULL NULL NULL NULL
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tabelas Lógicas
É possível construir uma condição booleana simples combinando expressões de número,
caractere e data com operadores de comparação.
Você pode construir uma condição booleana complexa combinando condições booleanas
simples com os operadores lógicos AND, OR e NOT. Os operadores lógicos são usados para
verificar os valores da variável booleana e retornar TRUE, FALSE ou NULL. Nas tabelas lógicas
mostradas no slide:
• FALSE tem precedência em uma condição AND e TRUE tem precedência em uma
condição OR
• AND retornará TRUE somente se os dois operandos forem TRUE
• OR retornará FALSE somente se os dois operandos forem FALSE
• NULL AND TRUE sempre é avaliado como NULL, pois não se sabe se o segundo operador é
avaliado como TRUE
Observação: A negação de NULL (NOT NULL) resulta em um valor nulo porque os valores
nulos são indeterminados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Usando instruções IF
• Usando instruções CASE e expressões CASE
• Construindo e identificando instruções de loop
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
LOOP
statement1;
. . .
EXIT [WHEN condition];
END LOOP;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Loops Básicos
A forma mais simples de uma instrução de LOOP é o loop básico, que contém uma sequência de
instruções entre as palavras-chave LOOP e END LOOP. Cada vez que o fluxo de execução atinge
a instrução END LOOP, o controle é retornado à instrução LOOP correspondente acima dela. Um
loop básico permite a execução de suas instruções pelo menos uma vez, mesmo que a condição
EXIT seja atendida na entrada do loop. Sem a instrução EXIT, o loop seria infinito.
Instrução EXIT
Você pode usar a instrução EXIT para encerrar um loop. O controle passará para a próxima
instrução depois da instrução END LOOP. É possível executar EXIT como uma ação dentro de
uma instrução IF ou como uma instrução stand-alone dentro do loop. A instrução EXIT precisa
estar dentro de um loop. No último caso, você pode anexar uma cláusula WHEN para permitir o
término condicional do loop. Quando a instrução EXIT for encontrada, a condição da cláusula
WHEN será avaliada. Se a condição retornar TRUE, o loop será finalizado e o controle passará
para a instrução seguinte ao loop.
Um loop básico pode conter várias instruções EXIT, mas recomenda-se que haja apenas um
ponto EXIT.
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_counter NUMBER(2) := 1;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + v_counter), v_new_city, v_countryid);
v_counter := v_counter + 1;
EXIT WHEN v_counter > 3;
END LOOP;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
WHILE condition LOOP
statement1;
statement2;
. . .
END LOOP;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Loops WHILE
Você pode usar o loop WHILE para repetir uma sequência de instruções até que a condição de
controle não seja mais TRUE. A condição é avaliada no início de cada iteração. O loop será
encerrado quando a condição for FALSE ou NULL. Se a condição for FALSE ou NULL no início
do loop, nenhuma outra iteração será executada. Portanto, é possível que nenhuma das
instruções contidas no loop sejam executadas.
Na sintaxe:
condition É uma variável booleana ou expressão (TRUE, FALSE ou NULL)
statement Pode ser uma ou mais instruções PL/SQL ou SQL
Caso as variáveis envolvidas nas condições não se alterem durante o corpo do loop, a condição
permanecerá TRUE e o loop não será encerrado.
Observação:Se a condição retornar NULL, o loop será ignorado e o controle passará para a
próxima instrução.
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
v_counter NUMBER := 1;
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
WHILE v_counter <= 3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + v_counter), v_new_city, v_countryid);
v_counter := v_counter + 1;
END LOOP;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Loops FOR
Os loops FOR têm a mesma estrutura geral de um loop básico. Além disso, eles têm uma
instrução de controle antes da palavra-chave LOOP para definir o número de iterações que o
código PL/SQL executará.
Na sintaxe:
counter É um inteiro implicitamente declarado, cujo valor aumenta ou
diminui de forma automática (diminui se for usada a palavra-chave
REVERSE) uma unidade a cada iteração do loop até que seja
alcançado o limite superior ou inferior
REVERSE Faz com que o contador seja diminuído a cada iteração, do limite
superior para o limite inferior
Observação: O limite inferior ainda é referenciado primeiro.
lower_bound Especifica o limite inferior da faixa de valores do contador
upper_bound Especifica o limite superior da faixa de valores do contador
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id
FROM locations
WHERE country_id = v_countryid;
FOR i IN 1.0,3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + i), v_new_city, v_countryid );
END LOOP;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
...
BEGIN
<<Outer_loop>>
LOOP
v_counter := v_counter+1;
EXIT WHEN v_counter>10;
<<Inner_loop>>
LOOP
...
EXIT Outer_loop WHEN total_done = 'YES';
-- Leave both loops
EXIT WHEN inner_done = 'YES';
-- Leave inner loop only
...
END LOOP Inner_loop;
...
END LOOP Outer_loop;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• Definição
– Adiciona a funcionalidade para iniciar a próxima iteração
de loop
– Permite que programadores possam transferir o controle
para a próxima iteração de um loop
– Usa estrutura e semântica paralela na instrução EXIT
• Vantagens
– Facilita o processo de programação
– Pode oferecer um pequeno aperfeiçoamento do
desempenho em relação às soluções de programação
anteriores para simular a instrução CONTINUE
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
v_total SIMPLE_INTEGER := 0;
BEGIN
FOR i IN 1..10 LOOP
1 v_total := v_total + i;
dbms_output.put_line
('Total is: ' || v_total);
CONTINUE WHEN i > 5;
v_total := v_total + i;
2 dbms_output.put_line
('Out of Loop Total is:
' || v_total);
END LOOP;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a
Tipos de Loop
O código PL/SQL oferece os seguintes tipos de loops:
• Loops básicos que executam ações repetitivas sem condições gerais
• Loops FOR que executam ações iterativas com base em uma contagem
• Loops WHILE que executam ações iterativas com base em uma condição
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Uma linguagem só pode ser chamada de linguagem de programação se ela fornecer estruturas de
controle para a implementação da lógica de negócios. Essas estruturas de controle também são
usadas para controlar o fluxo do programa. O código PL/SQL é uma linguagem de programação
que integra estruturas de programação ao código SQL.
Um bloco de controle condicional verifica a validade de uma condição e executa uma ação de
acordo com ela. Use o bloco IF para realizar uma execução condicional de instruções.
Um bloco de controle interativo executa uma sequência de instruções repetidamente, enquanto a
condição especificada se mostrar TRUE. Use os vários blocos de loop para executar as operações
iterativas.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você já foi apresentado aos tipos de dados compostos. Nesta lição, você aprenderá mais sobre
os tipos de dados compostos e seus usos.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
VARCHAR2
PLS_INTEGER
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Registros PL/SQL
Um registro é um grupo de itens de dados relacionados armazenados em campos,, cada um
com seu próprio nome e tipo de dados.
• Cada registro definido pode ter quantos campos forem necessários.
• É possível designar aos registros valores iniciais, e os registros podem ser definidos como
NOT NULL.
• Os campos sem valores iniciais serão inicializados como NULL.
• A palavra-chave DEFAULT, bem como := pode ser usada nos campos de inicialização.
• Você pode definir tipos RECORD e declarar registros definidos pelo usuário na parte
declarativa de qualquer bloco, subprograma ou pacote.
• Você pode declarar e fazer referência a registros aninhados. Um registro pode ser o
componente de outro registro.
Sintaxe:
2 identifier type_name;
field_declaration:
field_name {field_type | variable%TYPE
| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Declarações de campo:
Exemplo:
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Atributo %ROWTYPE
Você aprendeu que %TYPE é usado para declarar uma variável do tipo de coluna. A variável
tem o mesmo tipo de dados e tamanho de uma coluna da tabela. A vantagem de %TYPE é que
não será necessário alterar a variável caso a coluna seja alterada. Além disso, se a variável for
um número e for usada em qualquer cálculo, você não precisará se preocupar com a sua
precisão.
O atributo %ROWTYPE é usado para declarar um registro que possa armazenar uma linha
inteira de uma view ou tabela. Os campos do registro adotam os nomes e tipos de dados das
colunas da view ou da tabela. O registro também pode armazenar uma linha inteira de dados
extraídos de um cursor ou uma variável de cursor.
O slide mostra a sintaxe para se declarar um registro. Na sintaxe:
identifier É o nome escolhido para o registro como um todo
reference É o nome da tabela, view, cursor ou variável de cursor na qual
o registro deve ser baseado (a tabela ou view deve existir para
que essa referência seja válida).
Neste exemplo, um registro é declarado usando %ROWTYPE como um especificador de tipo de
dados:
DECLARE
emp_record employees%ROWTYPE;
...
Oracle Database: Fundamentos de PL/SQL 6 - 10
Atributo %ROWTYPE (continuação)
O registro emp_record tem uma estrutura que consiste nos campos a seguir, cada um
representando uma coluna da tabela employees.
Observação: Isso não é um código, mas apenas a estrutura da variável composta.
(employee_id NUMBER(6),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
email VARCHAR2(20),
phone_number VARCHAR2(20),
hire_date DATE,
salary NUMBER(8,2),
commission_pct NUMBER(2,2),
manager_id NUMBER(6),
department_id NUMBER(4))
Para fazer referência a um determinado campo, use a notação de ponto:
record_name.field_name
Por exemplo, faça referência ao campo commission_pct do registro emp_record desta
forma:
emp_record.commission_pct
Em seguida, você poderá designar um valor ao campo do registro:
emp_record.commission_pct:= .35;
Designando Valores a Registros
Com a instrução SELECT ou FETCH, é possível designar uma lista de valores comuns a um
registro. Certifique-se de que os nomes de colunas aparecem na mesma ordem que os campos
do seu registro. Você também pode designar um registro a outro se ambos tiverem tipos de
dados correspondentes. Um registro do tipo employees%ROWTYPE e um tipo de registro
definido pelo usuário com campos análogos da tabela employees terão o mesmo tipo de
dados. Portanto, se um registro definido pelo usuário contiver campos semelhantes aos de um
registro %ROWTYPE, você poderá designar esse registro definido pelo usuário ao registro
%ROWTYPE.
DECLARE
TYPE t_rec IS RECORD
(v_sal number(8),
v_minsal number(8) default 1000,
v_hire_date employees.hire_date%type,
v_rec1 employees%rowtype);
v_myrec t_rec;
BEGIN
v_myrec.v_sal := v_myrec.v_minsal + 500;
v_myrec.v_hire_date := sysdate;
SELECT * INTO v_myrec.v_rec1
FROM employees WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(v_myrec.v_rec1.last_name ||' '||
to_char(v_myrec.v_hire_date) ||' '|| to_char(v_myrec.v_sal));
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Agenda
Como mencionado anteriormente, os conjuntos PL/SQL são usados quando você deseja
armazenar valores do mesmo tipo de dados. Esse tipo de dados também pode ser do tipo
composto (como registros).
Portanto, os conjuntos são usados para tratar os dados como uma unidade única. Existem três
tipos de conjuntos:
• Array associativo
• Tabela aninhada
• VARRAY
Observação: Desses três conjuntos, o array associativo é o foco desta lição. A tabela aninhada
e VARRARY são apresentados apenas com a finalidade de comparação. Esses dois conjuntos
são abordados em detalhes no curso Oracle Database 10g: Advanced PL/SQL ou Oracle
Database 11g: Advanced PL/SQL (conforme for adequado para a versão que você estiver
usando).
Chave Valores
1 JONES
2 HARDEY
3 MADURO
4 KRAMER
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
1 2
Coluna de chave ---- Coluna de valores ----
exclusiva
... ... <ou> ...
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
1 TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table%ROWTYPE
| INDEX BY PLS_INTEGER | BINARY_INTEGER
| VARCHAR2(<size>);
2 identifier type_name;
Exemplo:
...
TYPE ename_table_type IS TABLE OF
employees.last_name%TYPE
INDEX BY PLS_INTEGER;
...
ename_table ename_table_type;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Observação: A constraint NOT NULL impede que nulos sejam designados ao array
associativo.
Exemplo
No exemplo, um array associativo com o nome de variável ename_table é declarado para
armazenar os sobrenomes dos funcionários.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Método Descrição
EXISTS(n) Retorna TRUE caso o elemento enésimo exista em um array associativo
COUNT Retorna o número de elementos que um array associativo contenha atualmente
FIRST • Retorna o primeiro (o menor) número de índice em um array associativo
• Retorna NULL se o array associativo estiver vazio
LAST • Retorna o último (o maior) número de índice em um array associativo
• Retorna NULL se o array associativo estiver vazio
PRIOR(n) Retorna o número de índice que precede o índice n em um array associativo
NEXT(n) Retorna o número de índice que sucede o índice n em um array associativo
DELETE • DELETE remove todos os elementos de um array associativo.
• DELETE(n) remove o enésimo elemento de um array associativo.
• DELETE(m, n) remove todos os elementos na faixa m ... n de um array
associativo.
Oracle Database: Fundamentos de PL/SQL 6 - 22
Opção da Tabela de Registros INDEX BY
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
TYPE emp_table_type IS TABLE OF
employees%ROWTYPE INDEX BY PLS_INTEGER;
my_emp_table emp_table_type;
max_count NUMBER(3):= 104;
BEGIN
FOR i IN 100..max_count
LOOP
SELECT * INTO my_emp_table(i) FROM employees
WHERE employee_id = i;
END LOOP;
FOR i IN my_emp_table.FIRST..my_emp_table.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(my_emp_table(i).last_name);
END LOOP;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
2 GB no
máximo
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tabelas Aninhadas
A funcionalidade das tabelas aninhadas é semelhante à dos arrays associativos; no entanto, há
diferenças na implementação da tabela aninhada.
• Uma tabela aninhada é um tipo de dados válido em uma tabela em nível de esquema, mas
um array associativo não é. Portanto, ao contrário dos arrays associativos, as tabelas
aninhadas podem ser armazenadas no banco de dados.
• O tamanho de uma tabela aninhada pode aumentar dinamicamente, embora o tamanho
máximo seja de 2 GB.
• A “chave” não pode ter um valor negativo (ao contrário do array associativo). Embora
seja feita uma referência à primeira coluna como chave, não há chave em uma tabela
aninhada. Há uma coluna com números.
• Os elementos podem ser deletados de qualquer lugar de uma tabela aninhada deixando a
tabela desordenada com “chaves” não seqüenciais. As linhas de uma tabela aninhada não
estão em uma ordem específica.
• Se você recuperar valores de uma tabela aninhada, as linhas receberão subscripts
consecutivos, começando em 1.
Sintaxe
TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table.%ROWTYPE
Oracle Database: Fundamentos de PL/SQL 6 - 25
Tabelas Aninhadas (continuação)
Exemplo:
TYPE location_type IS TABLE OF locations.city%TYPE;
offices location_type;
Se você não inicializar uma tabela aninhada, ela será inicializada automaticamente como
NULL. Você pode inicializar a tabela aninhada offices usando um construtor:
offices := location_type('Bombay', 'Tokyo','Singapore',
'Oxford');
DECLARE
TYPE location_type IS TABLE OF locations.city%TYPE;
offices location_type;
table_count NUMBER;
BEGIN
offices := location_type('Bombay', 'Tokyo','Singapore',
'Oxford');
FOR i in 1.. offices.count() LOOP
DBMS_OUTPUT.PUT_LINE(offices(i));
END LOOP;
END;
/
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
10 Tokyo
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
VARRAY
Um array de tamanho variável (VARRAY) é semelhante a um array associativo, a diferença é
que um VARRAY tem restrição de tamanho.
• Um VARRAY é válido em uma tabela em nível de esquema.
• Itens do tipo VARRAY são chamados de VARRAYs.
• Os VARRAYs têm um limite superior fixo. Você deverá especificar o limite superior ao
declará-los. Essa característica é semelhante à dos arrays na linguagem C. O tamanho
máximo de um VARRAY é de 2 GB, como nas tabelas aninhadas.
• A diferença entre a tabela aninhada e o VARRAY é o modo de armazenamento físico. Os
elementos de um VARRAY são armazenados em linha com os dados da tabela, exceto se o
tamanho do VARRAY for superior a 4 KB. Compare-os com as tabelas aninhadas, que são
sempre armazenadas fora da linha.
• Com o código SQL, é possível criar um tipo VARRAY no banco de dados.
Exemplo:
TYPE location_type IS VARRAY(3) OF locations.city%TYPE;
offices location_type;
O tamanho desse VARRAY é restrito a 3. Você pode inicializar um VARRAY usando
construtores. Se você tentar inicializar o VARRAY com mais de três elementos, será exibida a
mensagem de erro “Subscript outside of limit”.
Array associativo
Organizado Organizado
pelo índice pelo índice
PLS_INTEGER 1 2 3 4 5 6 a f i o t w VARCHAR2
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a, b
Vantagens do Uso do Atributo %ROWTYPE
Use o atributo %ROWTYPE quando você não tiver certeza da estrutura da tabela subjacente do
banco de dados.
A principal vantagem de usar %ROWTYPE é que ele simplifica a manutenção. A utilização de
%ROWTYPE assegura que os tipos de dados das variáveis declaradas com esse atributo serão
dinamicamente alterados caso a tabela subjacente seja alterada. Se uma instrução DDL alterar
as colunas de uma tabela, a unidade do programa PL/SQL será invalidada. Quando o programa
for recompilado, ele refletirá automaticamente o novo formato de tabela.
O atributo %ROWTYPE é particularmente útil se você quiser recuperar uma linha inteira de uma
tabela. Na ausência desse atributo, você teria que declarar uma variável para cada coluna
recuperada pela instrução SELECT.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Um registro PL/SQL é um conjunto de campos individuais que representam uma linha de uma
tabela. Usando registros, você pode agrupar os dados em uma estrutura e, posteriormente,
manipular essa estrutura como uma entidade ou unidade lógica. Isso ajuda a diminuir a
codificação e facilita a compreensão e a manutenção do código.
Assim como os registros PL/SQL, um conjunto PL/SQL é outro tipo de dados composto. Os
conjuntos PL/SQL incluem:
• Arrays associativos (também conhecidos como tabelas INDEX BY). Eles são objetos do
tipo TABLE e são semelhantes às tabelas do banco de dados, mas com uma pequena
diferença. As chamadas tabelas INDEX BY usam uma chave primária para prover acesso
às linhas de modo semelhante a arrays. O tamanho de um array associativo não tem
restrição.
• Tabelas aninhadas. A chave de tabelas aninhadas não pode ter um valor negativo, ao
contrário das tabelas INDEX BY. A chave também deve estar em uma sequência.
• Arrays de tamanho variável (VARRAY). Um VARRAY é semelhante a um array
associativo, a diferença é que um VARRAY tem restrição de tamanho.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você aprendeu sobre os cursores implícitos que são criados automaticamente pelo código
PL/SQL quando você executa uma instrução SQL SELECT ou DML. Nesta lição, você
conhecerá os cursores explícitos. Você aprenderá a diferenciar os cursores implícitos dos
explícitos. Também será ensinado a declarar e controlar cursores simples, bem como cursores
com parâmetros.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Cursores
O Oracle Server usa áreas de trabalho (chamadas de áreas SQL privadas) para executar
instruções SQL e armazenar informações sobre o processamento. Você pode usar cursores
explícitos para nomear uma área SQL privada e para acessar as informações armazenadas nela.
O Oracle Server abre implicitamente um cursor para processar cada instrução SQL não
associada a um cursor declarado explicitamente. Com o código PL/SQL, é possível fazer
referência ao cursor implícito mais recente como o cursor SQL.
Tabela
100 King AD_PRES
101 Kochhar AD_VP
102 De Haan AD_VP
. . .
. . .
. . .
139 Seo ST_CLERK
140 Patel ST_CLERK
Conjunto ativo
. . .
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Não
Sim
DECLARE OPEN FETCH VAZIO? CLOSE
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
1 Abra o cursor.
Ponteiro
do cursor
Ponteiro
3 Feche o cursor. do cursor
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
CURSOR cursor_name IS
select_statement;
Exemplos:
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
DECLARE
v_locid NUMBER:= 1700;
CURSOR c_dept_cursor IS
SELECT * FROM departments
WHERE location_id = v_locid;
...
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Declarando o Cursor
A sintaxe para declarar um cursor é mostrada no slide. Na sintaxe:
cursor_name É um identificador PL/SQL
select_statement É uma instrução SELECT sem uma cláusula INTO
O conjunto ativo de um cursor é determinado pela instrução SELECT na declaração do cursor. É
obrigatória a existência de uma cláusula INTO para uma instrução SELECT no código PL/SQL.
Entretanto, observe que a instrução SELECT na declaração do cursor não pode ter uma cláusula
INTO. Isso acontece porque você está apenas definindo um cursor na seção declarativa e não
recuperando linhas para dentro do cursor.
Observação
• Não inclua a cláusula INTO na declaração do cursor porque ela aparecerá mais tarde na
instrução FETCH.
• Se você deseja que as linhas sejam processadas em uma sequência específica, use a
cláusula ORDER BY na consulta.
• O cursor pode ser qualquer instrução SELECT válida, incluindo joins, subconsultas etc.
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
...
BEGIN
OPEN c_emp_cursor;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Abrindo o Cursor
A instruçãoOPEN executa a consulta associada ao cursor, identifica o conjunto ativo e posiciona
o cursor na primeira linha. A instrução OPEN é incluída na seção executável do bloco PL/SQL.
OPEN é uma instrução executável que realiza as seguintes operações:
1. Aloca memória dinamicamente para uma área de contexto
2. Efetua parse da instrução SELECT
3. Associa as variáveis de entrada (define os valores para as variáveis de entrada obtendo seus
endereços de memória)
4. Identifica o conjunto ativo (o conjunto de linhas que satisfaz os critérios de pesquisa). As
linhas do conjunto ativo não são recuperadas em variáveis quando a instrução OPEN é
executada. Mais especificamente, é a instrução FETCH que recupera as linhas do cursor
nas variáveis.
5. Posiciona o ponteiro na primeira linha do conjunto ativo.
Observação: Se nenhuma linha for retornada pela consulta quando o cursor for aberto, o código
PL/SQL não gerará uma exceção. Você pode saber o número de linhas retornadas com um
cursor explícito, usando o atributo <cursor_name>%ROWCOUNT.
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;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
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;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
...
LOOP
FETCH c_emp_cursor INTO empno, lname;
EXIT WHEN c_emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
END LOOP;
CLOSE c_emp_cursor;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Fechando o Cursor
A instrução CLOSE desativa o cursor, libera a área de contexto e remove a definição do conjunto
ativo. Feche o cursor após concluir o processamento da instrução FETCH. Você poderá reabrir o
cursor se necessário. Um cursor só poderá ser reaberto se ele tiver sido fechado. Se você tentar
extrair dados de um cursor com o comando fetch após ele ter sido fechado, uma exceção
INVALID_CURSOR será gerada.
Observação: Embora seja possível encerrar o bloco PL/SQL sem fechar os cursores, convém
que seja um hábito fechar todos os cursores declarados explicitamente para liberar recursos.
Existe um limite máximo no número de cursores abertos por sessão, que é determinado pelo
parâmetro OPEN_CURSORS no arquivo de parâmetros do banco de dados. (OPEN_CURSORS =
50 por default.)
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Cursores e Registros
Você já viu que é possível definir registros que tenham a estrutura de colunas em uma tabela.
Também é possível definir um registro baseado na lista selecionada de colunas de um cursor
explícito. Isso é conveniente para o processamento das linhas do conjunto ativo porque é
possível simplesmente extrair (fetch) para dentro do registro. Portanto, os valores das linhas são
carregados diretamente nos campos correspondentes do registro.
Sintaxe:
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
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;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Atributo %ISOPEN
• Só é possível extrair linhas quando o cursor está aberto. Use o atributo de cursor %ISOPEN
para determinar se o cursor está aberto.
• Extraia linhas em um loop. Use os atributos de cursores para determinar quando sair do
loop.
• Use o atributo de cursor %ROWCOUNT para fazer o seguinte:
- Processar um número exato de linhas.
- Extrair as linhas de um loop com o comando fetch e determinar quando sair do loop.
Observação: %ISOPEN retorna o status do cursor: TRUE se estiver aberto e FALSE se não
estiver aberto.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
CURSOR cursor_name
[(parameter_name datatype, ...)]
IS
select_statement;
OPEN cursor_name(parameter_value,.....) ;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
A notação do parâmetro não oferece melhor funcionalidade; ela simplesmente permite que você
especifique valores de entrada com facilidade e clareza. Isso será especialmente útil quando o
mesmo cursor for referido de forma repetitiva.
Oracle Database: Fundamentos de PL/SQL 7 - 24
Cursores com Parâmetros
DECLARE
CURSOR c_emp_cursor (deptno NUMBER) IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = deptno;
...
BEGIN
OPEN c_emp_cursor (10);
...
CLOSE c_emp_cursor;
OPEN c_emp_cursor (20);
...
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
WHERE CURRENT OF cursor ;
• Use cursores para atualizar ou deletar a linha atual.
• Inclua a cláusula FOR UPDATE na consulta do cursor para
bloquear as linhas primeiro.
• Use a cláusula WHERE CURRENT OF para fazer referência
à linha atual de um cursor explícito.
UPDATE employees
SET salary = ...
WHERE CURRENT OF c_emp_cursor;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
O Oracle Server usa áreas de trabalho para executar instruções SQL e armazenar as informações
de processamento. Você pode usar uma estrutura PL/SQL chamada cursor para nomear uma
área de trabalho e acessar as informações armazenadas. Há dois tipos de cursores: implícitos e
explícitos. O bloco PL/SQL declara implicitamente um cursor para todas as instruções de
manipulação de dados SQL, incluindo consultas que retornam apenas uma linha. No caso das
consultas que retornam várias linhas, você deve declarar explicitamente um cursor para
processar as linhas individualmente.
Os cursores explícitos e as variáveis de cursor têm quatro atributos: %FOUND, %ISOPEN,
%NOTFOUND e %ROWCOUNT. Quando anexados ao nome da variável do cursor, esses atributos
retornam informações úteis sobre a execução de uma instrução SQL. É possível usar atributos de
cursor em instruções procedurais, mas não em instruções SQL.
Use loops simples ou loops FOR de cursor para operar várias linhas extraídas pelo cursor. Se
usar loops simples, você terá de usar os comandos open, fetch e close com o cursor; no entanto,
os loops FOR de cursor fazem isso implicitamente. Se estiver atualizando ou deletando linhas,
bloqueie as linhas com a cláusula FOR UPDATE. Isso assegura que os dados que você está
usando não sejam atualizados por outra sessão depois que você abriu o cursor. Use uma cláusula
WHERE CURRENT OF junto com a cláusula FOR UPDATE para fazer referência à linha atual
extraída pelo cursor.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você aprendeu a criar blocos PL/SQL contendo uma seção declarativa e uma seção executável.
Todos os códigos SQL e PL/SQL que precisam ser executados são gravados no bloco
executável.
Até agora, pressupomos que o código funcionará bem se tomarmos cuidado com os erros que
ocorrem no momento da compilação. No entanto, o código pode causar alguns erros inesperados
durante o runtime. Nesta lição, você aprenderá a tratar esses erros no bloco PL/SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
O código não funciona como esperado. Você esperava que a instrução SELECT recuperasse
apenas uma linha; entretanto, ela recupera várias linhas. Esses erros que ocorrem durante o
runtime são denominados exceções. Se ocorrer uma exceção, o bloco PL/SQL será encerrado. É
possível tratar essas exceções no bloco PL/SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
A
exceção
foi inter- Encerre
ceptada? Não abruptamente.
Sim
Encerre
normalmente.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tratando Exceções
Interceptando uma Exceção
Inclua uma seção EXCEPTION no programa PL/SQL para interceptar exceções. Se a exceção
for gerada na seção executável do bloco, o processamento será ramificado para o handler de
exceção correspondente na seção de exceções do bloco. Se o código PL/SQL tratar a exceção
com sucesso, ela não será propagada para o bloco que a contém ou para o ambiente de chamada.
O bloco PL/SQL será encerrado com sucesso.
Propagando uma Exceção
Se a exceção for gerada na seção executável do bloco e não houver um handler de exceções
correspondente, o bloco PL/SQL será encerrado com falha e a exceção se propagará a um bloco
que o contém ou ao ambiente de chamada. O ambiente de chamada pode ser qualquer aplicação,
como o SQL*Plus, que chame o programa PL/SQL.
•
•
Predefinidas no Oracle Server
Não Predefinidas no Oracle Server } Geradas
implicitamente
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Tipos de Exceções
Há três tipos de exceções.
Exceção Descrição Instruções para Tratamento
Erro predefinido do Um dos, Você não precisa declarar essas
Oracle Server aproximadamente, 20 exceções. Elas são predefinidas pelo
erros que ocorrem com Oracle Server e são emitidas
mais freqüência na implicitamente.
linguagem PL/SQL
Erro não Qualquer outro erro Você precisa declará-los na seção
predefinido do padrão do Oracle Server declarativa; o servidor Oracle gera o
Oracle Server erro implicitamente, e você pode
detectar o erro no handler de
exceção.
Erro definido pelo Uma condição que o Você precisa declarar dentro da
usuário desenvolvedor definiu seção declarativa e emitir
como anormal explicitamente.
Observação: Algumas ferramentas de aplicações com PL/SQL no lado cliente (como o Oracle
Developer Forms) possuem suas próprias exceções.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
statement2;
. . .
[WHEN exception3 [OR exception4 . . .] THEN
statement1;
statement2;
. . .]
[WHEN OTHERS THEN
statement1;
statement2;
. . .]
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Fazer
Declarar Associar
Referência
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
error_code NUMBER;
error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
error_code := SQLCODE ;
error_message := SQLERRM ;
INSERT INTO errors (e_user, e_date, error_code,
error_message) VALUES(USER,SYSDATE,error_code,
error_message);
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
. . .
e_no_rows exception;
e_integrity exception;
PRAGMA EXCEPTION_INIT (e_integrity, -2292);
BEGIN
FOR c_record IN emp_cursor LOOP
BEGIN
Os sub-blocos podem SELECT ...
tratar uma exceção ou UPDATE ...
transmiti-la para o IF SQL%NOTFOUND THEN
bloco que os contém. RAISE e_no_rows;
END IF;
END;
END LOOP;
EXCEPTION
WHEN e_integrity THEN ...
WHEN e_no_rows THEN ...
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sintaxe:
raise_application_error (error_number,
message[, {TRUE | FALSE}]);
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Procedure RAISE_APPLICATION_ERROR
Use o procedure RAISE_APPLICATION_ERROR para comunicar interativamente uma
exceção predefinida, retornando uma mensagem e um código de erro não padrão. Com
RAISE_APPLICATION_ERROR, é possível reportar erros à aplicação e evitar o retorno de
exceções não tratadas.
Na sintaxe:
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Seção executável:
BEGIN
...
DELETE FROM employees
WHERE manager_id = v_mgr;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR (-20202,
'This is not a valid manager');
END IF;
...
Seção de exceções:
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR (-20201,
'Manager is not a valid employee.');
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a
É possível interceptar qualquer erro, incluindo um handler correspondente dentro da seção de
tratamento de exceções do bloco PL/SQL. Cada handler consiste em uma cláusula WHEN, que
especifica um nome de exceção, seguida de uma sequência de instruções a serem executadas
quando essa exceção for gerada. É possível incluir inúmeros handlers dentro de uma seção
EXCEPTION para tratar exceções específicas. No entanto, não é possível ter vários handlers
para uma única exceção.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
Nesta lição, você aprendeu a lidar com diferentes tipos de exceções. No código PL/SQL, uma
condição de advertência ou erro durante o runtime é chamada de exceção. As exceções
predefinidas são condições de erro que foram definidas pelo Oracle Server. As exceções não
predefinidas podem ser quaisquer erros padrão do Oracle Server. As exceções definidas pelo
usuário são exceções específicas da sua aplicação. A função PRAGMA EXCEPTION_INIT pode
ser usada para associar um nome de exceção declarada a um erro do Oracle Server.
Você pode definir suas próprias exceções na parte declarativa de um bloco PL/SQL. Por
exemplo, você pode definir a exceção INSUFFICIENT_FUNDS para identificar contas
bancárias com saldo insuficiente.
Se ocorrer um erro, será gerada uma exceção. A execução normal é interrompida e o controle é
transferido para a seção de tratamento de exceções do bloco PL/SQL. As exceções internas são
geradas implicitamente (automaticamente) pelo sistema durante o runtime; contudo, as exceções
definidas pelo usuário devem ser geradas explicitamente. Para tratar as exceções geradas, crie
rotinas separadas chamadas handlers de exceções.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Você já aprendeu sobre os blocos anônimos. Esta lição apresenta os blocos nomeados, também
chamados de subprogramas. Os procedures e as funções são denominados subprogramas
PL/SQL. Nesta lição, você aprenderá a fazer a distinção entre blocos anônimos e subprogramas.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Procedures e Funções
Até este ponto, blocos anônimos foram os únicos exemplos do código PL/SQL abordado neste
curso. Como o nome indica, os blocos anônimos são blocos PL/SQL executáveis não nomeados.
Como não são nomeados, eles não podem ser reutilizados nem armazenados para uso posterior.
Procedures e funções são blocos PL/SQL nomeados, também conhecidos como subprogramas.
Esses subprogramas são compilados e armazenados no banco de dados. A estrutura de bloco dos
subprogramas é semelhante à estrutura dos blocos anônimos. Os subprogramas podem ser
declarados não apenas no nível do esquema, mas também dentro de qualquer outro bloco
PL/SQL. Um subprograma contém as seguintes seções:
• Seção declarativa:Os subprogramas podem ter uma seção declarativa opcional. No
entanto, ao contrário dos blocos anônimos, a seção declarativa de um subprograma não
começa com a palavra-chave DECLARE. A seção declarativa opcional usa a palavra-chave
IS ou AS na declaração do subprograma.
• Seção executável: Esta é a seção obrigatória do subprograma, que contém a
implementação da lógica de negócios. Observando o código desta seção, você pode
facilmente determinar a funcionalidade do subprograma. Esta seção começa e termina com
as palavras-chave BEGIN e END, respectivamente.
• Seção de exceções: Esta é uma seção opcional que é incluída para tratar exceções.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Procedure: Sintaxe
O slide mostra a sintaxe para criar procedures. Na sintaxe:
procedure_name É o nome do procedure a ser criado
argument É o nome dado ao parâmetro do procedure. Cada argumento é
associado a um modo e a um tipo de dados. É possível haver
inúmeros argumentos separados por vírgula.
mode Modo do argumento:
IN (default)
OUT
IN OUT
datatype É o tipo de dados do parâmetro associado. O tipo de dados dos
parâmetros não pode ter um tamanho explícito; em vez disso, use
%TYPE.
Procedure_body É o bloco PL/SQL que compõe o código.
...
CREATE TABLE dept AS SELECT * FROM departments;
CREATE PROCEDURE add_dept IS
v_dept_id dept.department_id%TYPE;
v_dept_name dept.department_name%TYPE;
BEGIN
v_dept_id:=280;
v_dept_name:='ST-Curriculum';
INSERT INTO dept(department_id,department_name)
VALUES(v_dept_id,v_dept_name);
DBMS_OUTPUT.PUT_LINE(' Inserted '|| SQL%ROWCOUNT
||' row ');
END;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Criando um Procedure
No código do exemplo, o procedure add_dept insere um novo departamento com o ID 280 e
o nome ST-Curriculum.
Além disso, o exemplo mostra o seguinte:
• A seção declarativa de um procedure começa imediatamente após a declaração do
procedure, e não com a palavra-chave DECLARE.
• O procedure declara duas variáveis: dept_id e dept_name.
• O procedure usa o atributo de cursor implícito ou o atributo SQL SQL%ROWCOUNT para
verificar se a linha foi inserida com sucesso. O valor 1 deverá ser retornado nesse caso.
Observação: Consulte a página a seguir para obter mais informações sobre o exemplo.
...
BEGIN
add_dept;
END;
/
SELECT department_id, department_name FROM dept
WHERE department_id=280;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Chamando o Procedure
O slide mostra como chamar um procedure de um bloco anônimo. Você deve incluir a chamada
ao procedure na seção executável do bloco anônimo. Da mesma forma, é possível chamar o
procedure a partir de qualquer aplicação, como uma aplicação do Forms ou uma aplicação Java.
A instrução SELECT no código verifica se a linha foi inserida com sucesso.
Também é possível chamar um procedure com a instrução SQL CALL <procedure_name>.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Função: Sintaxe
O slide mostra a sintaxe para criar uma função. Na sintaxe:
function_name É o nome da função a ser criada
argument É o nome dado ao parâmetro da função (cada argumento é associado
a um modo e a um tipo de dados. É possível haver inúmeros
argumentos separados por vírgula. Você especifica o argumento ao
chamar a função).
mode É o tipo de parâmetro (apenas os parâmetros IN devem ser
declarados.)
datatype É o tipo de dados do parâmetro associado
RETURN datatype É o tipo de dados do valor retornado pela função
function_body É o bloco PL/SQL que compõe o código da função
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Função: Exemplo
A função check_sal foi criada para determinar se o salário de um funcionário específico é
maior ou menor que a média de salário de todos os funcionários que trabalham no mesmo
departamento. A função retornará TRUE se o salário do funcionário for maior que o salário
médio dos funcionários do departamento; se não for, ela retornará FALSE. A função retornará
NULL se uma exceção NO_DATA_FOUND for gerada.
Observe que a função verifica o funcionário cujo ID é 205. A função foi codificada para
verificar apenas esse ID de funcionário. Se desejar verificar qualquer outro funcionário, você
precisará modificar a função propriamente dita. Para resolver esse problema, declare a função de
uma forma em que ela aceite um argumento. Em seguida, você poderá especificar o ID do
funcionário como um parâmetro.
BEGIN
IF (check_sal IS NULL) THEN
DBMS_OUTPUT.PUT_LINE('The function returned
NULL due to exception');
ELSIF (check_sal) THEN
DBMS_OUTPUT.PUT_LINE('Salary > average');
ELSE
DBMS_OUTPUT.PUT_LINE('Salary < average');
END IF;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Chamando a Função
Inclua a chamada na função na seção executável do bloco anônimo.
A função é chamada como parte de uma instrução. Lembre-se de que a função check_sal
retorna Boolean ou NULL. Dessa forma, a chamada à função é incluída como a expressão
condicional para o bloco IF.
Observação: Você pode usar o comando DESCRIBE para verificar os argumentos e retornar o
tipo da função, como no seguinte exemplo:
DESCRIBE check_sal;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Subprogramas:
a. São blocos PL/SQL nomeados e podem ser chamados por
outras aplicações
b. São compilados apenas uma vez
c. São armazenados no banco de dados
d. Não precisam retornar valores se forem funções
e. Podem aceitar parâmetros
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Resposta: a, b, c, e
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
É possível usar blocos anônimos para criar qualquer funcionalidade em blocos PL/SQL. No
entanto, a restrição principal em relação aos blocos anônimos é que eles não são armazenados e,
consequentemente, não podem ser reutilizados.
Em vez de criar blocos anônimos, você pode criar subprogramas PL/SQL. Funções e procedures
são considerados subprogramas, que são blocos PL/SQL nomeados. Os subprogramas expressam
lógica reutilizável por meio dos parâmetros. A estrutura de um procedure ou de uma função é
semelhante à estrutura de um bloco anônimo. Esses subprogramas são armazenados no banco de
dados e, portanto, são reutilizáveis.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2) Crie uma conexão com o banco de dados utilizando as seguintes informações (Dica:
Marque a caixa de seleção Save Password):
a) Nome da Conexão: MyConnection
b) Nome de usuário: ora41
c) Senha: ora41
d) Nome do host: localhost
8) Selecione Database > Worksheet Parameters. Na caixa de texto “Select default path
to look for scripts”, use o botão Browse para selecionar a pasta
/home/oracle/labs/plsf. Essa pasta contém os scripts do código de exemplo,
os scripts de laboratório e os scripts de solução dos exercícios usados neste curso. Em
seguida, na janela Preferences, clique em OK para salvar a configuração Worksheet
Parameters.
2) Crie uma conexão com o banco de dados utilizando as seguintes informações (Dica:
Marque a caixa de seleção Save Password):
a) Nome da Conexão: MyConnection
b) Nome de usuário: ora41
c) Senha: ora41
d) Nome do host: localhost
e) Porta: 1521
f) SID: orcl
Por exemplo, quando você pressionar F9, os resultados exibidos serão semelhantes a
estes:
8) Selecione Database > Worksheet Parameters. Na caixa de texto “Select default path
to look for scripts”, use o botão Browse para selecionar a pasta
/home/oracle/labs/plsf.
b) Você também pode usar a tab Files para navegar pelas pastas a fim de abrir os
arquivos de script.
c) Usando a janela Open e a tab Files, navegue pelas pastas e abra um arquivo de
script sem executar o código.
d) Feche a Planilha SQL.
Para fechar qualquer tab da Planilha SQL, clique em X na tab, como
mostrado aqui:
a) BEGIN
END;
b) DECLARE
v_amount INTEGER(10);
END;
c) DECLARE
BEGIN
END;
d) DECLARE
v_amount INTEGER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE(amount);
END;
2) Crie e execute um bloco anônimo simples que exiba a saída “Hello World”. Execute e
salve esse script como lab_01_02_soln.sql.
a) BEGIN
END;
b) DECLARE
v_amount INTEGER(10);
END;
c) DECLARE
BEGIN
END;
d) DECLARE
v_amount INTEGER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE(amount);
END;
2) Crie e execute um bloco anônimo simples que exiba a saída “Hello World”. Execute e
salve esse script como lab_01_02_soln.sql.
Clique no botão Save. Selecione a pasta em que deseja salvar o arquivo. Insira
lab_01_02_soln.sql como o nome do arquivo e clique em Save.
DECLARE
v_today DATE:=SYSDATE;
v_tomorrow v_today%TYPE;
c) Na seção executável:
1. Inicialize a variável v_tomorrow com uma expressão que calcula a data de
amanhã (adicione um ao valor em v_today)
2. Imprima o valor de v_today e v_tomorrow após imprimir “Hello World”
BEGIN
v_tomorrow:=v_today +1;
DBMS_OUTPUT.PUT_LINE(' Hello World ');
DBMS_OUTPUT.PUT_LINE('TODAY IS : '|| v_today);
DBMS_OUTPUT.PUT_LINE('TOMORROW IS : ' || v_tomorrow);
END;
c) Encerre o bloco PL/SQL com “/” e exiba o valor das variáveis de bind usando o
comando PRINT.
/
PRINT b_basic_percent
PRINT b_pf_percent
OU
DECLARE
v_weight NUMBER(3) := 600;
v_message VARCHAR2(255) := 'Product 10012';
BEGIN
DECLARE
v_weight NUMBER(3) := 1;
v_message VARCHAR2(255) := 'Product 11001';
v_new_locn VARCHAR2(50) := 'Europe';
BEGIN
v_weight := v_weight + 1;
v_new_locn := 'Western ' || v_new_locn;
1
END;
v_weight := v_weight + 1;
v_message := v_message || ' is in stock';
v_new_locn := 'Western ' || v_new_locn;
2
END;
/
1) Avalie o bloco PL/SQL anterior e determine o tipo de dados e o valor de cada uma
das variáveis a seguir, de acordo com as regras de escopo.
a) O valor de v_weight na posição 1 é:
DECLARE
v_customer VARCHAR2(50) := 'Womansport';
v_credit_rating VARCHAR2(50) := 'EXCELLENT';
BEGIN
DECLARE
v_customer NUMBER(7) := 201;
v_name VARCHAR2(25) := 'Unisports';
BEGIN
v_credit_rating :='GOOD';
…
END;
…
END;
2) No bloco PL/SQL anterior, determine os valores e tipos de dados para cada um dos
seguintes casos:
a) O valor de v_customer no bloco aninhado é:
3) Use a mesma sessão usada para executar os exercícios da lição “Declarando Variáveis
PL/SQL”. Se você abriu uma nova sessão, execute lab_02_05_soln.sql Em
seguida, edite lab_02_05_soln.sql como se segue:
a) Use a sintaxe de comentário de uma única linha para incluir comentários nas
linhas que criam as variáveis de bind e ative SERVEROUTPUT.
b) Use comentários de várias linhas na seção executável para comentar as linhas que
designam valores às variáveis de bind.
c) Na seção declarativa:
1. Declare e inicialize duas variáveis temporárias para substituir as variáveis
de bind nas linhas comentadas.
2. Declare duas variáveis adicionais: v_fname do tipo VARCHAR2 e
tamanho 15, e v_emp_sal do tipo NUMBER e tamanho 10.
e) Mude a linha que exibe “Hello World” para exibir “Hello” e o nome. Em seguida,
comente as linhas que exibem as datas e imprima as variáveis de bind.
DECLARE
v_weight NUMBER(3) := 600;
v_message VARCHAR2(255) := 'Product 10012';
BEGIN
DECLARE
v_weight NUMBER(3) := 1;
v_message VARCHAR2(255) := 'Product 11001';
v_new_locn VARCHAR2(50) := 'Europe';
BEGIN
v_weight := v_weight + 1;
v_new_locn := 'Western ' || v_new_locn;
1
END;
v_weight := v_weight + 1;
v_message := v_message || ' is in stock';
v_new_locn := 'Western ' || v_new_locn;
2
END;
/
1) Avalie o bloco PL/SQL anterior e determine o tipo de dados e o valor de cada uma
das variáveis a seguir, de acordo com as regras de escopo.
a) O valor dev_weight na posição 1 é:
2
O tipo de dados é NUMBER.
b) O valor de v_new_locn na posição 1 é:
Western Europe
O tipo de dado é VARCHAR2.
c) O valor dev_weight na posição 2 é:
601
O tipo de dados é NUMBER.
d) O valor de v_message na posição 2 é:
Product 10012 is in stock
O tipo de dado é VARCHAR2.
e) O valor de v_new_locn na posição 2 é:
Inválido pois v_new_locn não é visível fora do sub-bloco
2) No bloco PL/SQL anterior, determine os valores e tipos de dados para cada um dos
seguintes casos:
3) Use a mesma sessão usada para executar os exercícios da lição “Declarando Variáveis
PL/SQL”. Se você abriu uma nova sessão, execute lab_02_05_soln.sql Em
seguida, edite lab_02_05_soln.sql como se segue:
a) Use a sintaxe de comentário de uma única linha para incluir comentários nas
linhas que criam as variáveis de bind e ative SERVEROUTPUT.
/*:b_basic_percent:=45;
:b_pf_percent:=12;*/
c) Na seção declarativa:
1. Declare e inicialize duas variáveis temporárias para substituir as variáveis
de bind nas linhas comentadas.
2. Declare duas variáveis adicionais: v_fname do tipo VARCHAR2 e
tamanho 15, e v_emp_sal do tipo NUMBER e tamanho 10.
DECLARE
v_basic_percent NUMBER:=45;
v_pf_percent NUMBER:=12;
v_fname VARCHAR2(15);
v_emp_sal NUMBER(10);
e) Mude a linha que exibe “Hello World” para exibir “Hello” e o nome. Em seguida,
comente as linhas que exibem as datas e imprima as variáveis de bind.
/
--PRINT b_basic_percent
--PRINT b_basic_percent
3) Na etapa 2, você define location_id como NULL. Crie um bloco PL/SQL que
atualiza location_id como 3000 para o novo departamento.
Observação:Se você concluiu a etapa 2 com sucesso, siga para a etapa 3a. Caso não
tenha concluído com sucesso, execute primeiro o script de solução
/soln/sol_04_02.sql.
a) Inicie o bloco executável com a palavra-chave BEGIN. Inclua a instrução
UPDATE para definir location_id como 3000 para o novo departamento
(dept_id =280).
b) Finalize o bloco executável com a palavra-chaveEND. Encerre o bloco PL/SQL
com “/” e inclua uma instrução SELECT para exibir o departamento que foi
atualizado.
c) Inclua uma instrução DELETE para deletar o departamento adicionado.
d) Execute e salve esse script como lab_04_03_soln.sql. O exemplo de saída
é o seguinte:
DECLARE
v_max_deptno NUMBER;
BEGIN
SELECT MAX(department_id) INTO v_max_deptno FROM
departments;
v_dept_id := 10 + v_max_deptno;
…
INSERT INTO departments (department_id, department_name,
location_id)
VALUES (v_dept_id, v_dept_name, NULL);
d) Use o atributo SQL SQL%ROWCOUNT para exibir o número de linhas que foram
afetadas.
…
/
SELECT * FROM departments WHERE department_id= 280;
3) Na etapa 2, você define location_id como NULL. Crie um bloco PL/SQL que
atualiza location_id como 3000 para o novo departamento.
Observação: Se você concluiu a etapa 2 com sucesso, siga para a etapa 3a. Caso não
tenha concluído com sucesso, execute primeiro o script de solução
/soln/sol_04_02.sql.
a) Inicie o bloco executável com a palavra-chave BEGIN. Inclua a instrução
UPDATE para definir location_id como 3000 para o novo departamento
(dept_id =280).
BEGIN
UPDATE departments SET location_id=3000 WHERE
department_id=280;
END;
/
SELECT * FROM departments WHERE department_id=280;
2) Execute o script lab_05_02.sql. Esse script cria uma tabela emp que é uma
réplica da tabela employees. Ele altera a tabela emp para adicionar uma nova
coluna, stars, do tipo de dados VARCHAR2 e tamanho 50. Crie um bloco PL/SQL
que insere um asterisco na coluna stars para cada $1000 do salário do
funcionário. Salve o script como lab_05_02_soln.sql.
a) Na seção declarativa do bloco, declare uma variável v_empno do tipo
emp.employee_id e inicialize-a com 176. Declare uma variável
v_asterisk do tipo emp.stars e inicialize-a com NULL. Crie uma variável
v_sal do tipo emp.salary..
b) Na seção executável, crie uma lógica para anexar um asterisco (*) à string para
cada US$ 1.000 do salário. Por exemplo, se o funcionário ganhar US$ 8.000, a
BEGIN
FOR i in 1..10 LOOP
IF i = 6 or i = 8 THEN
null;
ELSE
INSERT INTO messages (results)
VALUES (i);
END IF;
END LOOP;
COMMIT;
END;
/
c) Execute uma instrução SELECT para verificar se o seu bloco PL/SQL funcionou.
2) Execute o script lab_05_02.sql. Esse script cria uma tabela emp que é uma
réplica da tabela employees. Ele altera a tabela emp para adicionar uma nova
coluna stars, do tipo de dados VARCHAR2 e tamanho 50. Crie um bloco PL/SQL
que insere um asterisco na coluna starspara cada $1000 do salário do funcionário.
Salve o script como lab_05_02_soln.sql.
a) Na seção declarativa do bloco, declare uma variável v_empno do tipo
emp.employee_id e inicialize-a com 176. Declare uma variável
v_asterisk do tipo emp.stars e inicialize-a com NULL. Crie uma variável
v_sal do tipo emp.salary.
.
DECLARE
v_empno emp.employee_id%TYPE := 176;
v_asterisk emp.stars%TYPE := NULL;
v_sal emp.salary%TYPE;
b) Na seção executável, crie uma lógica para anexar um asterisco (*) à string para
cada US$ 1.000 do salário. Por exemplo, se o funcionário ganhar US$ 8.000, a
string de asteriscos deverá conter oito asteriscos. Se o funcionário ganhar US$
12.500, a string de asteriscos deverá conter 13 asteriscos.
BEGIN
SELECT NVL(ROUND(salary/1000), 0) INTO v_sal
FROM emp WHERE employee_id = v_empno;
FOR i IN 1..v_sal
LOOP
v_asterisk := v_asterisk ||'*';
END LOOP;
d) Exiba a linha da tabela emp para verificar se o seu bloco PL/SQL foi executado
com sucesso.
e) Você pode executar e testar o bloco PL/SQL para os países com os IDs DE, UK e
US.
DEPARTMENT_ID DEPARTMENT_NAME
10 Administration
20 Marketing
30 Purchasing
40 Human Resources
50 Shipping
60 IT
70 Public Relations
80 Sales
90 Executive
100 Finance
3) Modifique o bloco que você criou no Exercício 2 para recuperar todas as informações
sobre cada departamento da tabela departments e exiba as informações. Use um
array associativo com a tabela INDEX BY do método de registros.
a) Carregue o script lab_06_02_soln.sql.
b) Você declarou que o array associativo é do tipo
departments.department_name. Modifique a declaração do array
associativo para armazenar temporariamente o número, o nome e o local de todos
os departamentos. Use o atributo %ROWTYPE.
c) Modifique a instrução SELECT para recuperar todas as informações sobre os
departamentos que estão atualmente na tabela departments e armazene-as no
array associativo.
d) Usando outro loop, recupere as informações sobre os departamentos do array
associativo e exiba-as.
SET SERVEROUTPUT ON
v_country_record countries%ROWTYPE;
BEGIN
SELECT *
INTO v_country_record
FROM countries
WHERE country_id = UPPER(v_countryid);
END;
e) Você pode executar e testar o bloco PL/SQL para os países com os IDs DE, UK e
US.
SET SERVEROUTPUT ON
DECLARE
TYPE dept_table_type is table of
departments.department_name%TYPE
INDEX BY PLS_INTEGER;
my_dept_table dept_table_type;
DEPARTMENT_ID DEPARTMENT_NAME
10 Administration
20 Marketing
30 Purchasing
40 Human Resources
50 Shipping
60 IT
70 Public Relations
80 Sales
90 Executive
100 Finance
BEGIN
FOR i IN 1..f_loop_count
LOOP
v_deptno:=v_deptno+10;
SELECT department_name
INTO my_dept_table(i)
FROM departments
WHERE department_id = v_deptno;
END LOOP;
FOR i IN 1..f_loop_count
LOOP
DBMS_OUTPUT.PUT_LINE (my_dept_table(i));
END LOOP;
END;
3) Modifique o bloco que você criou no Exercício 2 para recuperar todas as informações
sobre cada departamento da tabela departments e exiba as informações. Use um
array associativo com a tabela INDEX BY do método de registros.
a) Carregue o script lab_06_02_soln.sql.
b) Você declarou que o array associativo é do tipo
departments.department_name. Modifique a declaração do array
SET SERVEROUTPUT ON
DECLARE
TYPE dept_table_type is table of departments%ROWTYPE
INDEX BY PLS_INTEGER;
my_dept_table dept_table_type;
f_loop_count NUMBER(2) := 10;
v_deptno NUMBER (4):=0;
BEGIN
FOR i IN 1..f_loop_count
LOOP
v_deptno := v_deptno + 10;
SELECT *
INTO my_dept_table(i)
FROM departments
WHERE department_id = v_deptno;
END LOOP;
FOR i IN 1..f_loop_count
LOOP
DBMS_OUTPUT.PUT_LINE ('Department Number : ' ||
my_dept_table(i).department_id
|| ' Department Name: ' ||
my_dept_table(i).department_name
|| ' Manager Id: '|| my_dept_table(i).manager_id
|| ' Location Id: ' || my_dept_table(i).location_id);
END LOOP;
END;
c) Na seção executável, use o loop de cursor FOR para operar os dados recuperados.
Se o salário do funcionário for menor que 5.000 e se o ID do gerente for 101 ou
124, exiba a mensagem “<<last_name>> Due for a raise.” Caso contrário, exiba a
mensagem “<<last_name>> Not Due for a raise.”
Department ID Message
10 Whalen Due for a raise
20 Hartstein Not Due for a raise
Fay Not Due for a raise
50 Weiss Not Due for a raise
Fripp Not Due for a raise
Kaufling Not Due for a raise
Vollman Not Due for a raise. . .
. . .
OConnell Due for a raise
Grant Due for a raise
80 Russell Not Due for a raise
Partners Not Due for a raise
Errazuriz Not Due for a raise
Cambrault Not Due for a raise
. . .
Livingston Not Due for a raise
Johnson Not Due for a raise
2) Em seguida, crie um bloco PL/SQL que declara e usa dois cursores — um sem
parâmetro e outro com parâmetro. O primeiro cursor recupera o número e o nome do
departamento da tabela departments para todos os departamentos cujo número de
ID é menor que 100. O segundo cursor recebe o número do departamento como um
parâmetro e recupera os detalhes dos funcionários que trabalham nesse departamento
e cujo employee_id é menor que 120.
c) Declare variáveis para reter os valores recuperados de cada cursor. Use o atributo
%TYPE enquanto estiver declarando variáveis.
d) Abra c_dept_cursor e use um loop simples para extrair com o comando fetch
valores para as variáveis declaradas. Exiba o número e o nome do departamento.
Use o atributo de cursor apropriado para sair do loop.
Observação
• Verifique se c_emp_cursor já está aberto antes de abrir o cursor.
• Use os atributos de cursor apropriados para a condição de saída.
• Quando o loop for concluído, imprima uma linha após ter exibido os detalhes
de cada departamento e feche c_emp_cursor.
3) Na seção executável, abra o loop e extraia com o comando fetch os n salários mais
altos e, em seguida, insira-os na tabela top_salaries. Você pode usar um loop
simples para operar os dados. Além disso, tente e use os atributos %ROWCOUNT e
%FOUND para a condição de saída.
Observação: Certifique-se de adicionar uma condição de saída para evitar um loop
infinito.
4) Após fazer a inserção na tabela top_salaries, exiba as linhas com a instrução
SELECT. A saída mostrada representa os cinco maiores salários da tabela
employees.
5) Teste alguns casos especiais como v_num = 0 ou onde v_num seja maior que o
número de funcionários na tabela employees. Esvazie a tabela top_salaries
após cada teste.
DECLARE
v_deptno NUMBER := 10;
CURSOR c_emp_cursor IS
SELECT last_name, salary,manager_id
FROM employees
WHERE department_id = v_deptno;
c) Na seção executável, use o loop de cursor FOR para operar os dados recuperados.
Se o salário do funcionário for menor que 5.000 e se o ID do gerente for 101 ou
124, exiba a mensagem “<<last_name>> Due for a raise.” Caso contrário, exiba a
mensagem “<<last_name>> Not Due for a raise.”
BEGIN
FOR emp_record IN c_emp_cursor
LOOP
IF emp_record.salary < 5000 AND (emp_record.manager_id=101
OR emp_record.manager_id=124) THEN
DBMS_OUTPUT.PUT_LINE (emp_record.last_name || ' Due for
a raise');
ELSE
DBMS_OUTPUT.PUT_LINE (emp_record.last_name || ' Not Due
for a raise');
END IF;
END LOOP;
END;
Department ID Message
10 Whalen Due for a raise
20 Hartstein Not Due for a raise
Fay Not Due for a raise
50 Weiss Not Due for a raise
Fripp Not Due for a raise
Kaufling Not Due for a raise
Vollman Not Due for a raise. . .
. . .
OConnell Due for a raise
Grant Due for a raise
80 Russell Not Due for a raise
Partners Not Due for a raise
Errazuriz Not Due for a raise
Cambrault Not Due for a raise
. . .
Livingston Not Due for a raise
Johnson Not Due for a raise
2) Em seguida, crie um bloco PL/SQL que declara e usa dois cursores — um sem
parâmetro e outro com parâmetro. O primeiro cursor recupera o número e o nome do
departamento da tabela departments para todos os departamentos cujo número de
ID é menor que 100. O segundo cursor recebe o número do departamento como um
parâmetro e recupera os detalhes dos funcionários que trabalham nesse departamento
e cujo employee_id é menor que 120.
a) Declare um cursor c_dept_cursor para recuperar department_id e
department_name dos departamentos com department_id menor que
100. Ordene por department_id.
DECLARE
CURSOR c_dept_cursor IS
SELECT department_id,department_name
FROM departments
WHERE department_id < 100
ORDER BY department_id;
c) Declare variáveis para reter os valores recuperados de cada cursor. Use o atributo
%TYPE enquanto estiver declarando variáveis.
v_current_deptno departments.department_id%TYPE;
v_current_dname departments.department_name%TYPE;
v_ename employees.last_name%TYPE;
v_job employees.job_id%TYPE;
v_hiredate employees.hire_date%TYPE;
v_sal employees.salary%TYPE;
d) Abra c_dept_cursor e use um loop simples para extrair com o comando fetch
valores para as variáveis declaradas. Exiba o número e o nome do departamento.
Use o atributo de cursor apropriado para sair do loop.
BEGIN
OPEN c_dept_cursor;
LOOP
FETCH c_dept_cursor INTO v_current_deptno,
v_current_dname;
EXIT WHEN c_dept_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ('Department Number : ' ||
v_current_deptno || ' Department Name : ' ||
v_current_dname);
Observação
• Verifique se c_emp_cursor já está aberto antes de abrir o cursor.
• Use os atributos de cursor apropriados para a condição de saída.
• Quando o loop for concluído, imprima uma linha após ter exibido os detalhes
de cada departamento e feche c_emp_cursor.
IF c_emp_cursor%ISOPEN THEN
CLOSE c_emp_cursor;
END IF;
OPEN c_emp_cursor (v_current_deptno);
LOOP
FETCH c_emp_cursor INTO v_ename,v_job,v_hiredate,v_sal;
EXIT WHEN c_emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (v_ename || ' ' || v_job
|| ' ' || v_hiredate || ' ' ||
v_sal);
END LOOP;
DBMS_OUTPUT.PUT_LINE('--------------------------------------
--------------------------------------------------');
CLOSE c_emp_cursor;
END LOOP;
CLOSE c_dept_cursor;
END;
DECLARE
v_num NUMBER(3) := 5;
v_sal employees.salary%TYPE;
CURSOR c_emp_cursor IS
SELECT salary
FROM employees
ORDER BY salary DESC;
3) Na seção executável, abra o loop e extraia com o comando fetch os n salários mais
altos e, em seguida, insira-os na tabela top_salaries. Você pode usar um loop
simples para operar os dados. Além disso, tente e use os atributos %ROWCOUNT e
%FOUND para a condição de saída.
Observação: Certifique-se de adicionar uma condição de saída para evitar um loop
infinito.
BEGIN
OPEN c_emp_cursor;
FETCH c_emp_cursor INTO v_sal;
WHILE c_emp_cursor%ROWCOUNT <= v_num AND c_emp_cursor%FOUND
LOOP
INSERT INTO top_salaries (salary)
VALUES (v_sal);
FETCH c_emp_cursor INTO v_sal;
END LOOP;
CLOSE c_emp_cursor;
END;
/
SELECT * FROM top_salaries;
5) Teste alguns casos especiais como v_num = 0 ou onde v_num seja maior que o
número de funcionários na tabela employees. Esvazie a tabela top_salaries
após cada teste.
4) Se o salário informado não retornar nenhuma linha, trate a exceção com um handler
de exceções adequado e insira na tabela messages a mensagem “No employee with
a salary of <salary>.”
7) Exiba as linhas da tabela messages para verificar se o bloco PL/SQL foi executado
com sucesso. A saída é a seguinte:
8) Altere o valor inicializado de v_emp_sal para 2000 e efetue uma nova execução. A
saída é a seguinte:
DECLARE
v_ename employees.last_name%TYPE;
v_emp_sal employees.salary%TYPE := 6000;
BEGIN
SELECT last_name
INTO v_ename
FROM employees
WHERE salary = v_emp_sal;
INSERT INTO messages (results)
VALUES (v_ename || ' - ' || v_emp_sal);
4) Se o salário informado não retornar nenhuma linha, trate a exceção com um handler
de exceções adequado e insira na tabela messages a mensagem “No employee with
a salary of <salary>.”
EXCEPTION
WHEN no_data_found THEN
INSERT INTO messages (results)
VALUES ('No employee with a salary of '||
TO_CHAR(v_emp_sal));
7) Exiba as linhas da tabela messages para verificar se o bloco PL/SQL foi executado
com sucesso.
/
SELECT * FROM messages;
A saída é a seguinte:
8) Altere o valor inicializado de v_emp_sal para 2000 e efetue uma nova execução. A
saída é a seguinte:
SET SERVEROUTPUT ON
DECLARE
e_childrecord_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);
BEGIN
DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
delete from departments where department_id=40;
EXCEPTION
WHEN e_childrecord_exists THEN
DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There
are employees in this department (child records exist.) ');
END;
f) Crie e execute um bloco anônimo para chamar o procedure greet com um valor
de parâmetro. O bloco também deve gerar a saída.
SET SERVEROUTPUT ON
BEGIN
greet;
END;
BEGIN
V_tomorrow:=v_today +1;
DBMS_OUTPUT.PUT_LINE(' Hello '|| p_name);
...
f) Crie e execute um bloco anônimo para chamar o procedure greet com um valor
de parâmetro. O bloco também deve gerar a saída.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Neste apêndice, você será apresentado à ferramenta gráfica chamada SQL Developer. Você
aprenderá a usar o SQL Developer nas tarefas de desenvolvimento de seu banco de dados. Você
aprenderá a usar a Planilha SQL para executar instruções e scripts SQL.
SQL Developer
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
1 2
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
2 4 6 8
1 3 5 7 9
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Informe
instruções SQL.
Os resultados são
mostrados aqui.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
F9 F5
F5
F9
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Identifique um local,
O conteúdo do arquivo
2 informe um nome de
3 salvo estará visível e arquivo e clique em Save.
poderá ser editado na
janela da Planilha SQL.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
1
Para executar o código, clique
em uma destas opções: 2
• Execute Script (F9) Selecione uma conexão
3
• Run Script (F5) na lista drop-down.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
A saída do script é
exibida na página com
a tab Script Output.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Antes
da formatação
Depois
da formatação
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Usando Snippets
Você poderá usar determinados fragmentos de código quando usar a Planilha SQL ou criar ou
editar um procedure ou uma função PL/SQL. O SQL Developer possui um recurso chamado
Snippets, que são fragmentos de código como funções SQL, dicas do Optimizer e diversas
técnicas de programação de PL/SQL. Você pode arrastar Snippets para a janela Editor.
Para exibir os Snippets, selecione View > Snippets.
A janela Snippets é exibida à direita. Você poderá usar a lista drop-down para selecionar um
grupo. O botão Snippets é exibido na margem da janela à direita para que você possa exibir a
janela Snippets se ela ficar oculta.
Inserindo
um Snippet
Editando o
Snippet
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Atalhos para
ferramentas usadas
com frequência
1
Links para
mecanismos de
pesquisa e fóruns de
discussão populares
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Definindo Preferências
Você pode personalizar muitos aspectos da interface e do ambiente do SQL Developer,
modificando as preferências do SQL Developer de acordo com seus requisitos. Para modificar as
preferências do SQL Developer, selecione Tools e Preferences.
As preferências estão agrupadas nas seguintes categorias:
• Environment
• Accelerators (atalhos do teclado)
• Code Editors
• Database
• Debugger
• Documentation
• Extensions
• File Types
• Migration
• PL/SQL Compilers
• PL/SQL Debugger e assim por diante
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
O SQL Developer é uma ferramenta gráfica gratuita que simplifica as tarefas de
desenvolvimento de banco de dados. Com o SQL Developer, você pode criar, editar e navegar
por objetos de banco de dados. Você pode usar a Planilha SQL para executar scripts e instruções
SQL. O SQL Developer permite que você crie e salve seu próprio conjunto especial de relatórios
para reutilização.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Objetivos
É possível criar instruções SELECT que possam ser usadas indefinidamente. Este apêndice também
aborda o uso de comandos do SQL*Plus para executar instruções SQL. Você aprenderá a formatar a
saída usando comandos do SQL*Plus, a editar comandos SQL e a salvar scripts no SQL*Plus.
Instruções SQL
Servidor
SQL*Plus
Resultados da consulta
Buffer
Scripts
SQL
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SQL e SQL*Plus
SQL é uma linguagem de comando que é usada para a comunicação com o Oracle Server por meio
de qualquer ferramenta ou aplicação. O Oracle SQL contém diversas extensões. Quando você
informa uma instrução SQL, ela é armazenada em uma parte da memória chamada de buffer SQL e
permanece lá até que você especifique uma nova instrução SQL. O SQL*Plus é uma ferramenta da
Oracle que reconhece e envia instruções SQL para o Oracle9i Server para serem executadas. Ele
contém sua própria linguagem de comandos.
Recursos da linguagem SQL
• Pode ser usada por vários usuários, incluindo aqueles com pouca ou nenhuma experiência em
programação
• É uma linguagem não procedural
• Reduz a quantidade de tempo necessária para a criação e a manutenção de sistemas
• É uma linguagem semelhante ao idioma inglês
Recursos do SQL*Plus
• Aceita a entrada ad hoc de instruções
• Aceita a entrada SQL de arquivos
• Oferece um editor de linha para a modificação de instruções SQL
• Controla as configurações do ambiente
• Formata os resultados da consulta em relatórios básicos
• Acessa bancos de dados locais e remotos
Oracle Database: Fundamentos de PL/SQL D - 3
Instruções SQL Versus
Comandos do SQL*Plus
SQL SQL*Plus
• Uma linguagem • Um ambiente
• Padrão ANSI • Proprietário da Oracle
• Palavras-chave não • Palavras-chave podem
podem ser abreviadas. ser abreviadas.
• As instruções manipulam • Os comandos não
dados e definições de permitem a manipulação
tabelas no banco de de valores no banco de
dados. dados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SQL SQL*Plus
É uma linguagem para a comunicação com o Reconhece instruções SQL e as envia ao
servidor Oracle a fim de acessar os dados servidor
É baseada no padrão ANSI (American É a interface proprietária da Oracle para a
National Standards Institute) SQL execução de instruções SQL
Manipula dados e definições de tabelas no Não permite a manipulação de valores no
banco de dados banco de dados
É incluída no buffer SQL em uma ou mais É incluído em uma linha de cada vez; não é
linhas armazenado no buffer SQL
Não tem um caractere de continuação Utiliza um traço (–) como caractere de
continuação se o comando ultrapassa uma
linha
Não pode ser abreviada Pode ser abreviado
Utiliza um caractere de finalização para Não requer caracteres de finalização; executa
executar os comandos imediatamente os comandos imediatamente
Utiliza funções para aplicar formatação Utiliza comandos para formatar dados
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SQL*Plus
O SQL*Plus é um ambiente no qual você pode:
• Executar instruções SQL para recuperar, modificar, adicionar e remover dados do banco de
dados
• Formatar, executar cálculos, armazenar e imprimir resultados de consultas no formato de
relatórios
• Criar arquivos de script para armazenar instruções SQL para uso repetido no futuro
Os comandos do SQL*Plus podem ser divididos nas seguintes categorias principais:
Categoria Objetivo
Environment Afeta o comportamento geral das instruções SQL na sessão
Format Formata os resultados da consulta
File manipulation Salva, carrega e executa arquivos de script
Execution Envia instruções SQL do buffer SQL para o servidor Oracle
Edit Modifica as instruções SQL no buffer
Interaction Cria e especifica variáveis para instruções SQL, imprime valores de
variáveis e imprime mensagens na tela
Miscellaneous Conecta-se ao banco de dados, manipula o ambiente SQL*Plus e exibe
definições de colunas
sqlplus [username[/password[@database]]]
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DESC[RIBE] tablename
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DESCRIBE departments
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
• A[PPEND] text
• C[HANGE] / old / new
• C[HANGE] / text /
• CL[EAR] BUFF[ER]
• DEL
• DEL n
• DEL m n
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Comando Descrição
A[PPEND] text Adiciona texto ao final da linha atual
C[HANGE] / old / new Altera o texto old para o new na linha atual
Diretrizes
• Se você pressionar Enter antes da conclusão de um comando, o SQL*Plus solicitará um número
de linha.
• Você pode finalizar o buffer SQL digitando um dos caracteres finalizadores (ponto e vírgula ou
barra) ou pressionando Enter duas vezes. O prompt SQL será exibido.
• I[NPUT]
• I[NPUT] text
• L[IST]
• L[IST] n
• L[IST] m n
• R[UN]
• n
• n text
• 0 text
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Observação: Você pode informar apenas um comando do SQL*Plus para cada prompt SQL. Os
comandos do SQL*Plus não são armazenados no buffer. Para continuar um comando do SQL*Plus
na linha seguinte, finalize a primeira linha com um hífen (-).
LIST
1 SELECT last_name
2* FROM employees
1
1* SELECT last_name
A , job_id
1* SELECT last_name, job_id
LIST
1 SELECT last_name, job_id
2* FROM employees
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
LIST
1* SELECT * from employees
c/employees/departments
1* SELECT * from departments
LIST
1* SELECT * from departments
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
LIST
1 SELECT last_name, manager_id, department_id
2* FROM employees
SAVE my_query
Created file my_query
START my_query
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Comando SERVEROUTPUT
A maioria dos programas PL/SQL executa entrada e saída por meio de instruções SQL, para
armazenar dados em tabelas de banco de dados ou consultar essas tabelas. Todas as outras
entradas/saídas PL/SQL são feitas por meio de APIs que interagem com outros programas. Por
exemplo, o pacote DBMS_OUTPUT possui procedures como PUT_LINE. Para ver o resultado fora
do código PL/SQL, é necessário outro programa, como o SQL*Plus, para ler e exibir os dados
passados para DBMS_OUTPUT.
O SQL*Plus não exibirá os dados de DBMS_OUTPUT, a não ser que você primeiro execute o
comando SET SERVEROUTPUT ON do SQL*Plus, conforme a seguir:
SET SERVEROUTPUT ON
Observação
• SIZE define o número de bytes da saída, que pode ser armazenado em buffer no servidor do
Oracle Database. O default é UNLIMITED. n não pode ser menor que 2.000 ou mais que
1.000.000.
• Para obter informações adicionais sobre SERVEROUTPUT, consulte o Oracle Database PL/SQL
User’s Guide and Reference 11g.
Opção Descrição
file_name[.ext] Envia a saída para o nome de arquivo especificado
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
SET AUTOTRACE ON
-- The AUTOTRACE report includes both the optimizer
-- execution path and the SQL statement execution
-- statistics
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Sumário
O SQL*Plus é um ambiente de execução que pode ser usado para enviar comandos SQL ao servidor
de banco de dados, bem como para editar e salvar esses comandos. Você pode executar comandos no
prompt do SQL ou em um arquivo de script.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Oracle JDeveloper
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Oracle JDeveloper
O Oracle JDeveloper é um IDE (Integrated Development Environment) para o desenvolvimento
e a disponibilização de aplicações Java e serviços Web. Ele suporta todos os estágios do SDLC
(Software Development Life Cycle), desde a modelagem até a disponibilização. Também dispõe
dos recursos que permitem usar os padrões mais recentes do setor para Java, XML e SQL no
desenvolvimento de aplicações.
O Oracle JDeveloper 11g introduz uma nova abordagem para o desenvolvimento em J2EE ao
oferecer recursos que permitem desenvolvimento visual e declarativo. Essa abordagem
inovadora torna o desenvolvimento em J2EE simples e eficiente.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Database Navigator
Usando o Oracle JDeveloper, você pode armazenar em um objeto denominado “connection” as
informações necessárias para se conectar a um banco de dados. Uma conexão é armazenada
como parte das definições do IDE e pode ser exportada e importada, a fim de facilitar o
compartilhamento entre grupos de usuários. As conexões são usadas para várias finalidades,
desde a navegação no banco de dados e a criação de aplicações até a implantação.
4 Clique em OK.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Esqueleto da função
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Compilando
Após editar a definição de esqueleto, você precisa compilar a unidade de programa. Clique com
o botão direito do mouse no objeto PL/SQL a ser compilado no Connection Navigator e
selecione Compile. Como alternativa, também é possível pressionar CTRL + SHIFT + F9 para
fazer a compilação.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Janela Structure
A janela Structure permite uma visão estrutural dos dados do documento selecionado na janela
ativa, que pode ser um dos elementos que formam a estrutura: navegadores, editores, modos de
exibição e o Property Inspector.
Selecione View > Structure window para exibir a janela Structure.
Na janela Structure, é possível exibir os dados do documento de várias maneiras. As estruturas
que estão disponíveis para exibição se baseiam no tipo do documento. No caso de um arquivo
Java, é possível exibir a estrutura de código, a estrutura da interface do usuário ou os dados de
modelo da interface do usuário. No caso de um arquivo XML, é possível exibir a estrutura XML,
a estrutura do projeto ou os dados de modelo da interface do usuário.
A janela Structure é dinâmica, controlando sempre a seleção atual da janela ativa (a menos que
você congele o conteúdo da janela em uma view específica), como acontece com o editor ativo
no momento. Quando a seleção atual é um nó no navegador, o editor default é utilizado. Se
quiser alterar a view da estrutura para a seleção atual, clique em outra tab de estrutura.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Janela Editor
Quando você clica duas vezes no nome de uma unidade de programa, ela é aberta na janela
Editor. É possível exibir todos os arquivos do seu projeto em apenas uma janela do editor, abrir
várias views do mesmo arquivo ou abrir várias views de arquivos diferentes.
Na parte superior da janela do editor, encontram-se as tabs de documentos. Clicar em uma tab de
documento coloca esse arquivo em destaque, trazendo-o para o primeiro plano da janela do
editor atual.
Na parte inferior da janela do editor referente a um determinado arquivo, estão as tabs de editor.
Clicar em uma dessas tabs abre o arquivo no editor correspondente.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Application Navigator
O Application Navigator permite uma visão lógica da aplicação e dos dados contidos nela. Esse
navegador fornece uma infraestrutura à qual as diversas extensões podem se conectar. Essas
extensões também podem usar a infraestrutura para organizar seus dados e menus de forma
consistente e abstrata. Embora o Application Navigator possa conter arquivos individuais (como
arquivos-fonte Java), ele foi projetado para consolidar dados complexos. Nesse navegador, os
tipos de dados complexos, como objetos de entidades, diagramas UML (Unified Modeling
Language), EJBs (Enterprise JavaBeans) ou serviços Web aparecem como nós únicos. Os
arquivos brutos que compõem esses nós abstratos são exibidos na janela Structure.
1 2 3
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Variáveis de Cursor
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Variáveis de Cursor
As variáveis de cursor são como ponteiros C ou Pascal, que armazenam a localização (endereço)
de um item na memória em vez do item propriamente dito. Portanto, declarar uma variável de
cursor cria um ponteiro, e não um item. Na linguagem PL/SQL, um ponteiro tem o tipo de dados
REF X, onde REF é a abreviatura de REFERENCE e X significa uma classe de objetos. Uma
variável de cursor tem o tipo de dados REF CURSOR.
Assim como um cursor, uma variável de cursor aponta para a linha atual do conjunto de
resultados de uma consulta de várias linhas. No entanto, os cursores diferem das variáveis de
cursor da mesma forma que as constantes diferem das variáveis. Um cursor é estático, mas uma
variável de cursor é dinâmica porque ela não está vinculada a uma consulta específica. É
possível abrir uma variável de cursor para qualquer consulta de tipo compatível. Isso
proporciona maior flexibilidade.
As variáveis de cursor estão disponíveis para todos os clientes PL/SQL. Por exemplo, você pode
declarar uma variável de cursor em um ambiente de host PL/SQL, como um programa OCI ou
Pro*C e, em seguida, transmiti-la como uma variável de host de entrada (variável de bind) para
o código PL/SQL. Além disso, as ferramentas de desenvolvimento de aplicações, como Oracle
Forms e Oracle Reports, que têm um mecanismo PL/SQL, podem usar variáveis de cursor no
lado cliente. O Oracle Server também tem um mecanismo PL/SQL. Você pode transmitir
variáveis de cursor entre uma aplicação e o servidor por meio de RPCs (remote procedure calls).
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
ref_cv ref_type_name;
Exemplo:
DECLARE
TYPE DeptCurTyp IS REF CURSOR RETURN
departments%ROWTYPE;
dept_cv DeptCurTyp;
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
emp_cv EmpCurTyp;
emp_rec employees%ROWTYPE;
sql_stmt VARCHAR2(200);
my_job VARCHAR2(10) := 'ST_CLERK';
BEGIN
sql_stmt := 'SELECT * FROM employees
WHERE job_id = :j';
OPEN emp_cv FOR sql_stmt USING my_job;
LOOP
FETCH emp_cv INTO emp_rec;
EXIT WHEN emp_cv%NOTFOUND;
-- process record
END LOOP;
CLOSE emp_cv;
END;
/
Copyright © 2011, Oracle e/ou suas empresas afiliadas. Todos os direitos reservados.
Estes exercícios impressos são usados como atividade extra para você declarar variáveis e
criar instruções executáveis.
1. DECLARE
name,dept VARCHAR2(14);
2. DECLARE
test NUMBER(5);
3. DECLARE
MAXSALARY NUMBER(7,2) = 5000;
4. DECLARE
JOINDATE BOOLEAN := SYSDATE;
4. test := FALSE;
6. var := sysdate;
1. DECLARE
name,dept VARCHAR2(14);
2. DECLARE
test NUMBER(5);
É válida.
3. DECLARE
MAXSALARY NUMBER(7,2) = 5000;
4. DECLARE
JOINDATE BOOLEAN := SYSDATE;
É inválida porque os tipos de dados não correspondem. O tipo de dados
booleano não pode receber valores de data. O tipo de dados deve ser date.
4. test := FALSE;
Booleano
DECLARE
v_custid NUMBER(4) := 1600;
v_custname VARCHAR2(300) := 'Women Sports Club';
v_ new_custid NUMBER(3) := 500;
BEGIN
DECLARE
v_custid NUMBER(4) := 0;
v_custname VARCHAR2(300) := 'Shape up Sports Club';
v_new_custid NUMBER(3) := 300;
v_new_custname VARCHAR2(300) := 'Jansports Club';
BEGIN
v_custid := v_new_custid;
v_custname := v_custname || ' ' || v_new_custname;
1
END;
v_custid := (v_custid *12) / 10;
2
END;
Avalie o bloco PL/SQL anterior e determine o valor e o tipo de dados de cada uma das
variáveis a seguir, de acordo com as regras de escopo:
1. v_custid na posição 1:
2. v_custname na posição 1:
3. v_new_custid na posição 1:
4. v_new_custname na posição 1:
5. v_custid na posição 2:
6. v_custname na posição 2:
DECLARE
v_custid NUMBER(4) := 1600;
v_custname VARCHAR2(300) := 'Women Sports Club';
v_ new_custid NUMBER(3) := 500;
BEGIN
DECLARE
v_custid NUMBER(4) := 0;
v_custname VARCHAR2(300) := 'Shape up Sports Club';
v_new_custid NUMBER(3) := 300;
v_new_custname VARCHAR2(300) := 'Jansports Club';
BEGIN
v_custid := v_new_custid;
v_custname := v_custname || ' ' || v_new_custname;
1
END;
v_custid := (v_custid *12) / 10;
2
END;
Avalie o bloco PL/SQL anterior e determine o valor e o tipo de dados de cada uma das
variáveis a seguir, de acordo com as regras de escopo:
1. v_custid na posição 1:
300, e o tipo de dados é NUMBER.
2. v_custname na posição 1:
Shape up Sports Club Jansports Club, e o tipo de dados é VARCHAR2.
3. v_new_custid na posição 1:
500, e o tipo de dados é NUMBER (ou INTEGER).
4. v_new_custname na posição 1:
Jansports Club, e o tipo de dados é VARCHAR2.
5. v_custid na posição 2:
1920, e o tipo de dados é NUMBER.
6. v_custname na posição 2:
Women Sports Club, e o tipo de dados é VARCHAR2.
2. Quando o bloco for executado, uma variável de substituição será exibida. Informe um
número de departamento válido e clique em OK.
Neste exercício, você criará um bloco PL/SQL que trata uma exceção, como a seguir:
1. Declare variáveis para o sobrenome, o salário e a data de admissão do funcionário.
Use uma variável de substituição para o sobrenome do funcionário. Em seguida,
consulte a tabela employees para last_name, salary e hire_date do
funcionário especificado.
2. Se o funcionário estiver na organização há mais de cinco anos e o salário dele for
menor que 3.500, gere uma exceção. No handler de exceção, faça o seguinte:
• Gere a saída das seguintes informações: sobrenome do funcionário e a
mensagem “due for a raise”, semelhante à seguinte saída:
Neste exercício, você criará um bloco PL/SQL que trata uma exceção, como a seguir:
1. Declare variáveis para o sobrenome, o salário e a data de admissão do funcionário.
Use uma variável de substituição para o sobrenome do funcionário. Em seguida,
consulte a tabela employees para last_name, salary e hire_date do
funcionário especificado.
2. Se o funcionário estiver na organização há mais de cinco anos e o salário dele for
menor que 3.500, gere uma exceção. No handler de exceção, faça o seguinte:
• Gere a saída das seguintes informações: sobrenome do funcionário e a
mensagem “due for a raise”.
• Insira o nome, os anos de serviço e o salário do funcionário na tabela
analysis..
3. Se não houver exceção, gere a saída do sobrenome do funcionário e a mensagem “not
due for a raise”.
SET SERVEROUTPUT ON;
DECLARE
E_DUE_FOR_RAISE EXCEPTION;
V_HIREDATE EMPLOYEES.HIRE_DATE%TYPE;
V_ENAME EMPLOYEES.LAST_NAME%TYPE := INITCAP( '& B_ENAME');
V_SAL EMPLOYEES.SALARY%TYPE;
V_YEARS NUMBER(2);
BEGIN
SELECT LAST_NAME,SALARY,HIRE_DATE
INTO V_ENAME,V_SAL,V_HIREDATE
FROM employees WHERE last_name = V_ENAME;
V_YEARS := MONTHS_BETWEEN(SYSDATE,V_HIREDATE)/12;
IF V_SAL < 3500 AND V_YEARS > 5 THEN
RAISE E_DUE_FOR_RAISE;
ELSE
DBMS_OUTPUT.PUT_LINE (' not due for a raise');
END IF;
EXCEPTION
WHEN E_DUE_FOR_RAISE THEN
BEGIN
DBMS_OUTPUT.PUT_LINE (V_NAME || ' due for a raise');
INSERT INTO ANALYSIS(ENAME,YEARS,SAL)
VALUES (V_ENAME,V_YEARS,V_SAL);
END;
END;
/