138
PL/SQL BÁSICO E AVANÇADO 7.3 Relacional Consultoria e Sistemas Rua da Candelária, 60 – 10º andar Tel: (021) 2213-9191 e-mail:[email protected] Copyright © 1998 Lúcia M. A. Fernandes Gerente de Treinamento

Comandos PL SQL

Embed Size (px)

DESCRIPTION

Apostila com comandos práticos para PL/SQL.

Citation preview

Page 1: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

Relacional Consultoria e Sistemas Rua da Candelária, 60 – 10º andar

Tel: (021) 2213-9191 e-mail:[email protected]

Copyright © 1998 Lúcia M. A. Fernandes

Gerente de Treinamento

Page 2: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 1 : INTRODUÇÃO AO PL/SQL....................................................................... 1

CONCEITOS.......................................................................................................................... 1 ESTRUTURA ........................................................................................................................ 1

FIM DE LINHA .................................................................................................................. 1 ARQUITETURA.................................................................................................................... 3 COMPONENTES DA LINGUAGEM................................................................................... 3

IDENTIFICADOR .............................................................................................................. 3 PALAVRAS RESERVADAS ................................................................................................ 3 LITERAIS............................................................................................................................ 4

COMENTÁRIOS ................................................................................................................... 4 VARIÁVEIS .......................................................................................................................... 5

TIPOS DE VARIÁVEIS....................................................................................................... 5 %TYPE ............................................................................................................................. 12 CONSTANTES.................................................................................................................. 13

ATRIBUIÇÕES.................................................................................................................... 14 CONVERSÃO DE TIPO DE VARIÁVEL.......................................................................... 15 ESCOPO DE UMA VARIÁVEL EM PL/SQL ................................................................... 16 COMANDOS ....................................................................................................................... 17

IF ...................................................................................................................................... 17 SELECT INTO.................................................................................................................. 19 LABEL .............................................................................................................................. 20 GOTO ............................................................................................................................... 20 NULL ................................................................................................................................ 21

ÍNDICE - i

Page 3: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 2 : FUNÇÕES PRÉ-DEFINIDAS ................................................................... 22

ESCALARES - CONTROLE DE ERRO............................................................................. 22 SQLCODE ........................................................................................................................ 22 SQLERRM ........................................................................................................................ 22

ESCALARES - NUMÉRICAS ............................................................................................ 23 ABS ................................................................................................................................... 23 CEIL ................................................................................................................................. 23 FLOOR ............................................................................................................................. 23 LN ..................................................................................................................................... 23 LOG.................................................................................................................................. 23 MOD................................................................................................................................. 24 POWER ............................................................................................................................ 24 ROUND ............................................................................................................................ 24 SIGN ................................................................................................................................. 24 SQRT ................................................................................................................................ 24 SIN .................................................................................................................................... 25 SINH ................................................................................................................................. 25 TAN................................................................................................................................... 25 TANH................................................................................................................................ 25 TRUNC ............................................................................................................................. 25

ESCALARES - ALFANUMÉRICAS.................................................................................. 27 CHR .................................................................................................................................. 27 CONCAT........................................................................................................................... 27 INITCAP........................................................................................................................... 27 LOWER............................................................................................................................. 27 LPAD ................................................................................................................................ 27 LTRIM .............................................................................................................................. 28 REPLACE......................................................................................................................... 28 RPAD................................................................................................................................ 28 RTRIM .............................................................................................................................. 28 SOUNDEX........................................................................................................................ 28 SUBSTR ............................................................................................................................ 30 TRANSLATE..................................................................................................................... 30 UPPER ............................................................................................................................. 30

ESCALARES - ALFANUMÉRICAS RETORNANDO VALORES NUMÉRICOS.......... 32 ASCII ................................................................................................................................ 32 INSTR ............................................................................................................................... 32 LENGTH........................................................................................................................... 32

ÍNDICE - ii

Page 4: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - DATAS....................................................................................................... 34 ADD_MONTHS................................................................................................................ 34 LAST_DAY........................................................................................................................ 34 MONTHS_BETWEEN ...................................................................................................... 34 NEW_TIME ...................................................................................................................... 34 NEXT_DAY....................................................................................................................... 35 ROUND ............................................................................................................................ 35 SYSDATE.......................................................................................................................... 35 TRUNC ............................................................................................................................. 36

ESCALARES - CONVERSÃO ........................................................................................... 38 CHARTOROWID.............................................................................................................. 38 ROWIDTOCHAR.............................................................................................................. 38 HEXTORAW..................................................................................................................... 38 RAWTOHEX..................................................................................................................... 38 TO_CHAR ........................................................................................................................ 39 TO_DATE......................................................................................................................... 42 TO_NUMBER................................................................................................................... 42

ESCALARES - OUTRAS.................................................................................................... 43 DECODE.......................................................................................................................... 43 GREATEST....................................................................................................................... 43 LEAST............................................................................................................................... 43 NVL................................................................................................................................... 43 UID................................................................................................................................... 43 USER ................................................................................................................................ 44 USERENV......................................................................................................................... 44

EXEMPLO SIMPLES DE USO DE FUNÇÕES EM PL/SQL............................................ 46

ÍNDICE - iii

Page 5: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 3 : PROCESSAMENTO REPETITIVO ........................................................ 47

CURSOR.............................................................................................................................. 47 DECLARE CURSOR ........................................................................................................ 48 OPEN CURSOR ............................................................................................................... 49 FETCH CURSOR ............................................................................................................. 50 CLOSE CURSOR.............................................................................................................. 51 UPDATE PARA CURSOR................................................................................................ 52 DELETE PARA CURSOR ................................................................................................ 53 ATRIBUTOS PARA CURSOR .......................................................................................... 54 TIPO PARA CURSOR ...................................................................................................... 57 CURSOR LOOP ............................................................................................................... 59

OUTROS COMANDOS PARA PROCESSAMENTO REPETITIVO ............................... 60 EXIT.................................................................................................................................. 60 LOOP................................................................................................................................ 60 WHILE LOOP .................................................................................................................. 62 FOR LOOP....................................................................................................................... 64

CAPÍTULO 4 : TRATAMENTO DE ERROS EM PL/SQL.............................................. 67

EXCEÇÕES PRÉ-DEFINIDAS........................................................................................... 68 DEFININDO UMA EXCEPTION....................................................................................... 70 CAUSANDO UMA EXCEPTION CRIADA PELO USUÁRIO ........................................ 70

RAISE ............................................................................................................................... 70 PRAGMA EXCEPTION_INIT............................................................................................ 72 RAISE_APPLICATION_ERROR ....................................................................................... 73 PROPAGAÇÃO DA EXCEÇÃO ........................................................................................ 74

CAPÍTULO 5 TABELAS E REGISTROS EM PL/SQL.................................................... 75

TABLE ................................................................................................................................. 75 RECORD.............................................................................................................................. 77 ATRIBUTOS DE UMA TABELA PL/SQL ........................................................................ 78

EXISTS (N) ....................................................................................................................... 78 COUNT............................................................................................................................. 78 FIRST E LAST .................................................................................................................. 78 PRIOR(N) E NEXT(N)...................................................................................................... 78 DELETE, DELETE(N) E DELETE(M,N)......................................................................... 78

ÍNDICE - iv

Page 6: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 6 : SUBPROGRAMAS EM PL/SQL .............................................................. 80

PROCEDURES .................................................................................................................... 81 FUNCTIONS........................................................................................................................ 82 DECLARAÇÕES FORWARD ............................................................................................ 83 STORED SUBPROGRAMS................................................................................................ 84

VANTAGENS.................................................................................................................... 84 CHAMADAS DE UM STORED SUBPROGRAM............................................................. 85 CRIANDO UM STORED SUBPROGRAM....................................................................... 86

DEPENDÊNCIA REMOTA ................................................................................................ 88 USO DE TABELAS PL/SQL COMO PARÂMETRO DE SUBPROGRAMAS ................ 89

CAPÍTULO 7 : TRIGGERS E PACKAGES....................................................................... 91

DATABASE TRIGGERS .................................................................................................... 91 OBJETIVO........................................................................................................................ 91 CARACTERÍSTICAS ........................................................................................................ 91 SINTAXE .......................................................................................................................... 92 PREDICADOS CONDICIONAIS ..................................................................................... 92 EXEMPLO........................................................................................................................ 93 COMPILANDO TRIGGERS............................................................................................. 94 HABILITANDO, DESABILITANDO E COMPILANDO TRIGGERS............................... 94

PACKAGES......................................................................................................................... 95 VANTAGENS.................................................................................................................... 95 ESPECIFICAÇÃO............................................................................................................ 96 CORPO............................................................................................................................. 96 SINTAXE .......................................................................................................................... 97 EXEMPLO........................................................................................................................ 98 REFERÊNCIA A PACKAGES .......................................................................................... 99

ÍNDICE - v

Page 7: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 8 : ALGUNS PACKAGES DO ORACLE.................................................... 100

O PACKAGE DBMS_OUTPUT ....................................................................................... 100 ENABLE ......................................................................................................................... 101 DISABLE ........................................................................................................................ 102 PUT ................................................................................................................................ 102 NEW_LINE..................................................................................................................... 103 PUT_LINE...................................................................................................................... 103 GET_LINE...................................................................................................................... 104 GET_LINES.................................................................................................................... 104

O PACKAGE UTL_FILE .................................................................................................. 107 FOPEN ........................................................................................................................... 108 FCLOSE ......................................................................................................................... 110 FCLOSE_ALL................................................................................................................. 111 GET_LINE...................................................................................................................... 112 PUT ................................................................................................................................ 113 NEW_LINE..................................................................................................................... 114 PUT_LINE...................................................................................................................... 115 PUTF .............................................................................................................................. 116 FFLUSH ......................................................................................................................... 117

CAPÍTULO 9 : VARIÁVEIS CURSOR ............................................................................ 120

CONCEITO........................................................................................................................ 120 VANTAGENS.................................................................................................................... 120 CRIANDO UMA VARIÁVEL CURSOR ......................................................................... 121

SINTAXE ........................................................................................................................ 121 DECLARANDO VARIÁVEIS DO TIPO CURSOR......................................................... 122

USANDO UMA VARIÁVEL CURSOR........................................................................... 123 ASSOCIANDO UMA VARIÁVEL CURSOR A UMA QUERY........................................ 123 OBTENDO DADOS DE UMA VARIÁVEL CURSOR .................................................... 124 FECHANDO UMA VARIÁVEL CURSOR...................................................................... 125

PASSANDO VARIÁVEIS CURSOR COMO PARÂMETRO ......................................... 126 EM UM PROGRAMA PRINCIPAL................................................................................ 126 EM PROGRAMAS ARMAZENADOS NA BASE............................................................. 127

RESTRIÇÕES PARA VARIÁVEIS CURSOR ................................................................. 130

ÍNDICE - vi

Page 8: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 1 : INTRODUÇÃO AO PL/SQL

CONCEITOS A PL/SQL é uma linguagem procedural do ORACLE, extensão ao SQL. Com a PL/SQL pode-se usar comandos SQL para manipular os dados da base ORACLE e fluxos de controle para processar os dados. Pode-se declarar constantes e variáveis; definir subprogramas (procedures ou funções) e controlar erros de execução.

ESTRUTURA A PL/SQL é uma linguagem estruturada em blocos. Cada bloco pode conter qualquer número de sub-blocos. Um bloco permite que se façam declarações locais ao bloco, que deixam de existir quando o bloco termina. Cada bloco é composto basicamente de 3 áreas :

DECLARE <declarações>............ opcional BEGIN <lógica>..................... obrigatória EXCEPTION <erros>....................... opcional END;

A ordem das partes é lógica, ou seja, primeiro devemos efetuar as declarações, para depois utilizar (na lógica) as variáveis criadas. As exceções ocorridas durante a execução podem ser tratadas na parte referente a erros.

FIM DE LINHA A indicação de fim de linha de comando, em PL/SQL, é feita com um ponto e vírgula (;).

INTRODUÇÃO - 1

Page 9: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> SELECT vl_sal FROM func WHERE cd_mat = 150;

VL_SAL-----------

2907.2 SQL>DECLARE 2 Wrowid ROWID; 3 Wsal NUMBER(5); 4 BEGIN 5 SELECT vl_sal, rowid 6 INTO Wsal, Wrowid 7 FROM func -- obtém o salário 8 WHERE cd_mat = 150; 9 /* 10 Atualiza os valores de salário 11 ------------------------------------- 12 */ 13 UPDATE func 14 SET vl_sal = Wsal * 1.3 15 WHERE rowid = Wrowid; 16 -- 17 END; 18 / PL/SQL procedure successfully completed. SQL> SELECT vl_sal FROM func WHERE cd_mat = 150;

VL_SAL-----------

3779.1

INTRODUÇÃO - 2

Page 10: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ARQUITETURA O módulo executável da PL/SQL pode ser instalado no RDBMS e/ou em softwares aplicativos tais como: REPORTS 2.5, FORMS 4.5. Estes dois ambientes (RDBMS e aplicativos) são independentes. No ambiente instalado, a PL/SQL aceita como entrada qualquer bloco ou subprograma escrito na linguagem. A instalação no RDBMS permite:

◊ inclusão de rotinas em PL/SQL nos aplicativos das host languages (COBOL, PL/1, ADA, C, etc).

◊ compilação e armazenamento de subprogramas na base de dados ORACLE (chamados de "stored subprogram's")

COMPONENTES DA LINGUAGEM

IDENTIFICADOR Consiste de uma letra opcionalmente seguida de números, $, _ ou #. As letras podem ser minúsculas ou maiúsculas (Não é Case Sensitive). O tamanho máximo de um identificador é 30 caracteres.

LEGAIS ILEGAIS money$$$tree teste&teste ab### novo__teste_ nm func

PALAVRAS RESERVADAS Palavras que possuam um significado especial para a PL/SQL.

BEGIN END EXCEPTION TYPE TABLE

Não devem ser usadas como identificadores.

INTRODUÇÃO - 3

Page 11: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

LITERAIS É uma representação explícita de um número, caracter, string ou boleano, não representado por um identificador.

Numéricos Caracteres Strings Boleanos 030 ‘z’ ‘10-NOV-91’ TRUE

6 ‘%’ ‘hello, world !’ FALSE -14 ‘7’ NULL

+32767 ‘.’ 12.0 ‘.’

.5 ‘z’ 2E5 ‘(‘

-9.5E-3

COMENTÁRIOS Um comentário em PL/SQL pode ser marcado de 2 formas:

◊ dois hífens em qualquer ponto da linha torna o restante dela comentário. ◊ /* (início) e */ (fim) marcam uma região que será ignorada pelo compilador.

SQL> DECLARE 2 Wrowid ROWID; 3 Wsal NUMBER(5); 4 BEGIN 5 SELECT vl_sal, rowid 6 INTO Wsal, Wrowid 7 FROM func -- obtém o salário 8 WHERE cd_mat = 150; 9 /* 10 Atualiza os valores de salário 11 --------------------------------------- 12 */ 13 UPDATE func 14 SET vl_sal = Wsal * 1.3 15 WHERE rowid = Wrowid; 16 -- 17 END; 18 /

INTRODUÇÃO - 4

Page 12: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

VARIÁVEIS Cada constante ou variável possui um tipo que especifica o formato de armazenamento, restrições e intervalo de valores. O dado pode ser simples ou composto.

SINTAXE

<variável> <tipo> [NOT NULL] [ {:= | DEFAULT} <valor inicial>]

SUBTIPOS

São subconjuntos de tipos de variáveis. Possuem uma restrição sobre o tipo que caracteriza o subconjunto de valores.

TIPOS DE VARIÁVEIS

BINARY_INTEGER

Numérico, para armazenamento de valores inteiros de -2**31 a (2**31) - 1 SINTAXE

BINARY_INTEGER

SUBTIPOS NATURAL..................... de 0 a (2**31) - 1 POSITIVE..................... de 1 a (2**31) - 1

SQL> DECLARE 2 Wbin BINARY_INTEGER; 3 Wnat NATURAL; 4 Wpos POSITIVE; 5 BEGIN ........ ........ ........ 16 END; 17 /

INTRODUÇÃO - 5

Page 13: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CHAR

Alfanumérico de tamanho fixo com comprimento até 32767 caracteres. Tamanho default de 1 caracter. SINTAXE

CHAR [ (<comprimento>) ]

SUBTIPOS STRING [ (<comprimento>) ] idem a CHAR

NUMBER

Numérico, para armazenamento de valores em ponto flutuante com precisão de até 38 dígitos. SINTAXE

NUMBER [ ( <precisão>, <escala> ) ]

SUBTIPOS DEC [ ( <precisão>, <escala> ) ].............................. idem a NUMBER DECIMAL [ ( <precisão>, <escala> ) ]...................... idem a NUMBER DOUBLE PRECISION [ ( <precisão>, <escala> ) ]... idem a NUMBER FLOAT [ ( <precisão>) ]........................................... idem a NUMBER INTEGER [ ( <precisão>, <escala> ) ]..................... idem a NUMBER INT [ ( <precisão>, <escala> ) ]................................ idem a NUMBER NUMERIC [ ( <precisão>, <escala> ) ]..................... idem a NUMBER REAL [ ( <precisão>, <escala> ) ]............................ idem a NUMBER SMALLINT [ ( <precisão>, <escala> ) ].................... idem a NUMBER

INTRODUÇÃO - 6

Page 14: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE 2 Wa number(8,2); 3 Wb dec(8,2); 4 Wc decimal(8,2); 5 Wd double precision(8,2); 6 We float(8); 7 Wf int(8,2); 8 Wg real(8,2); 9 Wh smallint(8,2); 10 BEGIN ...................

LONG

Alfanumérico de tamanho variável com comprimento de até 32767. SINTAXE

LONG [ (<comprimento>) ]

SQL> DECLARE 2 Wlong LONG(35000); 3 BEGIN ...................... 15 END; 16 / Wlong LONG(35000); * ERROR at line 2: ORA-06550: line 2, column 17: PLS-00215: String length constraints must be in range (1 .. 32767) ORA-06550: line 2, column 17: PL/SQL: Item ignored

INTRODUÇÃO - 7

Page 15: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

VARCHAR2

Alfanumérico de tamanho variável com comprimento de até 32767. A especificação de comprimento é obrigatória. SINTAXE

VARCHAR2 (<comprimento>)

SUBTIPOS VARCHAR (<comprimento>) idem a VARCHAR2

RAW

Para armazenamento de dados binários (tam. máx até 32767). A especificação de comprimento é obrigatória. SINTAXE

RAW (<comprimento>)

INTRODUÇÃO - 8

Page 16: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

LONG RAW

Para armazenamento de dados binários (tam. máx até 32767). Comprimento default é 1. SINTAXE

LONG RAW [ (<comprimento>) ] SQL> DECLARE

2 Wchar CHAR(32767); 3 Wvarc VARCHAR2(32767); 4 Wraw RAW(32767); 5 Wlonr LONG RAW(32767); 6 Wchar1 CHAR; 7 Wlong1 LONG; 8 Wlongr1 LONG RAW; 9 BEGIN 10 null; 11 END; 12 / PL/SQL procedure successfully completed.

BOOLEAN

Para armazenamento de valores boleanos (true, false ou null) SINTAXE

BOOLEAN

INTRODUÇÃO - 9

Page 17: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ROWID

Para armazenamento de valores de ROWID do banco ORACLE (em hexadecimal). SINTAXE

ROWID FORMATO:

BBBBBBBB.RRRR.FFFF, onde : BBBBBBBB....... bloco dentro do arquivo (database file) RRRR............... row dentro do bloco (primeira row é 0) FFFF................. número do arquivo (database file)

DATE

Para armazenamento de datas. SINTAXE

DATE

INTRODUÇÃO - 10

Page 18: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PLS_INTEGER

Sua magnitude vai de -2147483647 até 2147483647 (mesma do BINARY_INTEGER). Uma vez que seu conjunto de valores é menor que o de um NUMBER ele requer menor armazenamento. Além disso ele usa “machine arithmetic” sendo, por isso, mais rápido que um NUMBER OU BINARY_INTEGER que usam em suas operações “library arithmetic”. Apesar do BINARY_INTEGER e do PLS_INTEGER possuírem o mesmo intervalo de valores, eles não são exatamente iguais. Quando um PLS_INTEGER receber um valor acima de sua capacidade (overflow), é associada uma exceção. No caso de cálculos com BINARY_INTEGER a exceção não será adquirida se o resultado for associado a uma variável NUMBER. É recomendável, portanto, que nas novas aplicações utilizemos PLS_INTEGER. SINTAXE

PLS_INTEGER

SQL> DECLARE 2 Wnum NUMBER; 3 Wbool BOOLEAN := TRUE; 4 Wdate DATE := TO_DATE('10/09/97', 'dd/mm/yy'); 5 Wrowid ROWID; 6 Wpls PLS_INTEGER := -2147483647; 7 Wbin BINARY_INTEGER := -2147483647; 8 BEGIN 9 Wnum := wbin - 1; 10 Wnum := wpls - 1; 11 END; 12 / DECLARE * ERROR at line 1: ORA-01426: numeric overflow ORA-06512: at line 10

INTRODUÇÃO - 11

Page 19: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

%TYPE Através do %TYPE as variáveis PL/SQL e constantes permitem a referência ao tipo e estrutura de uma outra variável sem a necessidade de repetição de sua definição. Na definição de tabelas e colunas do database podemos agir de forma similar. O atributo %TYPE copia as propriedades de uma variável, constante ou coluna do database. É particularmente usado quando declaramos variáveis que pertençam às colunas do database.

SINTAXE

<variável>/<constante>/<coluna>%TYPE SQL> DECLARE

2 Wcodigo NUMBER(3) NOT NULL := 3; 3 Wcod2 Wcodigo%TYPE; 4 Wcod3 Wcodigo%TYPE NOT NULL := 4; 5 Wcodep DEPTO.CD_DEPTO%TYPE; 6 BEGIN 7 null; 8 END; 9 / PL/SQL procedure successfully completed.

INTRODUÇÃO - 12

Page 20: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CONSTANTES A declaração de uma constante é semelhante à declaração de uma variável, exceto que devemos adicionar a palavra chave CONSTANT e, imediatamente, associar uma valor inicial. Seu valor não poderá ser alterado durante o programa.

SINTAXE

<nome da constante> CONSTANT <tipo> {:=/DEFAULT} <valor inicial>;

SQL> DECLARE 2 Wcons CONSTANT REAL := 3.14159; 3 Wconsr CONSTANT REAL DEFAULT 3.14159; 4 BEGIN ...................... 6 END; 7 /

PL/SQL procedure successfully completed.

INTRODUÇÃO - 13

Page 21: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ATRIBUIÇÕES Em PL/SQL a atribuição de valor a uma variável é feita com a notação := . As variáveis e constantes são inicializadas cada vez que é iniciado o bloco em que elas estão declaradas. Por default, as variáveis são inicializadas com "NULL".É importante, portanto, que as variáveis antes de serem usadas sejam inicializadas. SQL> VARIABLE msg char(80)

SQL> DECLARE 2 Wpi CONSTANT REAL := 3.14159; 3 Wvf boolean; 4 Wnum number; 5 BEGIN 6 Wvf := (Wnum > 4); 7 IF Wvf THEN 8 Wnum := Wpi + 1; 9 :MSG := 'O novo valor de Wnum é 4.14159'; 10 ELSE 11 Wnum := 0; 12 :MSG := 'O novo valor de Wnum é zero'; 13 END IF; 14 END; 15 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG ------------------------------------------------------------- O novo valor de Wnum é zero

INTRODUÇÃO - 14

Page 22: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CONVERSÃO DE TIPO DE VARIÁVEL Pode-se converter de um tipo de variável para outro explicitamente porém, em muitas situações a PL/SQL pode converter o tipo de caracter em outro, implicitamente. Isto ocorre quando usamos variável de um tipo onde era esperado outro. A PL/SQL utiliza uma das seguintes funções para executar esta conversão:

TO_CHAR TO_VARCHAR2 CHARTOROWID HEXTORAW TO_BINARY_INTEGER TO_DATE TO_NUMBER ROWIDTOCHAR RAWTOHEX

SQL> DECLARE 2 Wnum NUMBER := 12; 3 Wchar CHAR(5); 4 Wdata CHAR(20); 5 BEGIN 6 Wchar := Wnum; 7 Wdata := SYSDATE; 8 :msg := Wdata; 9 END; 10 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG ------------------------------------------------------ 10-MAY-97

INTRODUÇÃO - 15

Page 23: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCOPO DE UMA VARIÁVEL EM PL/SQL Uma variável declarada em um bloco deixa de existir quando o bloco termina.

SQL> DECLARE 2 Wnum NUMBER := 12; 3 Wchar CHAR(20) := 'Wchar externa'; 4 Wunico NUMBER := 5; 5 BEGIN 6 DECLARE 7 Wnum NUMBER := 10; 8 Wchar CHAR(20) := 'Wchar interna'; 9 Wtotal NUMBER; 10 BEGIN 11 Wtotal := Wnum + Wunico; 12 :msg := 'O valor de total é ' || to_char(Wtotal); 13 END; 14 END; 15 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG ---------------------------------------------------------------- O valor de total é 15

INTRODUÇÃO - 16

Page 24: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

COMANDOS

IF A seqüência de comandos só será executada se a condição for verdadeira.

SINTAXE

IF <CONDIÇÃO> THEN <SEQÜÊNCIA DE COMANDOS> END IF;

IF <CONDIÇÃO> THEN <SEQÜÊNCIA DE COMANDOS> ELSE <SEQÜÊNCIA DE COMANDOS> END IF;

IF <CONDIÇÃO> THEN <SEQÜÊNCIA DE COMANDOS> ELSIF <CONDIÇÃO> THEN <SEQÜÊNCIA DE COMANDOS> ELSE <SEQÜÊNCIA DE COMANDOS> END IF;

INTRODUÇÃO - 17

Page 25: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

<CONDIÇÃO>

[NOT] <EXPRESSÃO BOLEANA> [[AND | OR] <EXPRESSÃO BOLEANA>]

<EXPRESSÃO BOLEANA> <LITERAL BOLEANO> | <VARIÁVEL BOLEANA> | <CHAMADA DE FUNÇÃO BOLEANA> | (<EXPRESSÃO BOLEANA>) | <EXPRESSÃO PLSQL> <OPERADOR RELACIONAL> <EXPRESSÃO PLSQL> | <EXPRESSÃO PLSQL> IS [NOT] NULL | <EXPRESSÃO PLSQL> [NOT] LIKE <PATTERN> | <EXPRESSÃO PLSQL> [NOT] BETWEEN <EXPR. PLSQL> AND <EXPR. PLSQL> | <EXPRESSÃO PLSQL> [NOT] IN (<EXPRESSÃO PLSQL>[,<EXPRESSÃO PLSQL>]) | {<NOME CURSOR> | SQL} {%NOTFOUND |%FOUND |%ISOPEN}

SQL> VARIABLE msg CHAR(30)

SQL> ACCEPT teste PROMPT 'Informe o valor de Wvalor: ' Informe o valor de Wvalor: 0 SQL> DECLARE 2 Wvalor NUMBER := &teste; 3 BEGIN 4 IF Wvalor < 0 THEN 5 :msg := 'Valor é menor que zero'; 6 ELSIF Wvalor = 0 THEN 7 :msg := 'Valor é igual a zero'; 8 ELSE 9 :msg := 'Valor é maior que zero'; 10 END IF; 11 END; 12 / old 2: Wvalor NUMBER := &teste; new 2: Wvalor NUMBER := 0; PL/SQL procedure successfully completed. SQL> PRINT msg MSG -------------------------------- Valor é igual a zero

INTRODUÇÃO - 18

Page 26: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SELECT INTO Seleciona um número fixo de rows. A avaliação das variáveis é feita a tempo de execução do comando.

SINTAXE

SELECT <LISTA DE COLUNAS> / * INTO <LISTA DE VARIÁVEIS> FROM <ESPECIFICAÇÃO DE TABELA / VIEW> WHERE <CONDIÇÃO DE SELEÇÃO>

<LISTA DE VARIÁVEIS>

Uma ou mais variáveis do programa correspondentes às colunas selecionadas.

SQL> DECLARE 2 w_salario NUMBER(5); 3 BEGIN 4 SELECT vl_sal INTO w_salario FROM func 5 WHERE cd_mat = 150 6 FOR UPDATE OF vl_sal; 7 IF w_salario < 800 THEN 8 UPDATE func SET vl_sal = w_salario * 1.3 9 WHERE cd_mat = 150; 10 :msg := 'Valor do novo salário é ' || to_char(trunc(w_salario * 1.3)); 11 ELSE 12 UPDATE func SET vl_sal = vl_sal * 1.15 13 WHERE cd_mat = 150; 14 :msg := 'Valor do novo salário é ' || to_char(trunc(w_salario * 1.15)); 15 END IF; 16 END; 17 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG -------------------------------- Valor do novo salário é 4345

INTRODUÇÃO - 19

Page 27: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

LABEL Identifica (qualifica) um comando ou conjunto de comandos. Utilizado para desvios e para qualificação. Deve existir um comando após o LABEL.

SINTAXE

<< <LABEL> >>

GOTO Desvia incondicionalmente para um "LABEL", o qual deve ser único dentro do escopo.

SINTAXE

GOTO << <LABEL> >>

SQL> DECLARE 2 Wvez NUMBER(5) := 0; 3 Wloop NATURAL := 0; 4 BEGIN 5 <<inicio>> 6 Wloop := Wloop + 1; 7 IF Wvez > 5 THEN 8 :msg := 'O valor de Wvez é = ' || TO_CHAR(Wvez); 9 GOTO fim; 10 ELSE 11 Wvez := Wvez * Wloop + 1; 12 END IF; 13 GOTO inicio; 14 <<fim>> 15 COMMIT; 16 END; 17 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG -------------------------------- O valor de Wvez é = 10

INTRODUÇÃO - 20

Page 28: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

NULL Este comando explicitamente indica que não há ação a ser feita. Serve para compor certas situações em que um comando é exigido, mas nenhuma ação é realmente necessária.

SINTAXE

NULL

SQL> DECLARE 2 Wvez NUMBER(5) := 0; 3 Wloop NATURAL := 0; 4 BEGIN 5 <<inicio>> 6 Wloop := Wloop + 1; 7 IF Wvez > 5 THEN 8 :msg := 'O valor de Wvez é = ' || TO_CHAR(Wvez); 9 GOTO fim; 10 ELSE 11 Wvez := Wvez * Wloop + 1; 12 END IF; 13 GOTO inicio; 14 <<fim>> 15 NULL; 16 END; 17 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG -------------------------------- O valor de Wvez é = 10

INTRODUÇÃO - 21

Page 29: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 2 : FUNÇÕES PRÉ-DEFINIDAS A PL/SQL permite a utilização de diversas funções pré-definidas para a manipulação dos dados. Pode-se usá-las onde expressões do mesmo tipo são permitidas.

ESCALARES - CONTROLE DE ERRO

SQLCODE Retorna o código do erro associado à ultima exceção.

SINTAXE: SQLCODE

SQLERRM Retorna a mensagem de erro associado ao último sqlcode.

SINTAXE: SQLERRM (<código do erro>)

SQL> DECLARE 2 Wcode NUMBER(10) := &codigo; 3 BEGIN 4 :msg := SQLERRM(wcode); 5 END; 6 / Enter value for codigo: -1403 old 2: Wcode NUMBER(10) := &codigo; new 2: Wcode NUMBER(10) := -1403; PL/SQL procedure successfully completed. SQL> print msg MSG ------------------------------------------------------ ORA-01403: no data found

FUNÇÕES PRÉ-DEFINIDAS - 22

Page 30: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - NUMÉRICAS

ABS Retorna o valor absoluto do argumento <n>.

SINTAXE: ABS(<n>)

CEIL Retorna o menor inteiro maior que ou igual a <n>.

SINTAXE: CEIL(<n>)

FLOOR Retorna o maior inteiro menor que ou igual a <n>.

SINTAXE: FLOOR(<n>)

LN Retorna o logaritmo natural do argumento que deve ser maior que zero.

SINTAXE: LN (<n>)

LOG Retorna o logaritmo de <n> na base <m>, sendo que <m> deve ser maior que 1 e <n> deve ser maior que zero.

SINTAXE: LOG (<m>, <n>)

FUNÇÕES PRÉ-DEFINIDAS - 23

Page 31: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

MOD Retorna o resto da divisão de <m> por <n>.

SINTAXE: MOD(<m>,<n>)

POWER Retorna <m> elevado a <n> potência.

SINTAXE: POWER(<m>,<n>)

ROUND Retorna <n> arredondado para <m> posições à direita do ponto decimal. Se <m> for omitido, 0 será assumido. <m> pode ser negativo para arredondar os dígitos a esquerda do ponto decimal. <m> deve ser um inteiro.

SINTAXE: ROUND(<n>[,<m>])

SIGN Se <n> menor que 0, a função retorna -1. Se <n> é igual a 0, a função retorna 0. Se <n> é maior que 0, a função retorna 1.

SINTAXE: SIGN(<n>)

SQRT Retorna a raiz quadrada de <n>. Se <n> for negativo, retorna NULL. A função retorna um resultado real.

SINTAXE: SQRT(<n>)

FUNÇÕES PRÉ-DEFINIDAS - 24

Page 32: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SIN Retorna o seno de <n>, que deve ser expresso em radianos.

SINTAXE: SIN(<n>) OBS.: Se <n> estiver em graus, basta que seja dividido por 57.29578 para ser convertido para radianos.

SINH Retorna o seno hiperbólico do argumento.

SINTAXE: SINH(<n>)

TAN Retorna a tangente de <n>, que deve ser expresso em radianos.

SINTAXE: TAN(<n>) OBS.: Se <n> estiver em graus, basta que seja dividido por 57.29578 para ser convertido para radianos.

TANH Retorna a tangente hiperbólica do argumento.

SINTAXE: TANH(<n>)

TRUNC Retorna <n> truncado para <m> posições decimais. Se <m> for omitido, 0 será assumido. <m> pode ser negativo para truncar <m> dígitos a esquerda do ponto decimal.

SINTAXE: TRUNC(<n>[,<m>])

FUNÇÕES PRÉ-DEFINIDAS - 25

Page 33: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE

2 Wcos NUMBER := 0; 3 Wcosh NUMBER := 0; 4 Wln NUMBER := 0; 5 Wlog NUMBER := 0; 6 BEGIN 7 Wcos := round(cos(20 / 57.29578)); 8 Wcosh := trunc(cosh(20 / 57.29578)); 9 Wln := round(ln(2)); 10 Wlog := trunc(log(10, 5)); 11 :msg := 'cos = '|| to_char(Wcos) || 12 ' cosh = '|| to_char(Wcosh) || 13 ' ln = '|| to_char(Wln) || 14 ' log = '|| to_char(Wlog); 15 END; 16 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG -------------------------------------------------- cos = 1 cosh = 1 ln = 1 log = 0

FUNÇÕES PRÉ-DEFINIDAS - 26

Page 34: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - ALFANUMÉRICAS

CHR Retorna o caracter correspondente ao ASCII ou EBCDIC valor de <n>

SINTAXE: CHR(<n>)

CONCAT Retorna uma string que é o resultado da concatenação de <str1> com <str2>.

SINTAXE: CONCAT(<str1>, <str2>)

INITCAP Retorna <c> com a primeira letra de cada palavra em maiúscula e as demais em minúscula.

SINTAXE: INITCAP(<c>)

LOWER Retorna<c>, com todas as letras minúsculas.

SINTAXE: LOWER(<c>)

LPAD Retorna <c1> completado à esquerda para o comprimento <n> com a seqüência de caracteres em <c2> (default branco).

SINTAXE: LPAD(<c1>,<n>[,<c2>])

FUNÇÕES PRÉ-DEFINIDAS - 27

Page 35: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

LTRIM Retorna <c1> sem os caracteres <c2> encontrados à esquerda. A busca é interrompida quando for encontrado o primeiro caracter diferente de <c2> (default branco) .

SINTAXE: LTRIM(<c1>[,<c2>])

REPLACE Retorna <c> com cada ocorrência de <s1> substituída por <s2>. Se <s1> e <s2> não forem informados, a função retornará NULL.

SINTAXE: REPLACE(<c>,<s1>[,<s2>])

RPAD Retorna <c1> completado à direita para o comprimento <n> com a seqüência de caracteres em <c2> (default branco)

SINTAXE: RPAD(<c1>,<n>[,<c2>])

RTRIM Retorna <c1> sem os caracteres <c2> finais à direita. A busca é interrompida quando for encontrado o primeiro caracter diferente de <c2> (default branco)

SINTAXE: RTRIM(<c1>[,<c2>])

SOUNDEX Retorna uma string que represente o som de <c>.

SINTAXE: SOUNDEX(<c>)

FUNÇÕES PRÉ-DEFINIDAS - 28

Page 36: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg1 CHAR(50) SQL> VARIABLE msg2 CHAR(50) SQL> DECLARE 2 Wchr CHAR(5); 3 Wconcat VARCHAR2(30); 4 Winitcap VARCHAR2(15); 5 Wtexto VARCHAR2(20); 6 Wnome VARCHAR2(20); 7 Wsobrenome VARCHAR2(20); 8 BEGIN 9 SELECT nm_func, nm_sobrenome 10 INTO Wnome, Wsobrenome 11 FROM func 12 WHERE cd_mat = 200; 13 Wconcat := CONCAT (Wnome, Wsobrenome); 14 Winitcap := INITCAP (Wsobrenome); 15 Wtexto := LOWER(RTRIM(LTRIM(Wnome))) || 16 ' ' || UPPER(Wsobrenome); 17 :msg1 := Wtexto; 18 :msg2 := CONCAT(CONCAT(Wconcat, ' ---- '), Winitcap); 19 END; 20 / PL/SQL procedure successfully completed. SQL> PRINT msg1 MSG1 ---------------------------------------------------------------------------- davi BARBOSA SQL> PRINT msg2 MSG2 ---------------------------------------------------------------------------- DAVIBARBOSA ---- Barbosa

FUNÇÕES PRÉ-DEFINIDAS - 29

Page 37: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SUBSTR Retorna uma parte de <c>, começando no <n> caracter com comprimento <m>.

SINTAXE: SUBSTR(<c>,<n>[,<m>])

TRANSLATE Retorna <c>,substituindo todas as ocorrências de <x> por <y>. O relacionamento entre os caracteres de <x> e <y> é posicional. Caso <y> tenha cumprimento inferior a <x> os caracteres de <x> sem correspondência serão omitidos do resultado.

SINTAXE: TRANSLATE(<c>,<x>,<y>)

UPPER Retorna <c> com todas as letras maiúsculas.

SINTAXE: UPPER(<c>)

FUNÇÕES PRÉ-DEFINIDAS - 30

Page 38: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg1 CHAR(50)

SQL> VARIABLE msg2 CHAR(50) SQL> DECLARE 2 Wchr CHAR(5); 3 Wtexto1 VARCHAR2(20); 4 Wtexto2 VARCHAR2(20); 5 Wnome VARCHAR2(20); 6 Wsobrenome VARCHAR2(20); 7 BEGIN 8 SELECT nm_func, nm_sobrenome 9 INTO Wnome, Wsobrenome 10 FROM func 11 WHERE cd_mat = 300; 12 Wtexto1 := TRANSLATE (Wnome, 13 'ABCDEFGHIJKLMNOP', ';*&^%$#@!-_+=)('); 14 Wtexto2 := REPLACE (Wnome, 'EI', 'XK'); 15 Wchr := CHR(90); 16 :msg1 := 'TRANSLATE = ' || Wtexto1 || ' REPLACE = ' || Wtexto2; 17 :msg2 := UPPER(Wsobrenome) || ‘ - CHR(90) = ' || Wchr; 18 END; 19 / PL/SQL procedure successfully completed. SQL> PRINT msg1 MSG1 ------------------------------------------------------------------------------- TRANSLATE = $%+!% REPLACE = FELIPE SQL> PRINT msg2 MSG2 ------------------------------------------------------------------------------- SARAIVA - CHR(90) = Z

FUNÇÕES PRÉ-DEFINIDAS - 31

Page 39: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - ALFANUMÉRICAS RETORNANDO VALORES NUMÉRICOS

ASCII Retorna o número de seqüência em ASCII correspondente ao caracter <c>.

SINTAXE: ASCII (<c>)

INSTR Retorna a posição da <m>-ésima ocorrência de <c2> dentro de <c1>, começando na posição <n>.

SINTAXE: INSTR(<c1>,<c2>[,<n>[,<m>]])

LENGTH Retorna o comprimento de <c>.

SINTAXE: LENGTH(<c>)

FUNÇÕES PRÉ-DEFINIDAS - 32

Page 40: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg VARCHAR2(40) SQL> DECLARE 2 Wtexto VARCHAR2(30); 3 Wnome VARCHAR2(20); 4 Wsobrenome VARCHAR2(20); 5 Wposicao PLS_INTEGER; 6 BEGIN 7 SELECT nm_func, nm_sobrenome 8 INTO Wnome, Wsobrenome 9 FROM func 10 WHERE cd_mat = 100; 11 Wtexto := Wnome || ' ' || Wsobrenome; 12 Wposicao := INSTR(Wtexto, ' '); 13 :msg := 'TEXTO = *' || Wtexto || '* POSICAO = ' || Wposicao; 14 END; 15 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG --------------------------------------------------------------------------------- TEXTO = *TEODORO SIQUEIRA* POSICAO = 8

FUNÇÕES PRÉ-DEFINIDAS - 33

Page 41: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - DATAS

ADD_MONTHS Retorna a data <d> adicionada de <n> meses. <n> deve ser um inteiro e pode ser negativo.

SINTAXE: ADD_MONTHS(<d>,<n>)

LAST_DAY Retorna a data do último dia do mês de <d>.

SINTAXE: LAST_DAY(<d>)

MONTHS_BETWEEN Retorna o número de meses entre <d> e <e>

SINTAXE: MONTHS_BETWEEN(<d>, <e>)

NEW_TIME Retorna a data e hora no meridiano <b>, para a data e hora <d> no meridiano <a>.

SINTAXE: NEW_TIME(<d>,<a>,<b>)

ABREVIATURAS PARA MERIDIANOS AST, ADT........... Atlantic standard ou Daylight Time GMT................... Greenwich PST, PDT........... Pacific Sandard ou Daylight Time YST, YDT........... Youkon Standard ou Daylight Time.

FUNÇÕES PRÉ-DEFINIDAS - 34

Page 42: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

NEXT_DAY Retorna a data do primeiro dia da semana nomeado por <c> que seja posterior a <d>

SINTAXE: NEXT_DAY(<d>,<c>)

ROUND Retorna <d> arredondado para o formato especificado.

SINTAXE: ROUND(<d>,[,<fmt>])

SYSDATE Retorna a data e hora correntes

SINTAXE: SYSDATE

FUNÇÕES PRÉ-DEFINIDAS - 35

Page 43: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

TRUNC Retorna uma data no formato especificado por <fmt>, representando <d> truncada na unidade correspondente.

SINTAXE: TRUNC(<d>,<fmt>)

FORMATOS PARA ROUND E TRUNC

CC, SCC.......................................................... Século SYYY, YYYY, YEAR, SYEAR, YYY, YY, Y...... Ano (meio=01/07) Q...................................................................... Quarto de ano MONTH, MON, MM.......................................... Mês WW.................................................................. Dia da semana de início do ano W..................................................................... Dia da semana de início do mês DDD, DD, J...................................................... Dia (DEFAULT) DAY, DY, D...................................................... mais próximo domingo HH, HH12, HH24.............................................. Hora MI..................................................................... Minuto

FUNÇÕES PRÉ-DEFINIDAS - 36

Page 44: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg1 VARCHAR2(80) SQL> VARIABLE msg2 VARCHAR2(80) SQL> DECLARE 2 Whoje DATE := SYSDATE + 5.23; 3 Wmes DATE; 4 Wdia DATE; 5 Wdif NUMBER; 6 Wsem DATE; 7 Wround DATE; 8 BEGIN 9 Wmes := ADD_MONTHS(Whoje, 3); 10 Wdia := LAST_DAY(Whoje); 11 Wdif := MONTHS_BETWEEN(SYSDATE, '01-may-97'); 12 Wsem := NEXT_DAY(SYSDATE, 'Monday'); 13 Wround := ROUND(SYSDATE, 'Day'); 14 :msg1 := TO_CHAR(SYSDATE, 'dd/mm/yy hh24:mi:ss d') ||'#'|| 15 TO_CHAR(Whoje, 'dd/mm/yy hh24:mi:ss d') ||'#'|| 16 TO_CHAR(Wmes, 'dd/mm/yy hh24:mi:ss d'); 17 :msg2 := TO_CHAR(Wdia, 'dd/mm/yy hh24:mi:ss d') ||'#'|| 18 TO_CHAR(Wdif, '990.0099') ||'#'|| 19 TO_CHAR(Wsem, 'dd/mm/yy hh24:mi:ss d') ||'#'|| 20 TO_CHAR(Wround, 'dd/mm/yy hh24:mi:ss d'); 21 END; 22 / PL/SQL procedure successfully completed. SQL> PRINT MSG1 MSG1 ---------------------------------------------------------------------------------- 09/06/97 11:21:27 2#14/06/97 16:52:39 7#14/09/97 16:52:39 1 SQL> PRINT MSG2 MSG2 ----------------------------------------------------------------------------------------------- 30/06/97 16:52:39 2# 1.2733#16/06/97 11:21:27 2#08/06/97 00:00:00 1

FUNÇÕES PRÉ-DEFINIDAS - 37

Page 45: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - CONVERSÃO

CHARTOROWID Converte o valor de <c> para rowid.

SINTAXE: CHARTOROWID(<c>)

ROWIDTOCHAR Converte valores de ROWID para caracteres.

SINTAXE: ROWIDTOCHAR(<rowid>) ROWID corresponde ao endereço da linha. Esta pseudo-coluna existe em cada tabela do ORACLE. É composta das seguintes informações:

◊ número do bloco no arquivo de banco de dados. ◊ número da linha no bloco (iniciando em zero). ◊ número do arquivo (primeiro arquivo é 1).

HEXTORAW Converte uma string hexadecimal do tipo CHAR ou VARCHAR2 para RAW.

SINTAXE: HEXTORAW(<h>)

RAWTOHEX Converte um valor binário em uma string hexadecimal do tipo VARCHAR2.

SINTAXE: RAWTOHEX(<bin>)

FUNÇÕES PRÉ-DEFINIDAS - 38

Page 46: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

TO_CHAR Converte um valor numérico ou data para o formato especificado.

SINTAXE 1: TO_CHAR(<n> [,<fmt> [,<nls1>]]) SINTAXE 2: TO_CHAR(<d>, [<fmt> [,<nls2>]])

FORMATOS NUMÉRICOS PARA TO_CHAR E TO_NUMBER

9......... A quantidade de 9's determina o comprimento 0......... Completa o comprimento do formato com zero's. $......... Prefixa o valor com o símbolo $. B......... Substitui o valor 0 por branco. MI....... Mostra - após um valor negativo. PR...... Mostra um valor negativo entre <>. ,.......... Mostra uma , na posição correspondente. ........... Mostra um . decimal na posição. V......... Multiplica o valor por 10n, onde n corresponde ao número de 9’s após v. E......... Notação cientifica. DATE.. Para datas armazenadas em colunas number (ORACLE V.2). Mostra no

formato mm/dd/yy.

FORMATOS DE NLS

‘NLS_NUMERIC_CHARACTERS = ‘’<d><g>‘’, NLS_CURRENCY = ‘’<text>‘’, NLS_ISO_CURRENCY = ‘’<text>‘’ ‘........

<nls1>

‘NLS_DATE_LANGUAGE = <language>‘.................................................... <nls2> Onde:

<d>................ caracter decimal <g>................ separador de milhar <text>............. símbolo monetário

FUNÇÕES PRÉ-DEFINIDAS - 39

Page 47: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FORMATOS DE DATA PARA TO_CHAR E TO_DATE

CC, SCC............................... Século (S prefixa datas BC com um sinal de "-"). SYYY ou YYYY ou YYY...... Ano YY ou Y ou Y,YYY................ Ano YEAR, SYEAR ..................... Ano por extenso BC ou AD ............................. Indicadores BC ou AD. Q........................................... Quarto de ano MONTH................................ Nome do mês (9 caracteres) MON..................................... Nome do mês (3 caracteres) MM........................................ Mês (numérico) WW...................................... Semana do ano (numérico) W.......................................... Semana do mês(numérico) DDD...................................... Dia do ano(1-366) DD........................................ Dia do mês D........................................... Dia da semana(1-7) DAY...................................... Nome do dia(9 caracteres) DY........................................ Nome do dia(3 caracteres) J............................................ Dia em data juliana (número de dias desde

01/01/4712 BC). HH, HH12, HH24.................. Hora MI......................................... Minuto SS......................................... Segundo AM/PM.................................. Indicador AM ou PM. /., ..................................... Inclusão de pontuação "..." ..................................... Inclusão de strings no resultado

FUNÇÕES PRÉ-DEFINIDAS - 40

Page 48: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg1 CHAR(30) SQL> VARIABLE msg2 CHAR(30) SQL> DECLARE 2 Wnum NUMBER; 3 Wdata DATE; 4 Wsobrenome VARCHAR2(20); 5 Wposicao PLS_INTEGER; 6 BEGIN 7 Wdata := SYSDATE; 8 :msg1 := TO_CHAR(Wdata,'DAY', 9 'NLS_DATE_LANGUAGE = PORTUGUESE'); 10 Wnum := 123456.89; 11 :msg2 := TO_CHAR(Wnum, 'L999G999D99', 12 'NLS_NUMERIC_CHARACTERS = ,., NLS_CURRENCY = R$'); 13 END; 14 / PL/SQL procedure successfully completed. SQL> PRINT msg1 MSG1 -------------------------------------------------------------------------------------------------- DOMINGO SQL> PRINT msg2 MSG2 -------------------------------------------------------------------------------------------------- R$123.456,89

FUNÇÕES PRÉ-DEFINIDAS - 41

Page 49: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

TO_DATE Converte <c> para o formato interno de data.

SINTAXE: TO_DATE(<c>[,<fmt>])

TO_NUMBER Converte <c> para o valor numérico correspondente.

SINTAXE: TO_NUMBER(<c>) SQL> VARIABLE msg1 CHAR(80)

SQL> DECLARE 2 Wdata1 DATE; 3 Wdata2 DATE; 4 BEGIN 5 Wdata1 := TO_DATE('14/06/97 10:00:00', 'dd/mm/yy hh24:mi:ss'); 6 Wdata2 := TO_DATE('1997-july-15 10:15PM', 7 'yyyy-month-dd hh12:mipm'); 8 :msg1 := TO_CHAR(Wdata1, 'dd/mm/yy hh24:mi:ss d') ||'#'|| 9 TO_CHAR(Wdata2, 'dd/mm/yy hh24:mi:ss d'); 10 END; 11 / PL/SQL procedure successfully completed. SQL> PRINT MSG1 MSG1 ------------------------------------------------------------------------------ 14/06/97 10:00:00 7#15/07/97 22:15:00 3

FUNÇÕES PRÉ-DEFINIDAS - 42

Page 50: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESCALARES - OUTRAS

DECODE Só é permitido em comandos SQL.

GREATEST Retorna a maior <e> da lista de valores. Todas as expressões após a primeira são convertidas para o tipo de dado da primeira antes da comparação ser feita

SINTAXE: GREATEST(<e>,[,<e>] ...)

LEAST Retorna a menor <e> da lista de valores. Todas as expressões após a primeira são convertidas para o tipo de dado da primeira antes da comparação ser feita

SINTAXE: LEAST(<e>,[,<e>] ...)

NVL Se <e1> for NULL, retorna <e2>. Se <e1> não for NULL, retorna <e1>

SINTAXE: NVL(<e1>, <e2>)

UID Retorna o valor do inteiro associado a cada username pelo Oracle.

SINTAXE: UID

FUNÇÕES PRÉ-DEFINIDAS - 43

Page 51: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

USER Retorna o username corrente.

SINTAXE: USER

USERENV Retorna informações sobre o user e a sessão.

SINTAXE: USERENV(<option>)

VALORES DE <OPTION>

ENTRYID.......................... Identificador da entrada SESSIONID...................... Identificador da sessão TERMINAL........................ Identificador do terminal LANGUAGE...................... Identificador da linguagem em uso

VSIZE

Só é permitido em comandos SQL.

FUNÇÕES PRÉ-DEFINIDAS - 44

Page 52: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg1 VARCHAR2(80) SQL> DECLARE 2 Wdata1 DATE := TO_DATE('1997-july-15 10:15PM', 3 'yyyy-month-dd hh12:miam'); 4 Wdata2 DATE := NULL; 5 Wresult DATE; 6 Wenv VARCHAR2(30); 7 Wsize NUMBER; 8 BEGIN 9 Wresult := NVL(Wdata2, Wdata1); 10 Wenv := USERENV('LANGUAGE') ||'#'||USERENV('SESSIONID'); 11 :msg1 := TO_CHAR(Wresult, 'dd/mm/yy hh24:mi:ss d') ||'#'||Wenv; 12 END; 13 / PL/SQL procedure successfully completed. SQL> PRINT MSG1 MSG1 ----------------------------------------------------------------------------------- 15/07/97 22:15:00 3#AMERICAN_AMERICA.WE8DEC#29005

FUNÇÕES PRÉ-DEFINIDAS - 45

Page 53: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXEMPLO SIMPLES DE USO DE FUNÇÕES EM PL/SQL Deseja-se converter o código do departamento (da tabela de departamento) de alfabético para numérico, substituindo a letra pelo número correspondente. Por exemplo: deA00 para 100, de B01 para 201 e assim por diante.

SQL> DECLARE 2 Wnum NUMBER; 3 Wdepto CHAR(03) := '&depto'; 4 BEGIN 5 ------- Primeira Solução 6 IF UPPER(SUBSTR(Wdepto,1,1)) = 'A' THEN 7 Wnum := 100 + TO_NUMBER(SUBSTR(Wdepto,2,2)); 8 ELSIF UPPER(SUBSTR(Wdepto,1,1)) = 'B' THEN 9 Wnum := 200 + TO_NUMBER(SUBSTR(Wdepto,2,2)); 10 ELSIF UPPER(SUBSTR(Wdepto,1,1)) = 'C' THEN 11 Wnum := 300 + TO_NUMBER(SUBSTR(Wdepto,2,2)); 12 ELSIF UPPER(SUBSTR(Wdepto,1,1)) = 'D' THEN 13 Wnum := 400 + TO_NUMBER(SUBSTR(Wdepto,2,2)); 14 ELSIF UPPER(SUBSTR(Wdepto,1,1)) = 'E' THEN 15 Wnum := 500 + TO_NUMBER(SUBSTR(Wdepto,2,2)); 16 ELSE Wnum := 0; 18 END IF; 19 :msg1 := 'O novo valor é ' || TO_CHAR(Wnum); 20 -------- Segunda Solução 21 Wnum := (ASCII(UPPER(SUBSTR(Wdepto,1,1))) - 64) * 100 + 22 TO_NUMBER(SUBSTR(Wdepto,2,2)); 23 :msg2 := 'O novo valor é ' || TO_CHAR(Wnum); 24 END; 25 / Enter value for depto: C03 old 3: Wdepto CHAR(03) := '&depto'; new 3: Wdepto CHAR(03) := 'C03'; PL/SQL procedure successfully completed. SQL> PRINT msg1 MSG1 --------------------------------------------------------------------------- O novo valor é 303

SQL> PRINT msg2

FUNÇÕES PRÉ-DEFINIDAS - 46

Page 54: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 3 : PROCESSAMENTO REPETITIVO

CURSOR As linguagens convencionais (COBOL, PL/1, ASSEMBLER, etc.) não estão preparadas para trabalhar com tabelas. Sabemos, porém, que o resultado de uma operação relacional é sempre uma tabela (de uma ou mais rows). A fim de solucionar este problema, foi criado um artifício que permite a manipulação do resultado de uma consulta. Este artifício é o cursor. Com ele se torna possível a obtenção de linhas individuais da tabela resultante.

PROCESSAMENTO REPETITIVO - 47

Page 55: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DECLARE CURSOR Este comando tem por objetivo definir um cursor e associá-lo a uma tabela (em memória) ORACLE.

SINTAXE

CURSOR <nome cursor>

[(<parâmetro> <tipo> [,<parâmetro <tipo>...])] RETURN <tipo> |

<variável%TYPE | <table.column>%TYPE | <TABLE>%rowtype

IS <comando SELECT> O cursor com nome especificado é criado quando o programa é executado. Uma tabela resultado é determinada pelo comando SELECT do cursor.

<SELECT>

O comando SELECT do cursor possui a mesma sintaxe de um comando SELECT comum. Se a cláusula ORDER BY não for especificada, as rows da tabela resultado serão obtidas em uma ordem arbitrária. Se a cláusula FOR UPDATE não for especificada as rows da tabela resultado não poderão ser atualizadas.

FOR UPDATE OF <NOMES DE COLUNAS>

Permite que o cursor seja referenciado no comando UPDATE (a fim de atualizar a row apontada pelo cursor).

PROCESSAMENTO REPETITIVO - 48

Page 56: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

OPEN CURSOR Este comando abre um cursor para que ele possa ser usado na obtenção de rows da tabela resultado.

SINTAXE

OPEN <nome do cursor> [(<parâmetro> [, <parâmetro> . . . ])]

<NOME DO CURSOR>

Nomeia um cursor que foi definido em um comando DECLARE CURSOR anteriormente codificado no programa de aplicação. Quando o comando OPEN for executado, o cursor deve estar no estado de closed. A tabela resultado de um cursor é derivada da avaliação de um comando SELECT, usando os valores atuais dos parâmetros especificados no mesmo. O comando OPEN CURSOR ativa o conjunto de rows e aponta o cursor para o início do conjunto. O cursor é posicionado antes da primeira linha da tabela resultado. Nenhuma linha é, na verdade recuperada, neste ponto, somente a tempo de FETCH.

[(<PARÂMETRO> [, <PARÂMETRO> . . . ])]

Indica os valores dos parâmetros declarados. A tempo de OPEN estes valores devem ser fornecidos para que seja possível a execução do comando SELECT.

PROCESSAMENTO REPETITIVO - 49

Page 57: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FETCH CURSOR Posiciona um cursor na próxima linha da tabela resultado e associa os valores da linha atual às variáveis do programa.

SINTAXE

FETCH <nome do cursor> INTO <variável> [,<variável> ...]

<NOME DO CURSOR>

Substitua pelo nome de um cursor anteriormente definido e aberto pelo programa de aplicação. Se o cursor estiver posicionado sobre ou após a última linha da tabela resultado, o valor da função SQLCODE é atualizado com o valor +100, o cursor é posicionado após a última linha e os valores não são associados às variáveis do programa. Se o cursor está atualmente posicionado antes de uma linha, o cursor é posicionado sobre aquela linha e os valores desta são associados às variáveis do programa especificadas na cláusula INTO.

INTO <VARIÁVEL>

Cada variável do programa deve identificar uma variável simples ou ocorrência que esteja descrita no programa de aplicação. O número de linhas recuperado é determinado pela dimensão das variáveis (número ocorrências)

PROCESSAMENTO REPETITIVO - 50

Page 58: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CLOSE CURSOR Fecha um cursor. Se uma tabela temporária foi criada quando o cursor foi aberto, então esta tabela é destruída.

SINTAXE

CLOSE <nome do cursor>

<NOME DO CURSOR>

É o nome de uma cursor que tenha sido declarado no programa de aplicação. Quando o comando CLOSE é executado, o cursor deve estar no estado OPEN.

PROCESSAMENTO REPETITIVO - 51

Page 59: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

UPDATE PARA CURSOR Seu objetivo é atualizar uma linha previamente selecionada.

SINTAXE

UPDATE <nome de tabela / VIEW> SET <nome de coluna 1> = <expressão 1> [,<nome de coluna 2> = <expressão 2> . . . ]

WHERE CURRENT OF <nome cursor>

WHERE CURRENT OF <NOME DO CURSOR>

Esta cláusula indica que somente a row em uso será atualizada. Para que este comando seja executado é necessário que anteriormente tenha sido executado um comando SELECT em que a cláusula FOR UPDATE OF estivesse presente. Somente as colunas mencionadas no comando SELECT podem agora ser atualizadas no comando UPDATE.

PROCESSAMENTO REPETITIVO - 52

Page 60: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DELETE PARA CURSOR Seu objetivo é excluir uma linha previamente selecionada.

SINTAXE

DELETE FROM <nome da tabela / VIEW> WHERE CURRENT OF <nome do cursor>

WHERE CURRENT OF <NOME DO CURSOR>

Esta cláusula indica que a linha em uso será excluída.

PROCESSAMENTO REPETITIVO - 53

Page 61: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ATRIBUTOS PARA CURSOR Existem 2 tipos de cursores em PL/SQL: implícito e explícito. A PL/SQL implicitamente declara um cursor para cada comando SQL que manipule dados, inclusive QUERIES que retornem uma única linha.

%FOUND

Indica se o último FETCH retornou uma linha ou não, para cursores explícitos. E se alguma linha foi afetada pelo último comando INSERT, UPDATE ou DELETE para cursores implícitos. SINTAXE

<cursor>%FOUND SQL%FOUND

%NOTFOUND

Indica se o último FETCH retornou uma linha ou não, para cursores explícitos. E se alguma linha foi afetada pelo último comando INSERT, UPDATE ou DELETE para cursores implícitos. SINTAXE

<cursor> %NOTFOUND SQL %NOTFOUND

PROCESSAMENTO REPETITIVO - 54

Page 62: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

%ISOPEN

Permite que se verifique se um cursor está aberto ou não. No caso de cursores implícitos o resultado será sempre FALSE, uma vez que o ORACLE fecha o cursor após uma operação. SINTAXE

<cursor> %ISOPEN SQL %ISOPEN

%ROWCOUNT

Indica o número de linhas lidas para o cursor associado (para cursores explícitos) ou o número de linhas afetadas no último comando INSERT, UPDATE, DELETE ou SELECT (para cursores implícitos). Após a abertura do cursor, o valor de ROWCOUNT é zero. O número só será incrementado se o último FETCH retornou uma linha. SINTAXE

<cursor> %ROWCOUNT SQL %ROWCOUNT

PROCESSAMENTO REPETITIVO - 55

Page 63: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE 2 CURSOR Wc is 3 SELECT CD_DEPTO, NM_FUNC, CD_MAT, VL_SAL FROM FUNC 3 ORDER BY 4 DESC; 4 Wcr_cd_depto FUNC.CD_DEPTO%TYPE; 5 Wcr_nm_func FUNC.NM_FUNC%TYPE; 6 Wcr_cd_mat FUNC.CD_MAT%TYPE; 7 Wcr_vl_sal FUNC.VL_SAL%TYPE; 8 BEGIN 9 OPEN Wc; 10 <<INICIO>> 11 FETCH Wc into Wcr_cd_depto, 12 Wcr_nm_func, 13 Wcr_cd_mat, 14 Wcr_vl_sal; 15 IF Wc%NOTFOUND THEN 16 GOTO fim; 17 END IF; 18 IF Wc%ROWCOUNT > 10 THEN 19 GOTO fim; 20 END IF; 21 INSERT INTO MAIORES (DEPTO, NOME, MAT, SAL) 22 VALUES (Wcr_cd_depto, Wcr_nm_func, Wcr_cd_mat, Wcr_vl_sal); 23 GOTO inicio; 24 <<FIM>> 25 COMMIT; 26 END; 27 / PL/SQL procedure successfully completed.

PROCESSAMENTO REPETITIVO - 56

Page 64: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

TIPO PARA CURSOR A fim de facilitar a recepção de informações de linhas de tabelas, a PL/SQL As variáveis PL/SQL e constantes possuem atributos, que são propriedades que permitem a referência ao tipo e estrutura do objeto sem necessidade de repetição de sua definição. As tabelas e colunas do database possuem atributos similares, que podemos usar para facilitar a manutenção.

%ROWTYPE

Este atributo gera um tipo de registro que representa uma linha da tabela. O tipo pode armazenar uma linha de dados selecionados da tabela ou recebidos de um cursor (FETCHED). SINTAXE

{<tabela> | <cursor>} %ROWTYPE

PROCESSAMENTO REPETITIVO - 57

Page 65: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO Criar uma tabela com o layout abaixo para receber a quantidade de funcionários por departamento. O código do departamento deverá convertido da mesma forma que no problema anterior. S

T

QL> CREATE TABLE resultado 2 (cd_depto NUMBER, 3 qt_func NUMBER 4 ) STORAGE (INITIAL 2K NEXT 2K MINEXTENTS 1 MAXEXTENTS 3);

able created.

SQL> DECLARE 2 Wnum NUMBER; 3 CURSOR Wc is SELECT cd_depto, count(*) total 4 FROM func GROUP BY cd_depto; 5 Wrow Wc%ROWTYPE; 6 BEGIN 7 OPEN Wc; 8 <<inicio>> 9 FETCH Wc INTO Wrow; 10 IF Wc%NOTFOUND THEN 11 GOTO fim; 12 END IF; 13 Wnum := TRANSLATE (SUBSTR(Wrow.cd_depto,1,1)), 14 'ABCDEFGHIJKLMNOPQRSTUVWXYZ, 15 '12345123451234512345123451') || 16 SUBSTR(Wrow.cd_depto,2,2); 17 INSERT INTO resultado (cd_depto, qt_func) 18 VALUES (Wnum, Wrow.total); 19 GOTO inicio; 20 <<fim>> 21 COMMIT; 22 END; 23 / PL/SQL procedure successfully completed.

PROCESSAMENTO REPETITIVO - 58

Page 66: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CURSOR LOOP Implicitamente declara uma área para receber a linha da tabela resultante, abre um cursor, lê cada linha e fecha o cursor quando todas as linhas tiverem sido processadas.

SINTAXE

[<< <label> >>] FOR <RECORD> IN <CURSOR> [(<parâmetro> [,<parâmetro>. . . ])] LOOP

<seqüência de comandos> END LOOP;

EXEMPLO

SQL> DECLARE

2 CURSOR Wc is SELECT DEPTO.cd_depto, nm_depto, 3 SUM(vl_sal) soma, AVG(vl_sal) media 4 FROM func, depto 5 WHERE func.cd_depto = depto.cd_depto 6 GROUP BY DEPTO.cd_depto, nm_depto; 7 BEGIN 8 FOR Wrow in Wc LOOP 9 INSERT INTO tabdep (nome, codigo, salario, media) 10 VALUES (Wrow.nm_depto, Wrow.cd_depto, 11 Wrow.soma, Wrow.media); 11 END LOOP; 12 COMMIT; 13 END; 14 / PL/SQL procedure successfully completed.

PROCESSAMENTO REPETITIVO - 59

Page 67: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

OUTROS COMANDOS PARA PROCESSAMENTO REPETITIVO

EXIT Encerra um loop.

SINTAXE

EXIT [<LABEL>] [WHEN <condição>]

LOOP A seqüência de comandos é executada um número infinito de vezes ou até que seja encontrado um comando "EXIT" ou a condição de "WHEN" seja satisfeita

SINTAXE

[<< <label> >>] LOOP

<seqüência de comandos> END LOOP

LOOP <seqüência de comandos> IF ..... THEN

EXIT; -- encerra o loop END IF;

END LOOP;

LOOP <seqüência de comandos> EXIT WHEN -- encerra o loop

END LOOP;

PROCESSAMENTO REPETITIVO - 60

Page 68: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO

Repetiremos o mesmo problema anterior, substituindo o comando GOTO pelo LOOP.

S T

QL> CREATE TABLE resultado 2 (cd_depto NUMBER, 3 qt_func NUMBER 4 ) STORAGE (INITIAL 2K NEXT 2K MINEXTENTS 1 MAXEXTENTS 3);

able created.

SQL> DECLARE 2 Wnum NUMBER; 3 CURSOR Wc is SELECT cd_depto, count(*) total 4 FROM func GROUP BY cd_depto; 5 Wrow Wc%ROWTYPE; 6 BEGIN 7 OPEN Wc; 8 LOOP 9 FETCH Wc INTO Wrow; 10 IF Wc%NOTFOUND THEN 11 EXIT; 12 END IF; 13 Wnum := TRANSLATE (SUBSTR(Wrow.cd_depto,1,1)), 14 'ABCDEFGHIJKLMNOPQRSTUVWXYZ, 15 '12345123451234512345123451') || 16 SUBSTR(Wrow.cd_depto,2,2); 17 INSERT INTO resultado (cd_depto, qt_func) 18 VALUES (Wnum, Wrow.total); 17 END LOOP; 18 COMMIT; 19 END; 20 / PL/SQL procedure successfully completed.

PROCESSAMENTO REPETITIVO - 61

Page 69: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

WHILE LOOP A seqüência de comandos é executada enquanto a condição for verdadeira. Antes de cada iteração do loop, a condição é avaliada. Se for verdadeira, a seqüência de comandos é executada.

SINTAXE

[<< <label> >>] WHILE <condição> LOOP

<seqüência de comandos> END LOOP;

PROCESSAMENTO REPETITIVO - 62

Page 70: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO

Preencher a tabela TABDEP (nome, codigo, salario, media) com os valores abaixo na tabela de departamentos:

nome............ nome do departamento codigo........... codigo do departamento salario........... somatório dos salários do departamento correspondente media............ média salarial do departamento correspondente

SQL> CREATE TABLE tabdep 2 (nome VARCHAR2(50), 3 codigo CHAR(03), 4 salario NUMBER(12,2), 5 media NUMBER(12,2) 6 ) 7 STORAGE (INITIAL 2K NEXT 2K MINEXTENTS 1 MAXEXTENTS 3) 8 / Table created.

S P

QL> DECLARE 2 CURSOR Wc is SELECT depto.cd_depto, nm_depto, 3 SUM(vl_sal) soma, AVG(vl_sal) media FROM func, depto 4 WHERE func.cd_depto = depto.cd_depto 5 GROUP BY depto.cd_depto, nm_depto; 6 Wrow Wc%ROWTYPE; 7 BEGIN 8 OPEN Wc; 9 FETCH Wc INTO Wrow; 10 WHILE Wc%FOUND LOOP 11 INSERT INTO tabdep (nome, codigo, salario, media) 12 VALUES (Wrow.nm_depto, Wrow.cd_depto, 13 Wrow.soma, Wrow.media); 14 FETCH Wc INTO Wrow; 15 END LOOP; 16 COMMIT; 17 END; 18 /

L/SQL procedure successfully completed.

PROCESSAMENTO REPETITIVO - 63

Page 71: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FOR LOOP A seqüência de comandos é executada um número fixo de vezes estabelecido no comando. No início do comando a quantidade de vezes que o mesmo será executado já é conhecida, uma vez que não se pode alterar o valor de <contador> durante a iteração.

OBS: O <contador> é declarado no próprio comando.

SINTAXE

[<< <label> >>] FOR <contador> IN [REVERSE] <inferior>..<superior> LOOP

<seqüência de comandos> END LOOP;

SQL> DECLARE 2 Wvezes NUMBER := 0; 3 Werro NUMBER := 0; 4 BEGIN 5 FOR i IN 1..3 LOOP -- <seqüência de comandos> 6 Wvezes := i + 1; -- executada 3 vezes 7 END LOOP; -- o comando Werro é inválido, pois i só 8 Werro := i + 1; -- existe no escopo do comando FOR 9 END; 10 / Werro := i + 1; -- existe no escopo do comando FOR * ERROR at line 8: ORA-06550: line 8, column 12: PLS-00201: identifier 'I' must be declared ORA-06550: line 8, column 3: PL/SQL: Statement ignored

PROCESSAMENTO REPETITIVO - 64

Page 72: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE

2 Wvezes NUMBER := 0; 3 Werro NUMBER := 0; 4 Winicio NUMBER := 1; 5 Wfim NUMBER := 4; 6 BEGIN 7 FOR i IN Winicio..Wfim LOOP -- <seqüência de comandos> 8 Wvezes := Wvezes + 1; -- executada n vezes dependendo 9 END LOOP; -- do valor de início e fim 10 -- 11 FOR i IN 3..Winicio LOOP -- <seqüência de comandos> 12 Wvezes := 100; -- não será executada 13 END LOOP; 14 :msg := 'Wvezes = ' || TO_CHAR(Wvezes); 15 END; 16 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG ------------------------------------------------------------------------ Wvezes = 4

PROCESSAMENTO REPETITIVO - 65

Page 73: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE 2 Wvezes NUMBER := 0; 3 Werro NUMBER := 0; 4 Wexterno NUMBER := 0; 5 Winterno NUMBER := 0; 6 Winicio NUMBER := 1; 7 Wfim NUMBER := 4; 8 BEGIN 9 FOR i IN REVERSE 1..3 LOOP -- <seqüência de comandos> 10 Wvezes := Wvezes + 1; -- será executada 3 vezes 11 END LOOP; -- i terá o valor inicial de 3 12 <<externo>> 13 FOR i IN 1..4 LOOP -- no exemplo foram criadas 14 Wexterno := Wexterno + 1; -- duas variáveis i 15 <<interno>> 16 FOR i IN 2..10 LOOP -- a referência a cada variável 17 Winterno := Winterno + 1; -- externo é feita através do label 18 EXIT externo WHEN externo.i = interno.i; 19 END LOOP interno; -- esta forma de interrupção 20 END LOOP externo; -- encerra os dois níveis de loops 21 :msg := 'Wvezes = ' || Wvezes ||' Wexterno = ' || TO_CHAR(Wexterno); 22 END; 23 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG ------------------------------------------------------------------------------------------ Wvezes = 3 Wexterno = 2

PROCESSAMENTO REPETITIVO - 66

Page 74: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 4 : TRATAMENTO DE ERROS EM PL/SQL Em PL/SQL uma WARNING ou ERROR CONDITION é chamada uma EXCEPTION. Existem algumas exceções já definidas pelo ORACLE com mnemônicos para referência. Para as demais, podem ser dados nome pelo usuário, como veremos neste capítulo. Quando ocorre um erro, uma EXCEPTION é setada, isto é, a seqüência de execução do programa é interrompida e o controle é transferido para a área de tratamento de exceção do programa. As exceções pré-definidas pelo ORACLE são setadas quando a condição de erro ocorre. As exceções criadas pelo programa deverão ser setadas explicitamente pelo verbo RAISE.

DECLARE <declarações>............. opcional BEGIN <lógica>...................... obrigatória EXCEPTION <erros>....................... opcional END;

TRATAMENTO DE ERROS EM PL/SQL - 67

Page 75: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXCEÇÕES PRÉ-DEFINIDAS

NOME DA EXCEÇÃO ORACLE ERROR

SQLCODE CONDIÇÃO DE ERRO

CURSOR_ALREADY_OPEN ORA-06511 -6511 É causada se for executado um OPEN para um cursor já aberto.

DUP_VAL_ON_INDEX ORA-00001 -1 É causada se for tentada uma inclusão de uma coluna com valor duplicado em uma tabela que possui um índice único nesta coluna.

INVALID_CURSOR ORA-01001 -1001 É causada se for feita uma operação ilegal com um cursor. Por exemplo: CLOSE em um cursor não aberto.

ORA-01722 -1722 É causada se algum comando SQL tentou uma conversão de uma string para número e esta conversão falha porque a string não representa um número.

LOGIN_DENIED ORA-01017 -1017 É causada se for feita uma tentativa de logon com um username/password inválido.

NO_DATA_FOUND ORA-01403 +100 É causada se num SELECT INTO nenhuma row foi retornada ou se foi feita uma referência a uma row não inicializada em uma tabela PL/SQL.

NOT_LOGGED_ON ORA-01012 -1012 É causada se um programa PL/SQL tenta fazer acesso ao database sem efetuar um logon.

INVALID_NUMBER

TRATAMENTO DE ERROS EM PL/SQL - 68

Page 76: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

NOME DA EXCEÇÃO ORACLE

ERROR SQLCODE CONDIÇÃO DE ERRO

PROGRAM_ERROR ORA-06501 -6501 É causada se ocorrer um problema interno.

STORAGE_ERROR ORA-06500 -6500 É causada se PL/SQL sai da memória ou se a memória estiver corrompida.

TIMEOUT_ON_RESOURCE ORA-00051 -51 É causada se ocorrer timeout enquanto o Oracle estiver aguardando por um recurso.

TOO_MANY_ROWS ORA-01422 -1422 É causada se um comando SELECT INTO retornar mais que uma row.

TRANSACTION_BACKED_OUT

ORA-00061 -61 É causada quando a parte remota de uma transação é desmanchada. A transação local deve ser desmanchada também.

VALUE_ERROR ORA-06502 -6502 É causada se uma operação aritmética, conversão, constraint error, truncation ocorrer.

ZERO_DIVIDE ORA-01476 -1476 É causada se houver ocorrido uma divisão por zero.

TRATAMENTO DE ERROS EM PL/SQL - 69

Page 77: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DEFININDO UMA EXCEPTION Nomeia uma exceção definida pelo usuário.

SINTAXE

<nome da exceção> EXCEPTION

CAUSANDO UMA EXCEPTION CRIADA PELO USUÁRIO A PL/SQL permite que sejam definidas exceções dentro de um programa. Este tipo de exceção deve ser setada explicitamente pelo verbo RAISE.

RAISE Causa uma exceção.

SINTAXE

RAISE <exceção>

TRATAMENTO DE ERROS EM PL/SQL - 70

Page 78: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO

Fazer um programa para crítica de dados informados através de parâmetros :

◊ salário deve estar entre R$1500 e R$2000 mensais. ◊ departamento deve existir na tabela de departamentos

SQL> DECLARE 2 w_salario NUMBER(7,2) := &sal; 3 w_depto CHAR(3) := UPPER('&depto'); 4 w_nome CHAR(8) := UPPER('&nome'); 5 e_salario EXCEPTION; 6 w_aux NUMBER(3) := 0; 7 BEGIN 8 IF w_salario < 1500 OR w_salario > 2000 THEN 9 RAISE e_salario; 10 END IF; 11 SELECT 0 INTO w_aux FROM depto 12 WHERE cd_depto = w_depto; 13 SELECT MAX(cd_mat) INTO w_aux FROM func; 14 INSERT INTO func (cd_mat, vl_sal, cd_depto, nm_func) 16 VALUES (w_aux + 1, w_salario , w_depto, w_nome); 17 EXCEPTION 18 WHEN NO_DATA_FOUND THEN 19 :MSG := 'DEPARTAMENTO INVALIDO'; 20 WHEN e_salario THEN 21 :MSG := 'SALARIO INVALIDO'; 22 WHEN OTHERS THEN 23 :MSG := SQLERRM(SQLCODE); 24 END; 25 /

Obs.: O desvio de execução do programa é transferido para a exceção OTHERS quando o erro ocorrido não foi tratado em outras exceções mais específicas.

TRATAMENTO DE ERROS EM PL/SQL - 71

Page 79: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PRAGMA EXCEPTION_INIT Associa um nome de exceção com um número de SQLCODE. Isto permite que se façam testes de erro mais específicos em vez de se usar OTHERS.

SINTAXE

PRAGMA EXCEPTION_INIT (<nome da exceção>, <número>)

EXEMPLO

SQL> DECLARE 2 sem_privilegio EXCEPTION; 3 PRAGMA EXCEPTION_INIT (sem_privilegio, -1031); 4 BEGIN ... 20 EXCEPTION 21 WHEN sem_privilegio THEN ... 30 END; 31 /

Obs: O Oracle retorna o erro -1031 se, por exemplo, for feita uma tentativa de alterar uma tabela em que o usuário só tem autorização de SELECT

TRATAMENTO DE ERROS EM PL/SQL - 72

Page 80: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

RAISE_APPLICATION_ERROR É uma PROCEDURE que permite ao usuário enviar mensagens de um subprograma ou DATABASE TRIGGER.

SINTAXE

RAISE_APPLICATION_ERROR (<número>, <mensagem>); Onde:

◊ <número> - pode variar de -20000 a -20999 ◊ <mensagem> - pode possuir até 512 bytes de comprimento.

TRATAMENTO DE ERROS EM PL/SQL - 73

Page 81: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROPAGAÇÃO DA EXCEÇÃO Quando uma exceção é causada, se a PL/SQL não encontrar um tratamento para ela no bloco corrente ou subprograma, a exceção se propaga. Ou seja, a exceção se reproduz no bloco externo e assim por diante até que a PL/SQL retorne um erro para o ambiente (abortando o programa).

SQL>DECLARE 2 Wx NUMBER := &x; 3 a EXCEPTION; 4 b EXCEPTION; 5 c EXCEPTION; 6 BEGIN 7 :msg := 'Inicio '; 8 BEGIN 9 IF Wx = 1 THEN 10 RAISE A; 11 ELSIF Wx = 2 THEN 12 RAISE B; 13 ELSE RAISE C; 14 END IF; 15 EXCEPTION 16 WHEN A THEN 17 :msg := :msg || '- executou when A'; 18 END; 19 :msg := :msg || '- seguiu programa'; 20 EXCEPTION 21 WHEN B THEN 22 :msg := :msg || '- executou when B'; 23 END; 24 /

A exceção A é tratada no bloco mais interno. Após seu tratamento o programa continua normalmente. A exceção B se propaga para o bloco mais externo, é tratada e o programa termina normalmente. A exceção C se propaga para o bloco mais externo, não é tratada e o erro passa para o ambiente, isto é, o programa é abortado.

TRATAMENTO DE ERROS EM PL/SQL - 74

Page 82: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 5 TABELAS E REGISTROS EM PL/SQL Em PL/SQL podemos criar áreas de memória complexas, formadas por áreas de repetição ou áreas estruturadas.

TABLE Tabelas PL/SQL podem ter somente uma coluna e uma primary key, nenhuma das quais nomeadas. A declaração cria um tipo de variável. Deve ser feita uma declaração de variável com o tipo criado posteriormente para uso.

SINTAXE

TYPE <nome> IS TABLE OF

{<tipo coluna> | <tabela>.<coluna>%TYPE | <tabela> %ROWTYPE | <record> } [NOT NULL] INDEX BY BINARY_INTEGER

EXEMPLOS

1. Definir uma tabela com cada posição de tamanho NUMBER(10). 2. Definir uma tabela com cada posição correspondente ao layout da tabela FUNC.

NUMBER(10)NUMBER(10) NUMBER(10) NUMBER(10)

SQL> DECLARE 2 TYPE arr_num IS TABLE OF NUMBER(10) 3 INDEX BY BINARY_INTEGER; 4 BEGIN

SQL> DECLARE 2 TYPE arr_func IS TABLE OF func%ROWTYPE 3 INDEX BY BINARY_INTEGER; 4 BEGIN

TABELAS E REGISTROS EM PL/SQL - 75

Page 83: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> VARIABLE msg VARCHAR2(60)

SQL> DECLARE 2 TYPE tipotab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; 3 fibo tipotab; 4 Wtotal PLS_INTEGER := 2; 5 BEGIN 6 fibo(1) := 1; 7 fibo(2) := 1; 8 FOR i IN 3..30 LOOP 9 fibo(i) := fibo (i-2) + fibo(i-1); 10 Wtotal := Wtotal + fibo(i); 11 END LOOP; 12 :msg := 'O somatório dos 30 primeiros termos é ' || TO_CHAR(Wtotal); 13 END; 14 / PL/SQL procedure successfully completed. SQL> PRINT msg MSG --------------------------------------------------------------------------- O somatório dos 30 primeiros termos é 2178308

TABELAS E REGISTROS EM PL/SQL - 76

Page 84: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

RECORD Permite a criação de uma área estruturada.

SINTAXE

TYPE <nome> IS RECORD

(<campo1>{<tipo campo>|<tabela>.<coluna>%TYPE}[NOT NULL], <campo2>{<tipo campo>|<tabela>.<coluna>%TYPE}[NOT NULL]...)

SQL> DECLARE 2 TYPE tiporeg IS RECORD 3 (nome VARCHAR2(40), 4 depto VARCHAR2(40)); 5 Wreg tiporeg; 6 BEGIN 7 SELECT LTRIM(RTRIM(nm_func)) || ' ' || 8 LTRIM(RTRIM(nm_sobrenome)), nm_depto 9 INTO Wreg 10 FROM func, depto 11 WHERE func.cd_depto = depto.cd_depto 12 AND func.cd_mat = &mat; 13 :msg := Wreg.depto || ' - ' || Wreg.nome; 14 END; 15 / Enter value for mat: 120 old 12: AND func.cd_mat = &mat; new 12: AND func.cd_mat = 120; PL/SQL procedure successfully completed. SQL> PRINT msg MSG --------------------------------------------------------------------------- DIRETORIA - SILVIO OLIVA

TABELAS E REGISTROS EM PL/SQL - 77

Page 85: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ATRIBUTOS DE UMA TABELA PL/SQL

EXISTS (N) Retorna TRUE se o enésimo elemento em uma tabela PL/SQL existe. OBS.: O teste de existência controla o recebimento da exceção NO_DATA_FOUND, que é adquirido quando fazemos referência a um elemento inexistente.

COUNT Retorna o número de elementos que uma tabela PL/SQL possui.

FIRST E LAST Retorna o primeiro (menor) e o último (maior) número de índice de uma tabela PL/SQL. Se a tabela estiver vazia, FIRST e LAST retornam NULL. Se a tabela contiver um único elemento, FIRST E LAST retornam o mesmo índice.

PRIOR(N) E NEXT(N) Retorna o índice que precede o índice n, no caso de PIOR e o seguinte, no caso de NEXT.

DELETE, DELETE(N) E DELETE(M,N) O formato DELETE remove todos os elementos de uma tabela PL/SQL. DELETE(n) remove o enésimo elemento e DELETE (m,n) remove todos os elementos no intervalo m...n. Se m for maior que n ou se m ou n forem null, DELETE não tem efeito. OBS.: A quantidade de memória alocada por uma tabela PL/SQL pode aumentar ou diminuir dinamicamente. Conforme os elementos vão sendo removidos, a memória vai sendo liberada (página por página).

TABELAS E REGISTROS EM PL/SQL - 78

Page 86: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SQL> DECLARE 2 CURSOR WC is SELECT * FROM func ORDER BY vl_sal; 3 ---- Declaração de Tipos 4 TYPE tipofunc IS TABLE OF func%ROWTYPE 5 INDEX BY BINARY_INTEGER; 6 TYPE registro IS RECORD 7 ( salario number); 8 TYPE tabsal IS TABLE OF registro 9 INDEX BY BINARY_INTEGER; 10 --- Declaração de variáveis 11 Wsal tabsal; 12 Wfunc tipofunc; 13 Wlinha func%ROWTYPE; 14 Wvezes NUMBER := &n; 15 Wtotal NUMBER := 0; 16 BEGIN 17 OPEN wc; 18 FETCH wc INTO wlinha; 19 WHILE Wvezes > 0 and wc%FOUND LOOP 20 Wfunc(wlinha.cd_mat) := Wlinha; 21 Wvezes := Wvezes - 1; 22 FETCH wc INTO wlinha; 23 END LOOP; 24 FOR i in 1..999 LOOP 25 IF Wfunc.EXISTS(i) THEN 26 Wtotal := Wtotal + Wfunc(i).vl_sal; 27 END IF; 28 END LOOP; 29 :msg := 'Valor Total = ' || Wtotal; 30 END ; 31 / Enter value for n: 10 old 14: Wvezes NUMBER := &n; new 14: Wvezes NUMBER := 10; PL/SQL procedure successfully completed.

TABELAS E REGISTROS EM PL/SQL - 79

Page 87: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 6 : SUBPROGRAMAS EM PL/SQL Subprogramas são blocos PL/SQL com nome, que podem receber parâmetros e ser invocados. A PL/SQL possui dois tipos de subprogramas chamados PROCEDURES e FUNCTIONS. Geralmente usa-se uma PROCEDURE para executar uma ação e uma função para calcular um valor. Da mesma forma que qualquer outro bloco (anônimo) PL/SQL, os subprogramas possuem uma parte declarativa, uma parte executável e uma parte opcional para tratamento de erro. Os subprogramas podem ser definidos em qualquer ferramenta ORACLE que suporte PL/SQL. Os subprogramas devem ser declarados no fim da parte declarativa, após todos os outros objetos do programa.

EXEMPLO

SQL> DECLARE 2 w_vl_lim NUMBER(15,2) := &1; . . . 5 PROCEDURE calc_ir (val_ir OUT NUMBER) IS 6 BEGIN . . . 9 END calc_ir; 10 FUNCTION calc_inss (val_sal IN NUMBER) RETURN NUMBER IS 11 val_inss NUMBER(15,2); 12 BEGIN . . . 13 RETURN val_inss; 14 END calc_inss; 15 BEGIN . . . 21 END; 22 /

SUBPROGRAMAS EM PL/SQL - 80

Page 88: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROCEDURES As procedures são subprogramas que executam uma ação específica.

SINTAXE

PROCEDURE <nome da procedure> [(<parâmetro>[,<parâmetro>,.])] IS [<variáveis locais>] BEGIN

<comandos> [EXCEPTION

<tratamento das exceções>] END [<nome da procedure>];

Onde parâmetro possui a seguinte sintaxe:

<nome da variável> [ IN | OUT | IN OUT] <tipo> [{ := | DEFAULT} <valor>] OBS.: Quando [IN | OUT ...] não for especificado, será assumido IN. Na especificação de <tipo> não deve ser informado tamanho.

EXEMPLO

SQL> DECLARE . . . 2 PROCEDURE calc_ir (val_sal IN NUMBER, val_ir OUT NUMBER) IS 3 BEGIN 4 IF val_sal < 300.00 THEN 5 val_ir := 0; 6 ELSIF val_sal BETWEEN 300.01 AND 1000.00 THEN 7 val_ir := val_sal * .10; 8 ELSIF val_sal BETWEEN 1000.01 AND 3000.00 THEN 9 val_ir := val_sal * .20; 10 ELSE 11 val_ir := val_sal * .30; 12 END IF; 13 END calc_ir; 14 BEGIN . . . 20 END; 21 /

SUBPROGRAMAS EM PL/SQL - 81

Page 89: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FUNCTIONS Uma função é um subprograma que calcula um valor. Funções e procedures são estruturalmente iguais, exceto que funções possuem uma cláusula RETURN que especifica o tipo de retorno da função.

SINTAXE

FUNCTION <nome da função> [(<parâmetro>[,<parâmetro>,...])] RETURN <tipo da função> IS

[<variáveis locais>] BEGIN

<comandos> [EXCEPTION

<tratamento das exceções>] END <nome da função>];

Onde parâmetro possui a seguinte sintaxe:

<nome da variável> [ IN | OUT | IN OUT] <tipo> [{ := | DEFAULT} <valor>] OBS.: Quando [IN | OUT ...] não for especificado, será assumido IN. SQL> DECLARE

. . . 5 FUNCTION calc_inss (val_sal IN NUMBER, val_lim IN NUMBER) 6 RETURN NUMBER IS 7 val_inss NUMBER(15,2); 8 BEGIN 9 val_inss := val_sal * .08; 10 IF val_inss > val_lim THEN 11 val_inss := val_lim; 12 END IF; 13 RETURN val_inss; 14 END calc_inss; 15 BEGIN . . . 20 END; 21 /

SUBPROGRAMAS EM PL/SQL - 82

Page 90: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DECLARAÇÕES FORWARD A PL/SQL exige que se declare um subprograma antes de usá-lo. No caso de recursividade, porém isto não é possível. A PL/SQL resolve este problema com uma declaração FORWARD. Esta declaração pode ser usada para :

◊ definir subprogramas em ordem alfabética ◊ definir subprogramas recursivos ◊ grupar subprogramas dentro de PACKAGES

Uma declaração FORWARD consiste de uma declaração de subprograma terminada por ;. SQL> DECLARE

2 w_vl_lim NUMBER(15,2) := &1; . . . 6 PROCEDURE proc (salario IN NUMBER); -- declaração forward 7 FUNCTION teste RETURN NUMBER; -- declaração forward 8 FUNCTION calc_inss (val_sal IN NUMBER,val_lim IN NUMBER) 9 RETURN NUMBER IS 10 val_inss NUMBER(15,2); 11 BEGIN . . . 18 RETURN val_inss; 19 END calc_inss; 20 FUNCTION teste RETURN NUMBER IS 21 Waux NUMBER; 22 BEGIN . . . 25 END teste; 26 PROCEDURE proc (salario IN NUMBER) IS 27 BEGIN . . . 33 END proc; 34 BEGIN . . . 35 END; 36 /

SUBPROGRAMAS EM PL/SQL - 83

Page 91: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

STORED SUBPROGRAMS No ORACLE é possível armazenar um subprograma PL/SQL na base de dados após a compilação.

VANTAGENS

PRODUTIVIDADE Vários programas podem fazer uso de rotinas previamente gravadas na base de dados, diminuindo a redundância de codificação.

PERFORMANCE Subprogramas podem reduzir a necessidade de calls nas aplicações. Por exemplo, para executar 10 comandos SQL individuais, 10 calls são necessários, porém para executar um subprograma contendo dez comandos SQL, apenas um call é necessário.

MEMÓRIA Subprogramas tem a vantagem de compartilhar memória. Ou seja, somente uma cópia de um subprograma necessita ser carregada na memória para execução por múltiplos usuários.

INTEGRIDADE A utilização de librarys diminui a possibilidade de erros na codificação de rotinas de consistência, uma vez que só há a necessidade de se efetuar a validação da rotina uma vez e ela poderá ser usada por qualquer número de aplicações.

SEGURANÇA Pode haver uma aumento na segurança, uma vez que o DBA pode restringir o acesso a determinadas operações, fornecendo autorização somente através de subprogramas.

SUBPROGRAMAS EM PL/SQL - 84

Page 92: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CHAMADAS DE UM STORED SUBPROGRAM

LOCAL SINTAXE De outro subprograma

<nome da procedure> (<parâmetro> . . . );

De um programa de aplicação (HOST)

EXEC SQL EXECUTE BEGIN <nome da procedure> (<parâmetro> . . .); END; END-EXEC;

No SQL*PLUS EXECUTE <nome da procedure> (<parâmetro> . . . ); No PL/SQL BEGIN <nome da procedure> (<parâmetro> . . .); END;

SUBPROGRAMAS EM PL/SQL - 85

Page 93: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CRIANDO UM STORED SUBPROGRAM

SINTAXE

CREATE [OR REPLACE] PROCEDURE <nome da procedure>[(<parâmetro>[,<parâmetro>,...])] AS/IS [<variáveis locais>] BEGIN

<comandos> [EXCEPTION

<tratamento das exceções>] END [<nome da procedure>];

CREATE [OR REPLACE] FUNCTION <nome da função> [(<parâmetro>[,<parâmetro>,...])]

RETURN <tipo da função> AS/IS [<variáveis locais>] BEGIN

<comandos> [EXCEPTION

<tratamento das exceções>] END [<nome da função>];

A sintaxe é semelhante à de um SUBPROGRAM definido dentro de um programa PL/SQL. Posteriormente à criação do stored subprogram podemos fazer referência a ela nos programas de aplicação.

SUBPROGRAMAS EM PL/SQL - 86

Page 94: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

UTILIZAÇÃO

A utilização de uma função criada na base de dados pode ser referenciada em comandos SQL.

SQL> CREATE FUNCTION nova_data(pdata IN DATE) RETURN CHAR IS 2 BEGIN 3 RETURN (TO_CHAR (pdata,'DD/MM/YYYY HH24:Mi')); 4 END; 5 / Function created.

SQL> COL nasc FOR A20 SQL> COL adm FOR A20 SQL> SELECT nova_data(dt_nasc) NASC, nova_data(dt_adm) ADM 2 FROM func 3 WHERE ROWNUM < 5;

NASC ADM -------------------- -------------------- 14/08/1953 00:00 01/01/1995 00:00 02/02/1968 00:00 01/10/1993 00:00 11/05/1961 00:00 05/04/1995 00:00 15/09/1955 00:00 17/08/1989 00:00

SUBPROGRAMAS EM PL/SQL - 87

Page 95: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DEPENDÊNCIA REMOTA Normalmente o ORACLE usa somente o TIMESTAMP para gerenciar dependências remotas das bibliotecas de PL/SQL, isto é, PACKAGES e programas armazenados na base. Quando uma unidade de programa é recompilada, o ORACLE associa o TIMESTAMP do servidor a ela. A tempo de execução os subprogramas dependentes em um ambiente cliente ou em outro servidor são inválidos porque seu TIMESTAMP é anterior ao da rotina chamada. Frequentemente, porém a recompilação não era realmente necessária uma vez que a parte da especificação (ou seja os parâmetros passados) não havia sido modificada. Agora, o ORACLE pode usar TIMESTAMPS ou SIGNATURES para gerenciar dependências remotas. Quando o ORACLE usa o SIGNATURE (que inclui o nome do programa, número, tipo e modo dos parâmetros) de uma unidade de programa remoto, os subprogramas dependentes serão inválidos somente se a SIGNATURE ou especificação da unidade foi alterada. Assim, subprogramas dependentes são recompilados somente quando necessário. Para que o ORACLE use SIGNATURE em vez de TIMESTAMP devemos setar o seguinte parâmetro no arquivo de inicialização do ORACLE (INIT.ORA):

REMOTE_DEPENDENCIES_MODE = SIGNATURE Podemos alterar o parâmetro dinamicamente:

ALTER SESSION SET REMOTE_DEPENDENCIES_MODE = TIMESTAMP

SUBPROGRAMAS EM PL/SQL - 88

Page 96: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

USO DE TABELAS PL/SQL COMO PARÂMETRO DE SUBPROGRAMAS Uma tabela PL/SQL pode ser usada como retorno de uma função.

USANDO UMA TABELA LOCAL PARA RECEPÇÃO DO PARÂMETRO

O programa principal deve declarar uma tabela local para que todo o resultado da função possa ser retornado e, então, utilizar os elementos desejados da tabela local.

SQL> DECLARE 2 TYPE tabcargo IS TABLE OF func.nr_cargo% type 3 INDEX BY BINARY_INTEGER; 4 cargo tabcargo; 5 nr_cargo func.nr_cargo%type; 6 FUNCTION novo_cargo RETURN tabcargo IS 7 tabnovocargo tabcargo; 8 BEGIN . . . 15 RETURN tabnovocargo; 16 END; 17 BEGIN . . . 25 cargo:= novo_cargo; 26 nr_cargo:= cargo(1); . . . 35 END; 36 /

SUBPROGRAMAS EM PL/SQL - 89

Page 97: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FAZENDO REFERÊNCIA DIRETA A UM ELEMENTO DA TABELA

Para fazermos referência a um elemento da tabela PL/SQL devemos usar o indexador. Da mreferê

OBS:usadapode

SQL> DECLARE 2 TYPE tabsal IS TABLE OF func.vl_sal%TYPE 3 INDEX BY BINARY_INTEGER; 4 salario REAL; 5 FUNCTION PROMOCAO (max_sal REAL) RETURN tabsal IS 6 sal_tab tabsal; 7 BEGIN . . . 12 RETURN saltab; 13 END; 14 BEGIN 15 salario:= promocao(500)(3); . . . 25 END;

esma forma, nas funções que retornam um registro PL/SQL, podemos fazer ncia direta a um elemento do registro.

SQL> DECLARE 2 TYPE tabdep IS TABLE OF depto%ROWTYPE 3 INDEX BY BINARY_INTERGER; 4 FUNCTION NewDepto (MaxNum INTEGER) RETURN tabdep IS 5 RegDepto tabdep; 6 BEGIN . . . 10 RETURN RegDepto; 11 END; 12 BEGIN . . . 13 IF NewDepto (90) (3).cd_depto=’C01’ then . . . 20 END;

Como restrição às duas formas de uso acima temos que ela não pode ser para uma função que não tenha parâmetros, uma vez que em PL/SQL não

mos usar uma lista de parâmetros vazia: função( ) (indice) é inválido.

SUBPROGRAMAS EM PL/SQL - 90

Page 98: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 7 : TRIGGERS E PACKAGES

DATABASE TRIGGERS Um DATABASE TRIGGER é um programa PL/SQL armazenado em um banco ORACLE, associado com uma tabela específica. O ORACLE irá executar o DATABASE TRIGGER automaticamente quando uma determinada operação SQL afetar a tabela.

OBJETIVO Podemos usar um DATABASE TRIGGER para:

◊ Logar modificações ◊ Garantir críticas complexas ◊ Gerar o valor de colunas ◊ Implementar níveis de segurança mais complexos ◊ Manter tabelas duplicadas

CARACTERÍSTICAS Podemos associar até 12 DATABASE TRIGGERS a cada tabela, um de cada tipo:

◊ BEFORE UPDATE <row> ◊ AFTER UPDATE <row> ◊ BEFORE DELETE <row> ◊ AFTER DELETE <row> ◊ BEFORE INSERT <row> ◊ AFTER INSERT <row> ◊ BEFORE INSERT <comando> ◊ AFTER INSERT <comando> ◊ BEFORE UPDATE <comando> ◊ AFTER UPDATE <comando> ◊ BEFORE DELETE <comando> ◊ AFTER DELETE <comando>

As palavras BEFORE e AFTER indicam se o TRIGGER será executado antes ou depois do evento que o causou.

TRIGGERS E PACKAGES - 91

Page 99: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SINTAXE Um DATABASE TRIGGER é composto de 3 partes:

◊ Evento ◊ Restrição (opcional) ◊ Ação

Quando o evento ocorre, o TRIGGER é disparado e um bloco PL/SQL “anônimo” executa a ação. A sintaxe CREATE OR REPLACE permite que executemos o script com o texto do trigger tanto para criação quanto para modificação do trigger.

CREATE [OR REPLACE] TRIGGER <nome trigger> {BEFORE | AFTER}

{ DELETE | INSERT | UPDATE [OF <coluna>[,<coluna>] . . ] [OR DELETE | INSERT | UPDATE [OF <coluna>[,<coluna>] . .] .}

ON <tabela> [REFERENCING{OLD [AS] <nome> | NEW [AS] <nome>

[OLD [AS] <nome> | NEW [AS] <nome>]} FOR EACH ROW [WHEN (<condição>)]]

Evento

Condição

Ação <bloco PL/SQL>

OBS.: Os DATABASE TRIGGERS executam com os privilégios do OWNER e não do usuário que causou o evento.

PREDICADOS CONDICIONAIS Quando criamos um trigger que esteja associado a mais de uma operação DML, podemos utilizar os predicados condicionais a fim de determinarmos o tipo de comando DML causador da execução do trigger.

INSERTING – Retorna TRUE se o trigger foi disparado por causa de um comando INSERT.

UPDATING – Retorna TRUE se o trigger foi disparado por causa de um comando UPDATE.

DELETING – Retorna TRUE se o trigger foi disparado por causa de um comando DELETE.

TRIGGERS E PACKAGES - 92

Page 100: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXEMPLO

SQL> CREATE TRIGGER checa_salario 2 BEFORE UPDATE OF vl_sal, nr_git ON FUNC 3 FOR EACH ROW WHEN (NEW.nr_git < 56) 4 DECLARE 5 salario_minimo NUMBER(5) := 0; 6 salario_maximo NUMBER(5) := 0; 7 faixa EXCEPTION; 8 negativo EXCEPTION; 9 BEGIN 10 SELECT MIN(vl_sal), MAX(vl_sal) 11 INTO salario_minimo, salario_maximo 12 FROM folha 13 WHERE nr_git = :new.nr_git; 14 IF (:NEW.vl_sal < salario_minimo OR 15 :NEW.vl_sal > salario_maximo) THEN 16 RAISE faixa; 17 ELSIF (:NEW.vl_sal < :OLD.vl_sal) THEN 18 RAISE negativo; 19 END IF; 20 EXCEPTION 21 WHEN faixa THEN 22 RAISE_APPLICATION_ERROR(-20225, ‘Salário fora da faixa’); 23 WHEN negativo THEN 24 RAISE_APPLICATION_ERROR(-20230, ‘Incremento negativo’); 25 WHEN OTHERS THEN 26 RAISE_APPLICATION_ERROR(-20999, SQLERRM(SQLCODE)); 27 END; 28 /

TRIGGERS E PACKAGES - 93

Page 101: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

COMPILANDO TRIGGERS Antes da versão 7.3, um TRIGGER era ´PARSED´ e compilado toda vez que o TRIGGER fosse disparado. A partir da versão 7.3, a versão compilada do TRIGGER é armazenada no dicionário de dados e será chamada quando o TRIGGER for executado. Se o TRIGGER tiver erros de compilação, ainda assim ele será armazenado, porém falhará a tempo de execução. Esta nova característica irá dar significativo ganho de performance.

HABILITANDO, DESABILITANDO E COMPILANDO TRIGGERS O comando ALTER TRIGGER possui três opções ENABLE, DISABLE e COMPILE, que permitirão :

◊ Que desabilitemos temporariamente um trigger objetivando por exemplo a carga de dados.

◊ Que compilemos um trigger previamente cadastrado. Se a compilação for bem sucedida, o trigger torna-se válido. Por outro lado se a compilação retornar erro, o trigger torna-se inválido.

SINTAXE

ALTER TRIGGER <nome trigger> ENABLEDISABLECOMPILE

TRIGGERS E PACKAGES - 94

Page 102: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PACKAGES Um PACKAGE é um objeto que grupa logicamente subprogramas, objetos e tipos PL/SQL. São compostos de duas partes:

◊ especificação ◊ corpo do pacote

VANTAGENS

MODULARIDADE Packages permitem que se encapsule logicamente tipos, objetos e subprogramas relacionados.

DESENHO DA APLICAÇÃO

Quando uma aplicação é desenhada, tudo que é necessário inicialmente é a informação da especificação do package. Pode-se codificar e compilar a especificação sem o corpo do package. Uma vez que a especificação tenha sido compilada e o subprograma armazenado a referência ao pacote pode ser compilada também.

SEGURANÇA Com pacotes pode-se especificar que tipos, objetos e subprogramas são públicos ou privados. Os públicos são especificados na parte de especificação dos packages. Já os privados são totalmente especificados no corpo do package. Eles são usados dentro do próprio pacote e não precisam ficar visíveis a quem usar os pacotes.

FUNCIONALIDADE

Variáveis públicas e cursores empacotados podem ser compartilhados por todas as procedures que executarem no ambiente.

PERFORMANCE Quando é feita a primeira chamada de um package subprogram pela primeira vez, todo o pacote é carregado na memória. Assim, subsequentes chamadas a outros subprogramas dentro do pacote não requerem I/O de disco.

TRIGGERS E PACKAGES - 95

Page 103: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

ESPECIFICAÇÃO A especificação é a interface com as aplicações. Nela são declarados os tipos, variáveis, constantes, exceções, cursores e subprogramas. Para os subprogramas são feitas, apenas declarações FORWARD. Na parte de especificação são feitas declarações públicas, visíveis pelas aplicações.

CORPO No corpo do pacote é concluída a definição dos cursores e subprogramas e feita a implementação da especificação. O corpo implementa detalhes e declarações privadas que são invisíveis pelas aplicações. O corpo seria uma caixa preta.

TRIGGERS E PACKAGES - 96

Page 104: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

SINTAXE A sintaxe CREATE OR REPLACE permite que executemos o script com o texto do package tanto para criação quanto para modificação do pacote.

ESPECIFICAÇÃO

CREATE [OR REPLACE] PACKAGE <nome do pacote> IS

<declarações> END [<nome do pacote>];

CORPO

CREATE [OR REPLACE] PACKAGE BODY <nome do pacote> IS

<corpo dos subprogramas> [BEGIN

<comandos de inicialização>] END [<nome do pacote>];

Deve-se observar que somente a especificação do pacote é visível e acessível pela aplicação. Detalhes da implementação que se localizam do BODY são invisíveis e inacessíveis. Desta forma pode-se alterar o BODY sem haver necessidade de se recompilar os programas que usarem os PACKAGES.

TRIGGERS E PACKAGES - 97

Page 105: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXEMPLO

ESPECIFICAÇÃO

CORPO

SQL> CREATE OR REPLACE PACKAGE funcionario AS 2 TYPE RegFunc IS RECORD (cd_mat NUMBER, vl_sal NUMBER); 3 CURSOR salario (mat NUMBER) RETURN RegFunc; 4 DtNasc DATE; 4 PROCEDURE admissão (nome CHAR, grau NUMBER, 5 sal NUMBER, depto CHAR); 6 PROCEDURE demissão (mat NUMBER); 7 END funcionario; 8 / Package created.

SQL> CREATE OR REPLACE PACKAGE BODY funcionario AS 2 CURSOR salario (mat NUMBER) RETURN RegFunc IS 3 SELECT cd_mat, vl_sal FROM func 4 WHERE cd_mat = mat 5 ORDER BY vl_sal DESC; 6 PROCEDURE admissão (nome CHAR, grau NUMBER, 7 sal NUMBER, depto CHAR) IS 8 BEGIN 9 INSERT INTO func (nm_func, nr_git, vl_sal, cd_mat, cd_depto) 10 VALUES (nome, grau, sal, cd_mat_seq.NEXTVAL, depto); 11 END admissão; 12 PROCEDURE demissão (mat NUMBER) IS 13 BEGIN 14 DELETE FROM func WHERE cd_mat = mat; 15 END demissão; 16 BEGIN 17 DtNasc := TO_DATE('17/01/1998', 'DD/MM/YYYY'); 18 END funcionario;

Package body created.

TRIGGERS E PACKAGES - 98

Page 106: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

REFERÊNCIA A PACKAGES Para fazer referência aos tipos, objetos e subprogramas declarados dentro da especificação de packages devemos usar a seguinte notação:

<nome do package>. <tipo> <nome do package>. <objeto> <nome do package>. <subprograma>

Podemos fazer referência a pacotes de dentro de DATABASE TRIGGERS, STORED SUBPROGRAMS e blocos PL/SQL dentro de programas e blocos PL/SQL anônimos. A inicialização da parte executável do PACKAGE é feita uma única vez, na primeira vez que for feita referência ao PACKAGE (por sessão).

RESTRIÇÃO

Um PACKAGE não pode ser chamado, receber parâmetro nem ser aninhado (declarado dentro de outro PACKAGE).

EXEMPLO

SS Eon P

QL> VARIABLE DtTeste VARCHAR2(30) QL> DECLARE

2 wr funcionario.salario%ROWTYPE; 3 BEGIN 4 OPEN funcionario.salario(&mat); 5 FETCH funcionario.salario into wr; 6 funcionario.admissão ('Teste', 19, wr.vl_sal * 1.2, 'A00'); 7 funcionario.demissão (wr.cd_mat); 8 :DtTeste := TO_CHAR(funcionario.DtNasc, 'DD/MM/YYYY'); 9 CLOSE funcionario.salario; 10 END; 11 / nter value for mat: 120 ld 4: OPEN funcionario.salario(&mat); ew 4: OPEN funcionario.salario(120);

L/SQL procedure successfully completed.

TRIGGERS E PACKAGES - 99

Page 107: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 8 : ALGUNS PACKAGES DO ORACLE

O PACKAGE DBMS_OUTPUT Este pacote tem a finalidade de permitir o envio de mensagens a partir de procedures, packages ou triggers. Este pacote utiliza um buffer em memória para transferência das mensagens. Estas mensagens poderão ser mostradas com o uso da procedure GET_LINE ou com o uso do comando SET SERVEROUTPUT ON no SQL*PLUS, caso contrário estas mensagens serão ignoradas. OBS.: Este package pode ser especialmente útil para depuração.

ALGUNS PACKAGES DO ORACLE - 100

Page 108: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

Veremos, agora cada uma das procedures e funções contidas no package DBMS_OUTPUT.

ENABLE Esta procedure habilita chamadas para PUT, PUT_LINE, NEW_LINE, GET_LINE e GET_LINES. As chamadas a estas procedures são ignoradas se o package DBMS_OUTPUT não estiver habilitado. Deve-se especificar a quantidade de informação (em bytes) a ser armazenada no buffer. Se o buffer for excedido, receberemos a seguinte mensagem de erro:

-20000, ORU-10027: Buffer overflow, Limit of buffer_limit bytes. Não é necessária a chamada a esta procedure quando utilizamos o SQL*PLUS. São permitidas múltiplas chamadas à ENABLE. Se existirem múltiplas chamadas a esta procedure, é o maior valor dentre os especificados que será utilizado.

SINTAXE

DBMS_OUTPUT.ENABLE (buffer_size in integer); Onde:

◊ buffer_size - pode variar de 2.000 a 1.000.000 de bytes.

ALGUNS PACKAGES DO ORACLE - 101

Page 109: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DISABLE Esta procedure desabilita as chamadas para PUT, PUT_LINE, NEW_LINE, GET_LINE e GET_LINES e limpa o buffer. Esta rotina não é necessária se estivermos usando a opção SET SERVEROUTPUT no SQL*PLUS.

SINTAXE

DBMS_OUTPUT.DISABLE;

PUT Esta procedure especifica a informação que desejamos armazenar no buffer. Devemos usar esta procedure para adicionar pedaços de informação ao buffer. As procedure GET_LINE e GET_LINES não retornam uma linha que não tenham sido terminadas com o caracter newline. Se o tamanho especificado pelo buffer for excedido, será recebida uma mensagem de erro.

SINTAXE

DBMS_OUTPUT.PUT (item VARCHAR2 | NUMBER | DATE);

OBS

Se passarmos como parâmetro um number ou date, quando o item for recuperado será convertido (com TO_CHAR) para string no formato default. Se desejarmos um formato particular, devemos passar o parâmetro já convertido (VARCHAR2).

ALGUNS PACKAGES DO ORACLE - 102

Page 110: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

NEW_LINE Esta procedure coloca uma marca de fim de linha no buffer. Normalmente usamos esta procedure após uma ou mais chamadas à procedure PUT, para indicar fim de mensagem. Cada chamada a NEW_LINE gerará uma linha a ser retornada pelo GET_LINE.

SINTAXE

DBMS_OUTPUT.NEW_LINE;

PUT_LINE Esta procedure especifica a informação que desejamos armazenar no buffer. Esta procedure armazena, automaticamente, um caracter de fim de linha a cada texto enviado. Cada chamada a PUT_LINE gera uma linha a ser recuperada pela procedure GET_LINE.

SINTAXE

DBMS_OUTPUT.PUT_LINE (item VARCHAR2 | NUMBER | DATE);

EXEMPLO

Suponha que desejássemos depurar um trigger. Neste caso devemos incluir uma ou mais linhas de mensagens, da seguinte forma:

DBMS_OUTPUT.PUT_LINE (‘O novo valor é ‘|| :new.col); Devemos usar o SQL*PLUS com a opção SET SERVEROUTPUT marcada para ON, para executar o trigger e depurar as mensagens incluídas.

ALGUNS PACKAGES DO ORACLE - 103

Page 111: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

GET_LINE Esta procedure recupera uma única linha da informação no BUFFER, excluindo o caracter NEWLINE final. O tamanho máximo da linha é de 255 bytes. Todas as linhas não recuperadas serão descartadas quando usadas as procedures PUT, PUT_LINE ou NEW_LINE. Se a procedure concluir com sucesso, o status retornado é zero, caso contrário 1 indicando que não existem linhas no buffer.

SINTAXE

DBMS_OUTPUT.GET_LINE (line OUT VARCHAR2, status OUT INTEGER); Onde:

◊ line - indica a área de texto correspondente à linha. Devemos passar como parâmetro uma variável para receber a linha.

◊ status - Indica o sucesso ou fracasso da operação.

GET_LINES Esta procedure recupera um conjunto de linhas e pode ser usada no lugar da GET_LINE para reduzir o número de chamadas ao servidor. Devemos especificar o número de linhas que desejamos recuperar do buffer. Após recuperar o número de linhas especificado, a procedure retorna o número de linhas realmente recuperado. Se este número for menor que o número de linhas requisitado, significa que não existem mais linhas no buffer. Todas as linhas não recuperadas serão descartadas quando usadas as procedures PUT, PUT_LINE ou NEW_LINE. Cada linha no array pode ter até 255 bytes de comprimento.

SINTAXE

DBMS_OUTPUT.GET_LINES (lines OUT CHARARR, num IN OUT INTEGER);

ALGUNS PACKAGES DO ORACLE - 104

Page 112: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXEMPLO USANDO O SQL*PLUS

O package DBMS_OUTPUT é, normalmente, usado para depuração de STORED PROCEDURES e TRIGGERS.

SQL> CREATE OR REPLACE FUNCTION DeptoSal (p_cd_depto IN CHAR) 2 RETURN NUMBER IS 3 CURSOR func_cursor IS 4 SELECT vl_sal FROM func WHERE cd_depto = p_cd_depto; 5 v_total_sal NUMBER(11,2) := 0; 6 v_conta NUMBER(10) := 1; 7 BEGIN 8 FOR func_rec IN func_cursor LOOP 9 v_total_sal := v_total_sal + func_rec.vl_sal; 10 DBMS_OUTPUT.PUT_LINE ('Loop NO. = ' || TO_CHAR(v_conta) || 11 '; salário = ' || TO_CHAR(v_total_sal)); 12 v_conta := v_conta + 1; 13 END LOOP; 14 DBMS_OUTPUT.PUT_LINE ('Total de salários = ' || 15 TO_CHAR(v_total_sal)); 16 RETURN v_total_sal; 17 END depto_sal; 18 /

SQL> SET SERVEROUTPUT ON

SQL> DECLARE 2 total number; 3 BEGIN 4 total := DeptoSal('A00'); 5 END; 6 / Loop NO. = 1; salário = 5275 Loop NO. = 2; salário = 9925 Loop NO. = 3; salário = Loop NO. = 4; salário = Total de salários = PL/SQL procedure successfully completed.

As mensagens são apresentadas na linha do SQL*PLUS.

ALGUNS PACKAGES DO ORACLE - 105

Page 113: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EXEMPLO USANDO OUTRO PROGRAMA

Este pacote também pode ser usado para passagem de informação entre programas executando no ambiente Server.

SQL> CREATE OR REPLACE PROCEDURE teste IS 2 linhas DBMS_OUTPUT.chararr; 3 total NUMBER; 4 nlin NUMBER := 3; 5 BEGIN 6 total := DeptoSal ('A00'); 7 DBMS_OUTPUT.GET_LINES (linhas, nlin); 8 IF nlin > 0 THEN 9 DBMS_OUTPUT.PUT_LINE(nlin); 10 END IF; 11 END; 12 / Procedure created.

SQL> EXECUTE teste; 3 PL/SQL procedure successfully completed.

ALGUNS PACKAGES DO ORACLE - 106

Page 114: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

O PACKAGE UTL_FILE O package UTL_FILE possui diversas rotinas capazes de efetuar o acesso, leitura e gravação em arquivos convencionais. Obs: Para utilização deste package o DBA deve acrescentar o parâmetro UTL_FILE_DIR ao arquivo de inicialização INIT.ORA. Este pacote não declara apenas procedures e funções, são declaradas exceções e tipos também. Devemos observar que este package se acha armazenado na base de dados, portanto sua execução é realizada pelo Server. Isto significa que a criação e/ou leitura de arquivos se dará no ambiente em que se acha o banco de dados, o ambiente Server.

EXCEPTIONS

A especificação do package UTL_FILE declara sete exceções. Estas exceções serão usadas de acordo com as rotinas específicas.

INVALID_PATH.................. Localização ou nome do arquivo inválido INVALID_MODE................. O parâmetro open_mode na rotina FOPEN está

inválido INVALID_FILEHANDLE...... O handle do arquivo está inválido INVALID_OPERATION....... O arquivo não pode ser aberto ou operado como

requisitado. READ_ERROR................... Um erro de sistema operacional ocorreu durante a

operação de leitura. WRITE_ERROR.................. Um erro de sistema operacional ocorreu durante a

operação de gravação. INTERNAL_ERROR........... Um erro não identificado ocorreu.

FUNÇÕES E PROCEDURES

Para cada função ou procedure apresentada serão vistas as exceções e tipos associados.

ALGUNS PACKAGES DO ORACLE - 107

Page 115: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FOPEN A função FOPEN abre um arquivo para leitura ou gravação. O PATH do diretório já deve existir, uma vez que não é feita criação pelo FOPEN. A função retorna um file handle que deve ser usado em todas as operações de I/O subseqüentes no arquivo.

SINTAXE

FUNCTION FOPEN ( Location IN VARCHAR2, Filename IN VARCHAR2, Open_mode IN VARCHAR2) RETURN UTL_FILE.FILE_TYPE

Onde:

◊ Location - Indica o diretório do arquivo a ser aberto. ◊ Filename - Indica o nome do arquivo incluindo a extensão. Não deve ser

incluído o caminho (path). ◊ Open_mode - Indica o modo como o arquivo será lido. Os valores válidos

são: ‘r’ - leitura, ‘w’ - gravação, ‘a’ - adicionar ao fim do arquivo.

TYPE

Deve ser declarada uma variável do tipo UTL_FILE.FILE_TYPE para receber o file handle.

EXCEPTION

As seguintes exceções podem ser obtidas no momento da abertura do arquivo (FOPEN) :

◊ UTL_FILE.INVALID_PATH, ◊ UTL_FILE.INVALID_MODE, ◊ UTL_FILE.INVALID_OPERATION

EXEMPLO

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 4 BEGIN 5 arq := UTL_FILE.FOPEN (‘/home/teste’, ‘arq.txt', ‘r’); . . . . 15 END; 16 /

ALGUNS PACKAGES DO ORACLE - 108

Page 116: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

IS_OPEN

Testa um file handle para ver se ele identifica um arquivo aberto. OBS: Esta função indica apenas se o arquivo está aberto ou não, ou seja se o file handle é válido ou não. Ela não garante que uma operação de I/O posterior usando o file handle não venha a receber um erro de sistema operacional.

SINTAXE

FUNCTION IS_OPEN (File_handle IN FILE_TYPE) RETURN BOOLEAN; Onde:

◊ File_handle - Indica um file handle retornado por um FOPEN.

EXCEPTION

Não Tem.

EXEMPLO

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 4 BEGIN 5 arq := UTL_FILE.FOPEN (‘/home/teste’, ‘arq.txt', ‘r’); . . . 8 IF UTL_FILE.IS_OPEN(arq) THEN . . . 10 END IF; 15 END; 16 /

ALGUNS PACKAGES DO ORACLE - 109

Page 117: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FCLOSE A procedure FCLOSE fecha um arquivo identificado por um file handle. OBS: Pode-se receber uma exceção do tipo WRITE_ERROR se existirem buffers de dados ainda não gravados quando o comando FCLOSE for executado.

SINTAXE

PROCEDURE FCLOSE (File_handle IN OUT FILE_TYPE); Onde:

◊ File_handle - Indica um file_handle ativo retornado por um FOPEN.

EXCEPTION

As seguintes exceções podem ser adquiridas no momento em que o arquivo é fechado (FCLOSE):

◊ UTL_FILE.WRITE_ERROR ◊ UTL_FILE.INVALID_FILEHANDLE

EXEMPLO

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 4 BEGIN 5 arq := UTL_FILE.FOPEN (‘/home/teste’, ‘arq.txt', ‘r’); . . . 8 IF UTL_FILE.IS_OPEN(arq) THEN . . . 10 END IF; 14 UTL_FILE.FCLOSE (arq); 15 END; 16 /

ALGUNS PACKAGES DO ORACLE - 110

Page 118: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FCLOSE_ALL Esta procedure fecha todos os file handle abertos na sessão. OBS: A procedure FCLOSE_ALL não altera o estado de um file handle adquirido (aberto) pelo usuário. Isto significa que um teste com IS_OPEN poderá retornar TRUE mesmo após o arquivo ter sido fechado, porém nenhuma operação de leitura ou gravação será válida até que um novo FOPEN seja realizado para aquele file handle.

SINTAXE

PROCEDURE FCLOSE_ALL;

EXCEPTION

A operação pode receber a seguinte exceção:

◊ UTL_FILE.WRITE_ERROR.

EXEMPLO

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 4 BEGIN 5 arq := UTL_FILE.FOPEN (‘/home/teste’, ‘arq.txt', ‘r’); . . . 8 IF UTL_FILE.IS_OPEN(arq) THEN . . . 10 END IF; 14 UTL_FILE.FCLOSE_ALL; 15 END; 16 /

ALGUNS PACKAGES DO ORACLE - 111

Page 119: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

GET_LINE Esta procedure lê uma linha de texto de um arquivo aberto identificado pelo file handle e coloca o texto no buffer de saída (parâmetro). Se a linha não couber na área de buffer o programa recebe a exceção VALUE_ERROR. Se o texto não for lido porque encontrou fim de arquivo, o programa receberá NO_DATA_FOUND. OBS: O tamanho máximo do texto para leitura é de 1022 bytes. A leitura de uma linha em branco gerará uma string vazia.

SINTAXE

PROCEDURE GET_LINE (file_handle IN FILE_TYPE, buffer OUT VARCHAR2);

EXCEPTION

A operação de leitura pode receber uma das seguintes exceções:

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.READ_ERROR ◊ NO_DATA_FOUND ◊ VALUE_ERROR

EXEMPLO

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 3 linha VARCHAR2(1000); 4 BEGIN 5 arq := UTL_FILE.FOPEN (‘/home/teste’, ‘arq.txt', ‘r’); 6 UTL_FILE.GET_LINE (arq, linha); . . . . 8 IF UTL_FILE.IS_OPEN(arq) THEN . . . 10 END IF; 14 UTL_FILE.FCLOSE_ALL; 15 END; 16 /

ALGUNS PACKAGES DO ORACLE - 112

Page 120: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PUT Esta procedure armazena o texto existente no buffer no arquivo identificado pelo file handle. OBS: A linha incluída não recebe nenhum caracter de fim de linha. É necessária a execução do comando NEW_LINE para gerar este caracter quando desejado.

SINTAXE

PROCEDURE PUT (File_handle IN FILE_TYPE, Buffer IN VARCHAR2); Onde:

◊ File_handle - Indica um file handle ativo retornado pelo FOPEN. ◊ Buffer - Determina a área de memória que contém o texto a ser gravado

para o arquivo.

EXCEPTION

As seguintes exceções podem ser recebidas:

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.WRITE_ERROR

EXEMPLO

SQL> DECLARE 2 carta UTL_FILE.FILE_TYPE; 3 dt_hoje VARCHAR2(10) := TO_CHAR (SYSDATE, 'dd/mm/yyyy'); 4 CURSOR aniv IS SELECT nm_func, . . . 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); 12 UTL_FILE.PUT (carta, 'Rio, ' || dt_hoje); . . . 23 UTL_FILE.FCLOSE(carta); 24 END LOOP; 25 END; 26 /

ALGUNS PACKAGES DO ORACLE - 113

Page 121: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

NEW_LINE Esta procedure grava um ou mais caracteres de fim de linha para o arquivo identificado por um file handle.

SINTAXE

PROCEDURE NEW_LINE (File handle IN file_type, Lines IN natural :=1) Onde:

◊ File_handle - Indica um file handle ativo retornado pelo FOPEN ◊ Lines - Determina o número de caracteres de fim de linha a serem

gravados no arquivo.

EXCEPTION

As seguintes exceções podem ser recebidas no momento da gravação do arquivo:

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.WRITE_ERROR

EXEMPLO

SQL> DECLARE 2 carta UTL_FILE.FILE_TYPE; 3 dt_hoje VARCHAR2(10) := TO_CHAR (SYSDATE, 'dd/mm/yyyy'); 4 CURSOR aniv IS SELECT nm_func, . . . 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); 12 UTL_FILE.PUT (carta, 'Rio, ' || dt_hoje); 13 UTL_FILE.NEW_LINE (carta, 1); 14 UTL_FILE.PUT (carta, 'Prezado(a) Sr(a). ' || wlinha.nm_func || ','); 15 UTL_FILE.NEW_LINE (carta, 2); . . . 23 UTL_FILE.FCLOSE(carta); 24 END LOOP; 25 END; 26 /

ALGUNS PACKAGES DO ORACLE - 114

Page 122: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PUT_LINE Esta procedure grava o texto presente no buffer para o arquivo. Este comando já adiciona um caracter de fim de linha ao texto.

SINTAXE

PROCEDURE PUT_LINE (File_handle IN FILE_TYPE, Buffer IN VARCHAR2); Onde:

◊ File_handle - Indica um file handle ativo retornado pelo FOPEN. ◊ Buffer - Determina o texto a ser gravado no arquivo.

EXCEPTION

As seguintes exceções podem ser adquiridas no monento da gravação no arquivo:

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.WRITE_ERROR

EXEMPLO

SQL> DECLARE 2 carta UTL_FILE.FILE_TYPE; 3 dt_hoje VARCHAR2(10) := TO_CHAR (SYSDATE, 'dd/mm/yyyy'); 4 CURSOR aniv IS SELECT nm_func, . . . 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); . . . 16 UTL_FILE.PUT_LINE (carta, 'Parabéns por seu aniversário dia ' || 17 wlinha.dt_nasc || '.'); . . . 21 UTL_FILE.PUT_LINE (carta, 'Depto Pessoal.'); . . . 24 END LOOP; 25 END; 26 /

ALGUNS PACKAGES DO ORACLE - 115

Page 123: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PUTF É uma procedure que trabalha de forma semelhante a um “printf” (do C), porém com limitações. A string de formatação pode conter qualquer texto. Os caracteres ‘%s’ e ‘\n’ possuem um significado especial:

◊ %s - marca um ponto para substituição, no texto, pelo próximo argumento da lista.

◊ \n - é substituído (de acordo com a plataforma) pelo caracter de fim de linha.

SINTAXE

PROCEDURE PUTF (File_handle IN FILE_TYPE, Format IN VARCHAR2, [Arg1 IN VARCHAR2, . . . Arg5 IN VARCHAR2]);

Onde:

◊ File_handle - Indica um file handle ativo, retornado por um FOPEN. ◊ Format - Indica uma string que pode conter os caracteres %s e \n. ◊ Arg1. . . Arg5 - de 1 a 5 argumentos para substituição no %s. Se

houveram mais %s que argumentos, o local será ocupado por uma string de comprimento zero.

EXCEPTION

As seguintes exceções podem ser adquiridas a tempo de gravação:

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.WRITE_ERROR

EXEMPLO

SQL> DECLARE . . . 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); . . . 19 UTL_FILE.PUTF (carta, ' de R$ %s no mês atual.', wlinha.vl_sal); . . . 25 END;

ALGUNS PACKAGES DO ORACLE - 116

Page 124: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FFLUSH Esta procedure grava fisicamente todos os dados pendentes para aquele arquivo. O FFLUSH faz com que os dados no buffer sejam “ descarregados” em disco.

SINTAXE

PROCEDURE FFLUSH (File_handle IN FILE_TYPE); Onde:

◊ File_handle - Indica um file handle ativo, retornado por um FOPEN.

EXCEPTION

Pode adquirir as seguintes exceções no momento da gravação.

◊ UTL_FILE.INVALID_FILEHANDLE ◊ UTL_FILE.INVALID_OPERATION ◊ UTL_FILE.WRITE_ERROR

EXEMPLO

SQL> DECLARE 2 carta UTL_FILE.FILE_TYPE; 3 dt_hoje VARCHAR2(10) := TO_CHAR (SYSDATE, 'dd/mm/yyyy'); 4 CURSOR aniv IS SELECT nm_func, . . . 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); 12 UTL_FILE.PUT (carta, 'Rio, ' || dt_hoje); 13 UTL_FILE.NEW_LINE (carta, 1); . . . 21 UTL_FILE.PUT_LINE (carta, 'Depto Pessoal.'); 22 UTL_FILE.FFLUSH(carta); 23 UTL_FILE.FCLOSE(carta); 24 END LOOP; 25 END; 26 /

ALGUNS PACKAGES DO ORACLE - 117

Page 125: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO

Deseja-se carregar na tabela Projetos X Atividades as atividades realizadas no mês. O arquivo com estas informações possui o layout abaixo:

Informação Coluna Código do projeto................ 1 a 6 Código da atividade............ 7 a 9 Data de início...................... 10 a 17 (dd/mm/yy) Data de fim.......................... 18 a 25 (dd/mm/yy)

SQL> DECLARE 2 arq UTL_FILE.FILE_TYPE; 3 buffer VARCHAR2(50); 4 wrow prjatv%ROWTYPE; 5 BEGIN 6 arq := UTL_FILE.FOPEN ('c:\lucia\curso', 'carga.sql', 'r'); 7 LOOP 8 UTL_FILE.GET_LINE(arq, buffer); 9 wrow.cd_proj := SUBSTR(buffer,1,6); 10 wrow.cd_ativ := TO_NUMBER(SUBSTR(buffer,7,3)); 11 wrow.dt_ini := TO_DATE(SUBSTR(buffer,10,8), 'dd/mm/yy'); 12 wrow.dt_fim := TO_DATE(SUBSTR(buffer,18,8), 'dd/mm/yy'); 13 INSERT INTO prjatv (cd_proj, cd_ativ, dt_ini, dt_fim) 14 VALUES (wrow. cd_proj, wrow. cd_ativ, wrow. dt_ini, wrow. dt_fim); 15 END LOOP; 16 EXCEPTION 17 WHEN NO_DATA_FOUND THEN 18 COMMIT; 19 UTL_FILE.FCLOSE(arq); 20 END; 21 /

ALGUNS PACKAGES DO ORACLE - 118

Page 126: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PROBLEMA PROPOSTO

O departamento pessoal de uma empresa deseja enviar a seguinte carta aos seus funcionários que fazem aniversário.

Rio, XX / XX / XXXX Prezado(a) Sr(a). XXXXXX, Parabéns por seu aniversário dia xx/xx. Seu presente será uma bonificação de R$ xxxxxxxx no mês atual. Depto Pessoal.

SQL> DECLARE 2 carta UTL_FILE.FILE_TYPE; 3 dt_hoje VARCHAR2(10) := TO_CHAR (SYSDATE, 'dd/mm/yyyy'); 4 CURSOR aniv IS SELECT nm_func, 5 LTRIM(TO_CHAR(vl_sal/5,'999G999D99')) vl_sal, 6 TO_CHAR(dt_nasc, 'dd/mm') dt_nasc FROM func 7 WHERE TO_CHAR(dt_nasc, 'mm') = TO_CHAR(SYSDATE, 'mm') 8 ORDER BY cd_mat; 9 BEGIN 10 FOR wlinha IN aniv LOOP 11 carta := UTL_FILE.FOPEN ('c:\lucia', wlinha.nm_func || '.txt', 'w'); 12 UTL_FILE.PUT (carta, 'Rio, ' || dt_hoje); 13 UTL_FILE.NEW_LINE (carta, 2); 14 UTL_FILE.PUT (carta, 'Prezado(a) Sr(a). ' || wlinha.nm_func || ','); 15 UTL_FILE.NEW_LINE (carta, 2); 16 UTL_FILE.PUT_LINE (carta, 'Parabéns por seu aniversário dia ' || 17 wlinha.dt_nasc || '.'); 18 UTL_FILE.PUT (carta, 'Seu presente será uma bonificação'); 19 UTL_FILE.PUTF (carta, ' de R$ %s no mês atual.', wlinha.vl_sal); 20 UTL_FILE.NEW_LINE (carta, 2); 21 UTL_FILE.PUT_LINE (carta, 'Depto Pessoal.'); 22 UTL_FILE.FFLUSH(carta); 23 UTL_FILE.FCLOSE(carta); 24 END LOOP; 25 END; 26 /

ALGUNS PACKAGES DO ORACLE - 119

Page 127: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CAPÍTULO 9 : VARIÁVEIS CURSOR

CONCEITO Uma variável do tipo cursor aponta para a linha corrente da “tabela” resultado de uma query que retorne um número indefinido de linhas. Uma variável do tipo cursor difere de um cursor propriamente dito, pelo fato de não estar associada a uma query específica. Desta forma poderemos abrir uma variável cursor para qualquer tipo compatível de query. Além disso, é possível associar novos valores a uma variável cursor e passá-la como parâmetro para subprogramas. As variáveis cursor estão disponíveis para cada PL/SQL cliente, isto é, podemos declarar uma variável cursor num ambiente host (ex: PRO*C) e passá-la como uma “bind variable” para o PL/SQL . Nas aplicações desenvolvidas com as ferramentas FORMS e REPORTS, pode-se usar as variáveis cursor inteiramente no ambiente cliente. OBS: Para executar uma “multi-row query” o ORACLE abre uma área de trabalho anônima para processar a informação. Para fazer acesso à informação podemos usar um cursor explicito, que nomeia a área de trabalho ou podemos usar uma variável cursor que aponte para a área de trabalho anônima. Diferentemente de um cursor que sempre se refere à mesma área de trabalho, uma variável cursor pode fazer referência a diferentes áreas de trabalho. Desta forma não podemos usar um cursor onde uma variável cursor era esperada e vice-versa.

VANTAGENS A principal vantagem é a possibilidade de passar o resultado de uma “query” entre um PL/SQL armazenado na base e as várias aplicações cliente. Nem o PL/SQL nem qualquer das aplicações cliente duplicam ou recebem a query resultante. Eles simplesmente compartilham um ponteiro para a área de trabalho resultante da query. Podemos considerar que houve uma dissociação entre o ponteiro e a área de trabalho. São duas entidades independentes. O ponteiro, como variável, passa a ser compartilhável da mesma forma que qualquer outra variável PL/SQL.

VARIÁVEIS CURSOR - 120

Page 128: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

CRIANDO UMA VARIÁVEL CURSOR A criação de uma variável cursor está subdividida em duas etapas. Na primeira declaramos o tipo e posteriormente variáveis daquele tipo.

SINTAXE

TYPE Tipo IS REF CURSORRETURN Tipo de retorno

Onde:

◊ Tipo - Indica o tipo a ser usado nas declarações subseqüentes. ◊ Tipo de retorno - Deve representar um registro (record) ou uma row em

uma tabela da base de dados.

EXEMPLO

SQL> DECLARE 2 ------------------------------------------ 3 ---- DECLARAÇÃO DE TIPO ---- 4 ------------------------------------------ 5 -- 6 TYPE CursorDepto IS REF CURSOR; -- sem especificação do retorno 7 TYPE CursorFunc IS REF CURSOR RETURN func%rowtype; 8 DeptoReg DEPTO%rowtype; 9 TYPE CursorDepReg IS REF CURSOR RETURN DeptoReg%type; 10 TYPE FuncReg IS RECORD 11 ( 12 cd_mat NUMBER(3), 13 nm_func VARCHAR2(15), 14 vl_sal NUMBER(10,2)); 15 TYPE CursorFuncReg IS REF CURSOR RETURN FuncReg; . . .

VARIÁVEIS CURSOR - 121

Page 129: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

DECLARANDO VARIÁVEIS DO TIPO CURSOR Após a declaração dos tipos podemos declarar as variáveis correspondentes aos tipos criados.

SQL> DECLARE 2 ------------------------------------------ 3 ---- DECLARAÇÃO DE TIPO ---- 4 ------------------------------------------ 5 -- 6 TYPE CursorDepto IS REF CURSOR; -- sem especificação do retorno 7 TYPE CursorFunc IS REF CURSOR RETURN func%rowtype; 8 DeptoReg DEPTO%rowtype; 9 TYPE CursorDepReg IS REF CURSOR RETURN DeptoReg%type; 10 TYPE FuncReg IS RECORD 11 ( 12 cd_mat NUMBER(3), 13 nm_func VARCHAR2(15), 14 vl_sal NUMBER(10,2)); 15 TYPE CursorFuncReg IS REF CURSOR RETURN FuncReg; 16 ------------------------------------------------- 17 --- DECLARAÇÃO DE VARIÁVEIS --- 18 ------------------------------------------------- 19 VCDepto CursorDepto; 20 VCFun CursorFunc; 21 VCDepReg CursorDepReg; 22 VCFuncReg CursorFuncReg; 23 BEGIN . . . 24 END; 25 /

OBSERVAÇÕES

Não podemos declarar variáveis CURSOR em um PACKAGE porque a declaração, na verdade, cria uma ponteiro e não um objeto. Sendo assim não pode ser salva no banco de dados.

VARIÁVEIS CURSOR - 122

Page 130: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

USANDO UMA VARIÁVEL CURSOR

ASSOCIANDO UMA VARIÁVEL CURSOR A UMA QUERY A associação acontece no momento da abertura do cursor (OPEN).

SINTAXE

OPEN VARIÁVEL CURSOR FOR COMANDO

SELECT HOST VARIÁVEL CURSOR

A query associada a uma variável cursor pode fazer referência a uma “BIND VARIABLE” e a variáveis do PL/SQL, parâmetros e funções, mas não pode incluir a cláusula FOR UPDATE.

EXEMPLO

SQL> DECLARE 2 TYPE CursorFunc IS REF CURSOR; 3 VCFunc CursorFunc; 4 Wtotal NUMBER:= 0; 5 Wr Func%ROWTYPE; 6 BEGIN 7 OPEN VCFunc FOR SELECT * FROM func ORDER BY vl_sal; 8 LOOP . . . 12 OPEN VCFunc FOR SELECT SUM(vl_sal) FROM func 13 WHERE cd_mat < Wr.cd_mat; . . . 20 END; 21 /

OBSERVAÇÕES

Quando reabrimos uma variável cursor já aberta, a QUERY anterior é perdida e a nova é executada. O programa não recebe a exceção CURSOR_ALREADY_OPEN, como ocorreria no caso de um cursor.

VARIÁVEIS CURSOR - 123

Page 131: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

OBTENDO DADOS DE UMA VARIÁVEL CURSOR O comando FETCH é o responsável pela recuperação das linhas geradas pela query.

SINTAXE

EXEMPLO

VARIÁVEL CURSORFETCH

SQL> DECLARE 2 TYPE CursorFunc IS REF CURSOR; 3 VCFunc CursorFunc; 4 Wtotal NUMBER:= 0; 5 Wr Func%ROWTYPE; 6 BEGIN 7 OPEN VCFunc FOR SELECT * FROM func ORDER BY vl_sal; 8 LOOP 9 FETCH VCFunc INTO Wr; . . . 14 FETCH VCFunc INTO Wtotal; 15 CLOSE VCFunc; . . . 19 END LOOP; 20 END; 21 /

INTO NOME DE REGISTRO

HOST VARIÁVEL CURSOR VARIÁVEL

OBSERVAÇÕES

Quando declaramos uma variável cursor como parâmetro formal de um subprograma que apenas realiza a operação de fetch, podemos especificar o modo IN ou IN OUT na passagem do parâmetro. Porém, se o subprograma também abre a variável cursor, devemos especificar, obrigatoriamente, o modo IN OUT.

VARIÁVEIS CURSOR - 124

Page 132: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

FECHANDO UMA VARIÁVEL CURSOR O comando CLOSE desvincula a variável cursor da área de query e recursos reservados para a área.

SINTAXE

CLOSE VARIÁVEL CURSOR

HOST VARIÁVEL CURSOR

EXEMPLO

SQL> DECLARE 2 TYPE CursorFunc IS REF CURSOR; 3 VCFunc CursorFunc; 4 Wtotal NUMBER:= 0; 5 Wr Func%ROWTYPE; 6 BEGIN 7 OPEN VCFunc FOR SELECT * FROM func ORDER BY vl_sal; 8 LOOP 9 FETCH VCFunc INTO Wr; 10 IF Wr.vl_sal > 3000 then 11 CLOSE VCFunc; 12 OPEN VCFunc FOR SELECT SUM(vl_sal) FROM func 13 WHERE cd_mat < Wr.cd_mat; 14 FETCH VCFunc INTO Wtotal; 15 CLOSE VCFunc; 16 DBMS_OUTPUT.PUT_LINE (Wtotal); 17 EXIT; 18 END IF; 19 END LOOP; 20 END; 21 /

VARIÁVEIS CURSOR - 125

Page 133: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

PASSANDO VARIÁVEIS CURSOR COMO PARÂMETRO

EM UM PROGRAMA PRINCIPAL Em um programa principal podemos declarar a variável cursor e passá-la para uma subrotina declarada dentro do próprio programa.

EXEMPLO

SQL> DECLARE 2 TYPE CursorFunc IS REF CURSOR RETURN func%ROWTYPE; 3 VCFunc CursorFunc; 4 FUNCTION Display (P_Func IN OUT CursorFunc) 5 RETURN BOOLEAN IS 6 Wr Func%ROWTYPE; 7 BEGIN 8 FETCH P_Func INTO Wr; 9 IF P_Func%FOUND THEN 10 DBMS_OUTPUT.PUT_LINE ('mat = ' || Wr.cd_mat); 11 RETURN TRUE; 12 ELSE 13 RETURN FALSE; 14 END IF; 15 END Display; 16 BEGIN 17 OPEN VCFunc FOR SELECT * FROM func 18 WHERE vl_sal > 3000 ORDER BY vl_sal; 19 WHILE Display (VCFunc) LOOP 20 DBMS_OUTPUT.PUT_LINE('Programa Principal'); 21 END LOOP; 22 END; 23 /

VARIÁVEIS CURSOR - 126

Page 134: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

EM PROGRAMAS ARMAZENADOS NA BASE Neste caso podemos fazer apenas a declaração de tipo, uma vez que a variável não pode ser armazenada na base.

EXEMPLO

SQL> CREATE OR REPLACE PACKAGE FData AS

2 TYPE CursorFunc is REF CURSOR RETURN func%ROWTYPE; 3 PROCEDURE AbreCursor (PFunc IN OUT CursorFunc); 4 PROCEDURE LeCursor (PFunc IN OUT CursorFunc); 5 PROCEDURE FechaCursor (PFunc IN OUT CursorFunc); 6 END FData; 7 / 8 CREATE OR REPLACE PACKAGE BODY Fdata AS 9 PROCEDURE AbreCursor (PFunc IN OUT CursorFunc) IS 10 BEGIN 11 OPEN PFunc FOR SELECT * FROM func 12 WHERE TO_CHAR(dt_nasc, 'mm') = TO_CHAR(SYSDATE, 'mm'); 13 END AbreCursor; 14 PROCEDURE LeCursor (PFunc IN OUT CursorFunc) IS

15 Wfunc func%ROWTYPE; 16 BEGIN 17 LOOP 18 FETCH PFunc into Wfunc; 19 EXIT WHEN PFunc%NOTFOUND; 20 DBMS_OUTPUT.PUT_LINE('Parabéns ' || Wfunc.nm_func); 21 END LOOP; 22 END LeCursor; 23 PROCEDURE FechaCursor (PFunc IN OUT CursorFunc) IS 24 BEGIN 25 Close PFunc; 26 END FechaCursor; 27 END FData; 28 /

VARIÁVEIS CURSOR - 127

Page 135: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

Para usarmos as procedures do pacote devemos criar uma variável do tipo correspondente. SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 VFunc FData.CursorFunc; 3 BEGIN 4 FData.AbreCursor(VFunc); 5 FData.LeCursor(VFunc); 6 FData.FechaCursor(VFunc); 7 END; 8 / Parabéns MIGUEL Parabéns MARIA Parabéns WILIAM PL/SQL procedure successfully completed.

OBSERVAÇÃO

Quando declararmos uma variável cursor com um parâmetro formal de um subprograma que abre a variável cursor, devemos especificar o modo IN OUT para que o subprograma possa passar o cursor aberto de volta para o programa chamador.

VARIÁVEIS CURSOR - 128

Page 136: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

Pode-se também criar uma procedure fora do package que faça referência a um tipo declarado no package.

EXEMPLO

SQL> CREATE OR REPLACE PROCEDURE SalFunc 2 (PFunc IN OUT FData.CursorFunc) AS 3 Wfunc func%ROWTYPE; 3 BEGIN 4 LOOP 5 FETCH PFunc INTO Wfunc; 6 EXIT WHEN PFunc%NOTFOUND; 7 DBMS_OUTPUT.PUT_LINE (Wfunc.nm_func || 8 ' seu abono de aniversário é de R$' || Wfunc.vl_sal/5); 9 END LOOP; 10 END SalFunc; 11 / SQL> SET SERVEROUTPUT ON SQL> DECLARE 2 VFunc FData.CursorFunc; 3 BEGIN 4 FData.AbreCursor(VFunc); 5 SalFunc(VFunc); 6 FData.FechaCursor(VFunc); 7 END; 8 / MIGUEL seu abono de aniversário é de R$825 MARIA seu abono de aniversário é de R$426.8 WILIAM seu abono de aniversário é de R$365.4 PL/SQL procedure successfully completed.

VARIÁVEIS CURSOR - 129

Page 137: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

RESTRIÇÕES PARA VARIÁVEIS CURSOR 1. Não podemos declarar variáveis cursor em um package porque elas não possuem um estado persistente, isto é, não são objetos armazenáveis na base de dados (são ponteiros). Subprogramas remotos em outros servidores não podem receber valores de variáveis cursor. Desta forma não podemos usar RPC’s para passar variáveis cursor de um server para outro. Se passarmos uma host variável cursor para um PL/SQL, não poderemos obter linhas dele (isto é, executar um fetch), neste lado do servidor, a menos que a abertura da variável tenha sido realizada na mesma chamada ao servidor. A query associada com uma variável cursor não pode ser do tipo for update. 2. Não podemos usar operadores de comparação para testar variáveis cursor para igualdade, desigualdade ou nulidade. O exemplo abaixo é ilegal. SQL> DECLARE

2 TYPE CursorTemp IS REF CURSOR RETURN func%rowtype; 3 TYPE CursorFunc IS REF CURSOR RETURN func%rowtype; 4 PROCEDURE AbreFunc (CFunc IN OUT CursorTemp, 3 CTemp IN OUT CursorFunc) IS 4 BEGIN . . . 15 IF CFunc = CTemp THEN . . . 20 IF CFunc IS NULL THEN . . . 30 END AbreFunc; 31 BEGIN . . . 32 END; 33 /

VARIÁVEIS CURSOR - 130

Page 138: Comandos PL SQL

PL/SQL BÁSICO E AVANÇADO 7.3

3. Não podemos criar variáveis cursor como colunas de uma tabela. 4. Não podemos usar o tipo REF CURSOR como elemento de uma tabela PL/SQL. O exemplo abaixo, portanto, é ilegal. S 5. Nexe S 6. N

QL> DECLARE 2 TYPE CursorFunc IS REF CURSOR RETURN func%ROWTYPE; 3 TYPE TabFunc IS TABLE OF CursorFunc 4 INDEX BY BINARY_INTEGER; . . .

ão podemos usar cursores no lugar de variáveis cursor e vice-versa. O mplo abaixo é ilegal.

QL> DECLARE 2 TYPE CursorFunc IN REF CURSOR RETURN func%rowtype; 3 VCFunc CursorFunc; 4 BEGIN . . . 12 FOR Wfunc IN VCFunc LOOP . . . 20 END LOOP; 21 END; 22 /

ão podemos usar variáveis cursor com SQL dinâmico.

VARIÁVEIS CURSOR - 131