Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
kellyton@gmail.com
kellyton@gmail.com
Melhor Desempenho
PL / SQL pode melhorar o desempenho de um aplicativo, dependendo do ambiente de execuo. PL / SQL pode ser usado para agrupar as instrues SQL dentro de um nico bloco e enviar todo o bloco para o servidor em uma nica chamada, reduzindo assim o trfego de rede. Sem PL / SQL: As instrues SQL so processados um de cada vez. Cada declarao SQL resultados em outra chamada para o servidor Oracle e a sobrecarga de alto desempenho. Em um ambiente de rede, a sobrecarga pode se tornar significativo
Kellyton Campos Feitosa
kellyton@gmail.com
Melhor Desempenho
SQL
Aplicao Aplicao
Aplicao Aplicao
kellyton@gmail.com
kellyton@gmail.com
kellyton@gmail.com
kellyton@gmail.com
kellyton@gmail.com
Procedures
PROCEDURE PROCEDURE name name IS IS BEGIN BEGIN --statements --statements [EXCEPTION] [EXCEPTION] END; END;
Funes
FUNCTION FUNCTION name name RETURN RETURN datatype datatype IS IS BEGIN BEGIN --statements --statements RETURN RETURN value; value; [EXCEPTION] [EXCEPTION] END; END;
kellyton@gmail.com
Identificadores
Os identificadores so usados para nomear objetos da PL/SQL como variveis, cursores, subprogramas, etc. Consistem em uma letra, opcionalmente seguida por qualquer seqncia de caracteres incluindo nmeros e ($), (#) e (_). Devem possuir comprimento mximo de 30 caracteres No h distino entre letras maiscula e minscula No pode possuir nome igual uma palavra reservada, ex: BEGIN, END Podem ser identificados com aspas para possurem espaos e distino entre letras maisculas e minsculas. EX: X / Y, variavel A.
Kellyton Campos Feitosa
10
kellyton@gmail.com
Comentrios
Melhoram a legibilidade e tornam os programas mais compreensveis. -- Comentrio de linha /* */ comentrio de bloco Ex.: Comentrios de uma nica linha, atravs de dois traos --":
v_data := SYSDATE; --varivel recebe data atual
11
kellyton@gmail.com
Declarao de varivel
Nome_da_varivel [CONSTANT] datatype [NOT NULL] [{:= | DEFAULT} valor];
DECLARE v_dataInicial DATE; v_contador BINARY_INTEGER NOT NULL := 0; v_nome VARCHAR2(20); c_PI CONSTANT NUMBER DEFAULT 3.14;
12
kellyton@gmail.com
13
kellyton@gmail.com
Tipos Character
Usados para armazenar dados alfanumricos. CHAR(<n>) armazena string de tamanho fixo. Tamanho default 1, mximo 32.767. Subtipo: CHARACTER VARCHAR2(<n>) armazena string de tamanho varivel. possvel armazenar string de at 32.767 bytes. Subtipo: STRING VARCHAR(<n>) sinnimo para o tipo VARCHAR2. NCHAR(<n>) e NVARCHAR2(<n>) possuem as mesmas caractersticas dos tipos CHAR e VARCHAR2 e so usados para armazenar dados NLS (National Language Support). A arquitetura Oracle NLS permite armazenar, processar e recuperar informaes em linguagens nativas. LONG um tipo de dados que se tornou obsoleto com a chegada dos tipos LOB (Large Object). O tipo LONG armazena strings de tamanho varivel de no mximo 2 GB.
Kellyton Campos Feitosa
14
kellyton@gmail.com
Tipos Numeric
Usado para armazenar dados numricos com preciso de at 38 digitos. NUMBER(<x>, <y>) onde <X> corresponde ao nmero de dgitos e <Y> o nmero de casas decimais. Valores inseridos em colunas numricas com nmero de casas decimais menor que o dado inserido sero arredondados. Subtipos: DEC, DECIMAL, DOUBLE PRECISION, FLOAT, INTEGER, INT, NUMERIC, REAL, SMALLINT. BINARY_INTEGER utilizado para armazenar inteiros com sinal, que variam de 2147483647 a 2147483647. Requerem menos memria que tipos NUMBER. Subtipos: NATURAL (n>=0), NATURALN (n>=0 not null), POSITIVE (n>0), POSITIVEN (n>0 not null), SIGNTYPE (-1, 0, 1). PLS_INTEGER Possui as mesmas caractersticas do tipo BINARY_INTEGER, entretanto possui melhor performance para clculos.
Kellyton Campos Feitosa
15
kellyton@gmail.com
Tipos Date
O tipo DATE permite valores de data e hora. O formato padro definido pelo parmetro NLS_DATE_FORMAT. O Oracle armazena internamente a data em formato de nmero juliano com a parte fracionria usada para controlar a hora. Uma data Juliana corresponde ao nmero de dias desde 1 de Janeiro de 4712 A.C. Para operaes aritmticas com datas no Oracle, basta adicionar ou subtrair nmeros inteiros ou fracionrios. Por exemplo, SYSDATE + 1 para somar uma dia, 1/24 para acrescentar uma hora, 1/(24x60) ou 1/1440 para acrescentar 1 minuto e 1/(24x60x60) ou 1/86400 para um segundo.
16
kellyton@gmail.com
Tipos Date
TIMESTAMP semelhante ao tipo DATE, com a diferena de armazenar frao de segundos com preciso de at 9 digitos. TIMESTAMP WITH TIME ZONE armazena data/hora com informaes de fuso horrio. TIMESTAMP WITH LOCAL TIME ZONE armazena data/hora no fuso horrio do servidor. Quando o usurio seleciona os dados, o valor ajustado para as configuraes da sua sesso. INTERVAL YEAR TO MONTH usado para armazenar espao de tempo em anos e meses. INTERVAL DAY TO SECOND permite especificar intervalos em dias, horas, minutos e segundos.
17
kellyton@gmail.com
Tipos LOB
Large Object (LOB) datatypes so usado para armazenar dados no estruturados como imagens, arquivos binrios. Os tipos LOBs podem armazenar at 4GB * (tamanho bloco) de informao. A manipulao dos tipos LOB feita atravs da package DBMS_LOB. BLOB - Binary Large Object, armazena at 4GB*(tamanho bloco) de dados binrios no banco. CLOB - Character Large Object Armazena at 4GB*tamanho_bloco de dados textuais. BFILE - Binary File, armazena at 8 terabytes de dados em arquivos binrios externos. Uma coluna BFILE armazena um ponteiro para o arquivo armazenado no sistema operacional.
Kellyton Campos Feitosa
18
kellyton@gmail.com
Tipo booleano
O nico tipo de dados na famlia booleana o BOOLEAN. Podem conter apenas os valores TRUE, FALSE ou NULL.
19
kellyton@gmail.com
Expresses booleanas
Uma expresso booleana qualquer expresso que avaliada como um valor booleano. Somentes os valores TRUE, FALSE e NULL podem ser atribudos a uma varivel booleana. As variveis so conectados por operadores lgicos AND, OR e NOT.
20
kellyton@gmail.com
Tabela verdade
NOT TRUE FALSE FALSE TRUE NULL NULL
21
kellyton@gmail.com
Tipos Compostos
Os tipos compostos disponveis em PL/SQL so registros, tabelas e varrays. Um tipo composto um que tem componentes dentro dele. Uma varivel do tipo composta contm uma ou mais variveis.
22
kellyton@gmail.com
Tipos de referencia
Um tipo de referncia na PL/SQL semelhante a um ponteiro em C. Em PL/SQL usamos os tipos REF, REF CURSOR e SYS_REFCURSOR.
23
kellyton@gmail.com
Tipos de objeto
Consiste em um tipo composto que possui atributos (variveis de outros tipos) e mtodos (subprogramas) dentro dele.
24
kellyton@gmail.com
Utilizando %TYPE
Utilizado para declarar uma varivel com o mesmo tipo de uma coluna de alguma tabela, ex:
DECLARE v_Nome STUDENTS.FIRST_NAME%TYPE; v_Idade PLS_INTEGER NOT NULL :=0; v_IdadeTemp v_Idade%TYPE; --no herda restrio nem valor default
25
kellyton@gmail.com
26
kellyton@gmail.com
Operadores
O operador mais bsico na PL/SQL o de atribuio. A sintaxe :
Varivel := valor;
27
kellyton@gmail.com
Operadores
Operador **, NOT *,/ +,-,|| =,!=,<,>,<=,>=, IS NULL, LIKE, BETWEEN, IN AND OR Binrio Binrio Binrio
Tipo
Descrio Exponenciao, negao lgica Multiplicao, diviso Adio, subtrao, concatenao Comparao lgica
28
kellyton@gmail.com
29
kellyton@gmail.com
IF-THEN- ELSE
IF v_NumberSeats < 50 THEN v_Comment := 'Fairly small'; ELSIF v_NumberSeats < 100 THEN v_Comment := 'A little bigger'; ELSE v_Comment := 'Lots of room'; END IF; ....
30
kellyton@gmail.com
CASE I
CASE v_Major WHEN 'Computer Science' THEN v_CourseName := 'CS 101'; WHEN 'Economics' THEN v_CourseName :='ECN 203'; WHEN 'History' THEN v_CourseName := 'HIS 101'; WHEN 'Music' THEN v_CourseName := 'MUS 100'; WHEN 'Nutrition' THEN v_CourseName := 'NUT 307'; ELSE v_CourseName := 'Unknown'; END CASE;
* Quando uma condio no for validada por uma condio CASE, a PL/SQL interromper a execuo com o erro CASE_NOT_FOUND, ou ORA-6592:
31
kellyton@gmail.com
CASE II
search_condition1 THEN result1 search_condition2 THEN result2 search_conditionN THEN resultN resultN+1]
* Quando uma condio no for validada por uma condio CASE, a PL/SQL interromper a execuo com o erro CASE_NOT_FOUND, ou ORA-6592:
32
kellyton@gmail.com
Loops while
A condio avaliada antes de cada iterao do loop. Sintaxe:
WHILE condio LOOP Seqncia_de_instrues; END LOOP; ... WHILE v_Counter <= 50 LOOP INSERT INTO temp_table VALUES (v_Counter, 'Loop index'); v_Counter := v_Counter + 1; END LOOP; ...
Se desejado, as instrues EXIT ou EXIT WHEN podem ainda ser utilizadas dentro de um loop WHILE para sair prematuramente do loop.
Kellyton Campos Feitosa
33
kellyton@gmail.com
Exemplo:
BEGIN --no necessrio declarer a varivel v_counter --ela ser automaticamente declarada como BINARY_INTERGER FOR v_Counter IN 1..50 LOOP INSERT INTO temp_table VALUES (v_Counter, 'Loop Index'); END LOOP; END;
Se desejado, as instrues EXIT ou EXIT WHEN podem ainda ser utilizadas dentro de um loop FOR para sair prematuramente do loop.
34
kellyton@gmail.com
35
kellyton@gmail.com
dbms_output.put_line
Package que vem com o Oracle e que permite escrever mensagens. til para fazer debug em ambientes sem recursos de depurao.
Set serveroutput on begin dbms_output.put_line('Ol a todos!'); end;
36
kellyton@gmail.com
Parte II
37
kellyton@gmail.com
Registros PL/SQL
Os registros PL/SQL so semelhantes a estruturas C. Um registro fornece uma maneira de lidar com variveis separadas, mas relacionadas como uma unidade. Sintaxe:
TYPE nome_tipo IS RECORD( campo1 tipo1 [NOT NULL] [:= valor], campo2 tipo2 [NOT NULL] [:= valor], ...);
38
kellyton@gmail.com
Registros PL/SQL
DECLARE TYPE t_Rec1Type IS RECORD ( Field1 NUMBER, Field2 VARCHAR2(5)); TYPE t_Rec2Type IS RECORD ( Field1 NUMBER, Field2 VARCHAR2(5)); v_Rec1 t_Rec1Type; v_Rec2 t_Rec2Type; v_Rec3 t_Rec1Type; v_Rec4 t_Rec1Type; BEGIN /*Apesar de possurem a mesma estrutura, a atribuio abaixo no permitida */ v_Rec1 := v_Rec2; --A forma correta seria: v_Rec1.Field1 := v_Rec2.Field1; v_Rec2.Field2 := v_Rec2.Field2; /*Essa atribuio permitida pois ambas variveis so do mesmo tipo */ v_Rec3 := v_Rec4; END;
39
kellyton@gmail.com
Registros PL/SQL
DECLARE TYPE t_StudentRecord IS RECORD ( FirstName students.first_name%TYPE, LastName students.last_name%TYPE, Major students.major%TYPE); v_Student t_StudentRecord; BEGIN SELECT first_name, last_name, major INTO v_Student FROM students WHERE ID = 10000; END;
40
kellyton@gmail.com
Utilizando %ROWTYPE
Declarar um tipo com base na definio de tabela ou cursor. Exemplo:
DECLARE v_Student students%ROWTYPE; BEGIN SELECT first_name, last_name, major INTO v_Student FROM students WHERE ID = 10000; END;
41
kellyton@gmail.com
As nicas instrues SQL permitidas diretamente em um programa PL/SQL so: DMLs (SELECT, INSERT, UPDATE, DELETE, MERGE) Instrues de controle de transao (COMMIT, ROLLBACK, SAVEPOINT...).
42
kellyton@gmail.com
Declarao Select
Recupera os dados do banco de dados para as variveis PL/SQL.
DECLARE v_StudentRecord students%ROWTYPE; v_Department classes.department%TYPE; v_Course classes.course%TYPE; BEGIN SELECT * INTO v_StudentRecord FROM students WHERE id = 10000; SELECT department, course INTO v_Department, v_Course FROM classes WHERE room_id = 20003; END;
43
kellyton@gmail.com
A clusula RETURNING
Utilizada para obter as informaes sobre a linha ou linhas que acabaram de ser processadas por um comando DML, como por exemplo conhecer a ROWID da linha que acabou de ser includa sem a necessidade de submeter um comando SELECT para o banco de dados. Vantagens: - fewer network round trips (Aplicaes tagarelas) - less server CPU time - fewer cursors - less server memory are required.
Kellyton Campos Feitosa
44
kellyton@gmail.com
A clusula RETURNING
declare name VARCHAR2(15); new_sal NUMBER; emp_id NUMBER := 100; BEGIN UPDATE emp SET sal = sal * 1.1 WHERE empno = emp_id RETURNING ename, sal INTO name, new_sal; -- Now do computations involving name and new_sal END;
45
kellyton@gmail.com
Controle de transaes
Uma transao uma srie de instrues SQL que podem ser aplicadas com sucesso, falhas ou canceladas. Os comandos para controlar transaes so:
Script: Parte ll - Controle Transacional.sql
COMMIT [WORK] para confirmar uma transao ROLLBACK [WORK] [TO [SAVEPOINT] nome_do_savepoint] para cancelar parte ou toda uma transao SAVEPOINT nome_do_savepoint para criar um ponto de salvamento na transao SET TRANSACTION para alterar o modo de consistncia de leitura de uma transao set transaction read only; deve ser a primeira instruo da transao No funciona com o usurio SYS
Para voltar ao normal, finalize a transao com commit ou rollback; Kellyton Campos Feitosa kellyton@gmail.com 46
TRATAMENTO DE ERROS
A PL/SQL implementa tratamento de erro por meio de excees e handlers de exceo. Tipos de erros PL/SQL
Tipos de erro Na compilao Em tempo de execuo Informado pelo Compilador PL/SQL Mecanismo de Execuo Como tratado Interativamente Programaticamente
Interativamente: o compilador informa os erros e voc tem de corrigilos. Programaticamente: as excees so levantadas e capturadas pelos blocos de exceo.
47
kellyton@gmail.com
TRATAMENTO DE ERROS
SET SERVEROUTPUT ON
DECLARE x NUMBER := 1; y NUMBER := 2; z NUMBER := 0; BEGIN y := 1 / z; z := x + y; EXCEPTION WHEN OTHERS THEN /* Handler para executar todos os erros */ --Handle_error(); dbms_output.put_line('Erro diviso zero'); END;
48
kellyton@gmail.com
Declarando Excees
As excees so declaradas na seo declarativa do bloco, levantadas na seo executvel e tratadas na seo de exceo. H dois tipos de excees : definidas pelo usurio predefinidas.
49
kellyton@gmail.com
50
kellyton@gmail.com
Excees predefinidas
Erro do Oracle
ORA-0001 ORA-0051 ORA-0061 ORA-1001 ORA-1012 ORA-1017 ORA-1403 ORA-1410 ORA-1422 ORA-1476 ORA-1722 ...
Exceo Equivalente
DUP_VAL_ON_INDEX TIMEOUT_ON_RESOURCE TRANSACTION_BACKED_OUT INVALID CURSOR NOT_LOGGED_ON LOGIN_DENIED NO_DATA_FOUND SYS_INVALID_ROWID TOO_MANY_ROWS ZERO_DIVIDE INVALID_NUMBER
Descrio
Uma restrio nica violada. (PK/UK) O tempo limite ocorreu ao esperar pelo recurso. A transao foi revertida devido a um impasse. Operao ilegal de cursor. No conectado ao Oracle. Nome usurio/senha invalida. Nenhum dado localizado. Converso para um ROWID universal falhou. Uma instruo SELECT.INTO corresponde a mais de uma linha. Diviso por zero. Converso para um nmero falhou por exemplo. IA no e valido.
51
kellyton@gmail.com
Levantando excees
Quando o erro associado com uma exceo ocorrer, a exceo levantada. Excees definidas pelo usurio so levantadas explicitamente via instruo RAISE. Todas as excees podem ser capturadas com um handler OTHERS e deve ser utilizada como ltima alternativa.
52
kellyton@gmail.com
Levantando excees
DECLARE -- Exception to indicate an error condition e_TooManyStudents EXCEPTION; -- Current number of students registered for HIS-101 v_CurrentStudents NUMBER(3); -- Maximum number of students allowed in HIS-101 v_MaxStudents NUMBER(3); BEGIN /* Find the current number of registered students, and the maximum number of students allowed. */ SELECT current_students, max_students INTO v_CurrentStudents, v_MaxStudents FROM classes WHERE department = 'HIS' AND course = 101; /* Check the number of students in this class. */ IF v_CurrentStudents > v_MaxStudents THEN /* Too many students registered -- raise exception. */ RAISE e_TooManyStudents; END IF; END;
53
kellyton@gmail.com
Tratando excees
EXCEPTION
WHEN
e_TooManyStudents
OR
TOO_MANY_ROWS
THEN
Seqncia_de_instrues1; WHEN nome_exceo THEN Seqncia_de_instrues2; WHEN OTHERS THEN Seqncia_de_instrues3; END;
54
kellyton@gmail.com
SQLCODE e SQLERRM
SQLCODE retorna o cdigo do erro atual SQLERRM retorna o texto da mensagem do erro atual. Inclusive os erros em cascata se existirem. O tamanho mximo da mensagem de erro de 2048 bytes, incluindo o cdigo de erro, as mensagens aninhadas, e inseres de mensagens, tais como nomes de tabela e coluna.
55
kellyton@gmail.com
O pragma EXCEPTION_INIT
Voc pode associar uma exceo nomeada com um erro do Oracle em particular. Isso d a capacidade de interromper especificamente esse erro, sem ser via um handler OTHERS.
PRAGMA EXCEPTION_INI ( nome_da_exceo, numero_erro_do_Oracle);
56
kellyton@gmail.com
O pragma EXCEPTION_INIT
DECLARE e_MissingNull EXCEPTION; PRAGMA EXCEPTION_INIT(e_MissingNull, -1400); BEGIN INSERT INTO students (id) VALUES (NULL); EXCEPTION WHEN e_MissingNull then INSERT INTO log_table (info) VALUES ('ORA-1400 occurred'); END;
57
kellyton@gmail.com
RAISE_APPLICATION_ERROR
Voc pode utilizar a funo predefinida RAISE_APPLICATION_ERROR para criar suas prprias mensagens de erro.
RAISE_APPLICATION_ERROR ( numero_do_erro, mensagem_do_erro, [true | false]);
True -> A mensagem no sobrepe as mensagens anteriores False -> A mensagem sobrepe as mensagens anteriores Onde numero_do_erro um valor entre 20.000 e 20.999, mensagem_do_erro, o texto associado, com no mximo 2048 bytes.
58
kellyton@gmail.com
RAISE_APPLICATION_ERROR
Begin RAISE_APPLICATION_ERROR( -20000, 'O salrio no pode ser maior que o do presidente' ); End;
59
kellyton@gmail.com
DBMS_UTILITY.FORMAT_CALL_STACK
Um problema com as excees que quando ela ocorre, no h nenhuma maneira fcil para informar qual parte do cdigo estava sendo executado nesse momento, utilize a funo DBMS_UTILITY.FORMAT_CALL_STACK para retornar um trace, para se chegar ao ponto onde a exceo foi gerada.
60
kellyton@gmail.com
Parte III
61
kellyton@gmail.com
CURSORES
Cursores so trechos alocados de memria destinados a processar as declaraes SELECT. Podem ser: Cursores Implcitos, definidos pelo prprio PL/SQL Cursores Explcitos definidos manualmente.
62
kellyton@gmail.com
Cursores explcitos
Para sua utilizao so necessrios alguns passos bsicos: declarar o cursor ; declarar as variveis que recebero os dados ; abrir (uma espcie de preparao) o cursor na rea de instrues (open) ; ler os dados produzidos pelo cursor (fetch) ; fechar (desalocar a memria) do cursor (close).
63
kellyton@gmail.com
Cursores Explcitos
Declarando CURSOR <nome do cursor> IS <declarao SELECT> ; Abrindo OPEN <nome-do-cursor>; Lendo FETCH <nome-do-cursor> INTO <lista de variveis> ; Fechando CLOSE <nome-do-cursor> ;
64
kellyton@gmail.com
Cursores Explcitos
DECLARE v_Department classes.department%TYPE; v_Course classes.course%TYPE; CURSOR c_AllClasses IS SELECT * FROM classes; v_ClassesRecord c_AllClasses%ROWTYPE; BEGIN OPEN c_AllClasses; -- This is a legal FETCH statement, returning the first -- row into a PL/SQL record which matches the select list -- of the query. FETCH c_AllClasses INTO v_ClassesRecord; -- This FETCH statement is illegal, since the select list -- of the query returns all 7 columns in the classes table -- but we are only fetching into 2 variables. -- This will raise the error "PLS-394: wrong number of values -- in the INTO list of a FETCH statement". FETCH c_AllClasses INTO v_Department, v_Course; CLOSE c_AllClasses ; END;
65
kellyton@gmail.com
66
kellyton@gmail.com
67
kellyton@gmail.com
CURSOR c_HistoryStudents IS SELECT id, first_name, last_name FROM students WHERE major = 'History'; BEGIN OPEN c_HistoryStudents; LOOP FETCH c_HistoryStudents INTO v_StudentID, v_FirstName, v_LastName; EXIT WHEN c_HistoryStudents%NOTFOUND; INSERT INTO registered_students (student_id, department, course) VALUES (v_StudentID, 'HIS', 301); INSERT INTO temp_table (num_col, char_col) VALUES (v_StudentID, v_FirstName || ' ' || v_LastName); END LOOP; CLOSE c_HistoryStudents; END;
68
kellyton@gmail.com
69
kellyton@gmail.com
70
kellyton@gmail.com
BEGIN FOR v_StudentData IN ( SELECT id, first_name, last_name FROM students WHERE major = 'History') LOOP INSERT INTO registered_students (student_id, department, course) VALUES (v_StudentData.ID, 'HIS', 301); INSERT INTO temp_table (num_col, char_col) VALUES (v_StudentData.ID, v_StudentData.first_name || ' ' || v_StudentData.last_name); END LOOP; END;
71
kellyton@gmail.com
72
kellyton@gmail.com
DECLARE CURSOR c_AllStutends IS SELECT * FROM students FOR UPDATE OF first_name, last_name; --Cursor explcito
* O select for update tambm pode ser utilizado para cursores implcitos * OF colunas, server para indicar quais tabelas deseja bloquear.
Kellyton Campos Feitosa
73
kellyton@gmail.com
74
kellyton@gmail.com
75
kellyton@gmail.com
76
kellyton@gmail.com
Variveis de cursor
77
kellyton@gmail.com
Variveis de cursor
set serveroutput on; DECLARE TYPE TMeuCursor IS REF CURSOR; v_Cursor TMeuCursor; v_EmpRec emp%ROWTYPE; v_DeptRec dept%ROWTYPE; BEGIN --Utilizar tabela EMP OPEN v_Cursor FOR select * from emp; FETCH v_Cursor INTO v_EmpRec; DBMS_OUTPUT.PUT_LINE(v_EmpRec.empno||'-'|| v_EmpRec.ename); CLOSE v_Cursor; --Utilizar tabela DEPT OPEN v_Cursor FOR select * from dept; FETCH v_Cursor INTO v_DeptRec; DBMS_OUTPUT.PUT_LINE(v_DeptRec.deptno||'-'|| v_DeptRec.dname); CLOSE v_Cursor; end;
78
kellyton@gmail.com
Exerccios
79
kellyton@gmail.com
Parte IV
80
kellyton@gmail.com
81
kellyton@gmail.com
Procedures
Quando a procedure criada, ela primeiramente compilada e ento armazenada o banco de dados. Este cdigo compilado pode ser executado de outro blobo PL/SQL. Parmetros podem ser passados quando uma procedure chamada.
82
kellyton@gmail.com
CREATE OR REPLACE PROCEDURE nome_da_procedure [lista_de_parametros] AS /* A seo declarativa entra aqui*/ BEGIN /* A seo executavel entra aqui*/ EXCEPTION /* A seo de exceo entra aqui*/ END [nome_da_procedure];
83
kellyton@gmail.com
84
kellyton@gmail.com
Funes
Uma funo bem semelhante a uma procedure, entretanto uma chamada de procedure uma instruo PL/SQL por si prpria, enquanto uma chamada de funo chamada como parte de uma expresso.
85
kellyton@gmail.com
CREATE [OR REPLACE] FUNCTION nome_de_funo [(argumento [{IN | OUT| IN OUT}] tipo)] , ... argumento [{IN | OUT| IN OUT}] tipo)] RETURN tipo_de_retorno {IS |AS} corpo_da_funo
86
kellyton@gmail.com
CREATE OR REPLACE FUNCTION f_par(p_valor IN NUMBER) RETURN NUMBER AS BEGIN IF MOD(p_valor, 2) = 0 THEN RETURN 1; --O valor do parmetro par. ELSE RETURN 0; --O valor do parmetro impar. END IF; END f_par;
87
kellyton@gmail.com
88
kellyton@gmail.com
89
kellyton@gmail.com
OUT
IN OUT
O parametro real que corresponde a um parametro IN OUT ou OUT deve ser uma variavel e nao pode ser uma expressao ou um constante
90
kellyton@gmail.com
CREATE OR REPLACE FUNCTION f_par(p_valor IN NUMBER) RETURN NUMBER AS BEGIN IF MOD(p_valor, 2) = 0 THEN RETURN 1; ELSE RETURN 0; END IF; END f_par;
91
kellyton@gmail.com
92
kellyton@gmail.com
Embora os parmetros formais no possam ser declarados com restries, eles podem ser restringidos utilizando %TYPE.
create or replace PROCEDURE ParameterLength ( p_Parameter1 IN OUT VARCHAR2, p_Parameter2 IN OUT employees.SALARY%type) AS BEGIN p_Parameter2 := 12345; END ParameterLength;
93
kellyton@gmail.com
Notao posicional A notao posicional aquela onde os parmetros reais so associados com os parmetros formais por posio.
CREATE OR REPLACE PROCEDURE CallMe( p_ParameterA VARCHAR2, p_ParameterB NUMBER, p_ParameterC BOOLEAN, p_ParameterD DATE) AS BEGIN NULL; END CallMe; / DECLARE v_Variable1 VARCHAR2(10); v_Variable2 NUMBER(7,6); v_Variable3 BOOLEAN; v_Variable4 DATE; BEGIN CallMe(v_Variable1, v_Variable2, v_Variable3, v_Variable4); END;
94
kellyton@gmail.com
Notao identificada
A notao posicional aquela onde os parmetros reais so associados com os parmetros formais pelo nome.
DECLARE v_Variable1 VARCHAR2(10); v_Variable2 NUMBER(7,6); v_Variable3 BOOLEAN; v_Variable4 DATE; BEGIN CallMe(p_ParameterA => v_Variable1, p_ParameterC => v_Variable3, p_ParameterD => v_Variable4, p_ParameterB => v_Variable2); END;
95
kellyton@gmail.com
nome_do_parmetro [modo] tipo_de_parmetro { := | DEFAULT } valor_inicial Ex.: CREATE OR REPLACE PROCEDURE AddNewStudent ( p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE, p_Major students.major%TYPE DEFAULT 'Economics') AS BEGIN -- Insert a new row in the students table. Use -- student_sequence to generate the new student ID, and -- 0 for current_credits. INSERT INTO students VALUES (student_sequence.nextval, p_FirstName, p_LastName, p_Major, 0); END AddNewStudent; * Se o parmetro no possuir um valor padro, a definio do seu valor ser obrigatria na chamada ao procedimento/funo. PLS-00306: nmero incorreto de tipos de argumentos na chamada
96
kellyton@gmail.com
A instruo CALL
CALL uma instruo SQL. Ela no vlida dentro de um bloco PL/SQL, mas vlida quando executada utilizando a SQL dinmica. Os parnteses so sempre requeridos, mesmo se o subprograma no receber nenhum argumento (ou tiver valores padro para todos os argumentos). A clusula INTO utilizada apenas para as variveis de sida de funes. Os parmetros IN OUT ou OUT so especificados como pare de lista_de_argumentos. No aceita a notao identificada.
97
kellyton@gmail.com
A instruo CALL
98
kellyton@gmail.com
A instruo CALL
CREATE OR REPLACE PROCEDURE CallProc1(p1 IN VARCHAR2 := NULL) AS BEGIN DBMS_OUTPUT.PUT_LINE('CallProc1 called with ' || p1); END CallProc1; CREATE OR REPLACE PROCEDURE CallProc2(p1 IN OUT VARCHAR2) AS BEGIN DBMS_OUTPUT.PUT_LINE('CallProc2 called with ' || p1); p1 := p1 || ' returned!'; END CallProc2; CREATE OR REPLACE FUNCTION CallFunc(p1 IN VARCHAR2) RETURN VARCHAR2 AS BEGIN DBMS_OUTPUT.PUT_LINE('CallFunc called with ' || p1); RETURN p1; END CallFunc; -- Algumas chamadas validas via SQL*Plus. SQL> CALL CallProc1('Hello!'); SQL> CALL CallProc1(); SQL> VARIABLE v_Output VARCHAR2(50); SQL> CALL CallFunc('Hello!') INTO :v_Output; SQL> PRINT v_Output
99
kellyton@gmail.com
Ambas podem retornar mais de um valor via parmetros OUT Ambas podem ter sees executveis, declarativas e de tratamento de excees. Ambas podem aceitar valores padro. Ambas podem ser chamados utilizando a notao posicional ou identificada.
100
kellyton@gmail.com
Pacotes Permitem agrupar procedimentos e funes em um nico local, onde todos o objetos do pacote so instanciados de uma nica vez.
101
kellyton@gmail.com
Especificao de pacote
Tambm conhecida como cabealho de pacote, contm as informaes sobre o contedo do pacote. CREATE [OR REPLACE] PACKAGE nome_de_pacote {IS | AS} definio_de_tipo | especificao_de_procedimento | especificao_de_funo | declarao_de_varivel | declarao_de_exceo | declarao_de_cursor | declarao_de_prgama | END [nome_do_pacote]
102
kellyton@gmail.com
Corpo de pacote
O corpo contm o cdigo para as declaraes introdutrias do subprograma no cabealho de pacote. CREATE OR REPLACE PACKAGE BODY nome_de_pacote { IS | AS} ... cdigo_de inicializao; cdigo_das_declaraes END [nome_de_pacote];
103
kellyton@gmail.com
UTILIZANDO PROCEDURES e FUNES A viso user_source contm o cdigo fonte-original para o objeto. A viso user_errors contm informaes sobre erros de compilao. Observao: na SQL*Plus, o comando show errors consultar user_errors sobre informaes do ltimo objeto criado.
104
kellyton@gmail.com
No caso de uma procedure/funo ela pode tornar-se invlida caso uma operao DDL seja realizada em um dos seus objetos dependentes - por exemplo, ao acrescentar uma coluna extra na tabela. Se o objeto dependente for invalidado, o mecanismo PL/SQL tentar recompil-lo automaticamente na prxima vez que for chamado. Obs. As visualizaes de dicionrio de dados user_dependencies, all_dependencies e dba_dependencies listam diretamente o relacionamento entre os objetos de esquema.
105
kellyton@gmail.com
Para recompilar manualmente uma procedure, utilize o comando: ALTER PROCEDURE nome_de_procedure COMPILE [DEBUG]; ALTER FUNCTION nome_de_funo COMPILE [DEBUG]; ALTER PACKAGE nome_de_pacote COMPILE [DEBUG]; ALTER PACKAGE nome_de_pacote COMPILE SPECIFICATION; ALTER PACKAGE nome_de_pacote COMPILE BODY; * Se SPECIFICATION e BODY no forem especificados, ambos so compilados.
106
kellyton@gmail.com
Privilgio EXECUTE
Para executar procedimentos/funes de outros usurios necessrio ter o privilgio execute sobre esses objetos. Grant execute on hr.f_par to scott
107
kellyton@gmail.com
CREATE [OR REPLACE] FUNCTION nome_de_funo [lista_de_parmetros] RETURN tipo_de_retorno [AUTHID {CURRENT_USER | DEFINER}] {IS | AS} corpo_de_funo; CREATE [OR REPLACE] PROCEDURE nome_de_procedure [lista_de_parmetros] [AUTHID {CURRENT_USER | DEFINER}] {IS | AS} corpo_de_procedure; CREATE [OR REPLACE] PACKAGE nome_da_especificao_do_pacote [AUTHID {CURRENT_USER | DEFINER}] {IS | AS} especificao_de_procedure;
108
kellyton@gmail.com
Se CURRENT_USER for especificado na clusula AUTHID, o objeto ter os direitos do chamador. Se DEFINER for especificado, ento o objeto ter os direitos do definidor. Default -> direitos do definidor. O exemplo a seguir uma procedure de direitos do chamador:
109
kellyton@gmail.com
CREATE OR REPLACE PROCEDURE RecordFullClasses AUTHID CURRENT_USER AS -- Note that we have to preface classes with -- UserA, since it is owned by UserA only. CURSOR c_Classes IS SELECT department, course FROM UserA.classes; BEGIN FOR v_ClassRecord IN c_Classes LOOP -- Record all classes which don't have very much room left -- in temp_table. IF AlmostFull(v_ClassRecord.department, v_ClassRecord.course) THEN INSERT INTO temp_table (char_col) VALUES (v_ClassRecord.department || ' ' || v_ClassRecord.course || ' is almost full!'); END IF; END LOOP; END RecordFullClasses;
110
kellyton@gmail.com
Exerccios
111
kellyton@gmail.com
Parte V
TRIGGERS DE BANCO DE DADOS
112
kellyton@gmail.com
113
kellyton@gmail.com
TRIGGERS DE BANCO DE DADOS CREATE [OR REPLACE] TRIGGER nome {BEFORE | AFTER | INSTEAD-OF} evento [clusula_de_referncia] [WHEN condio_da_trigger] [FOR EACH ROW] [declare] corpo_de_trigger;
114
kellyton@gmail.com
So acionados em uma operao INSERT, UPDATE ou DELETE de uma tabela de banco de dados. CREATE OR REPLACE TRIGGER update_job_history AFTER UPDATE OF job_id, department_id ON employees FOR EACH ROW BEGIN add_job_history(:old.employee_id, :old.hire_date, sysdate, :old.job_id, :old.department_id); END;
115
kellyton@gmail.com
Dentro do trigger, voc pode acessar os dados da linha que est sendo processada atualmente, atravs do :NEW.nome_coluna e :OLD.nome_coluna Observe que :OLD NULL para triggers em instrues INSERT, e :NEW NULL para instrues DELETE. Os valores :NEW e :OLD no podem ser alterados para gatilhos do tipo AFTER.
116
kellyton@gmail.com
A clusula WHEN
vlida apenas para triggers FOR EACH ROW. A trigger ser executada apenas para aquelas linhas que satisfaam a condio especificada.
CREATE OR REPLACE TRIGGER CheckSalary BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW WHEN (new.salary = 0) BEGIN /* corpo de trigger aqu */ END;
117
kellyton@gmail.com
CREATE OR REPLACE TRIGGER audt_employee BEFORE INSERT OR DELETE OR UPDATE ON employees FOR EACH ROW begin if inserting then --cdigo para insero end if; if deleting then --cdigo para excluso end if; if updating then --cdigo para atualizao end if; end;
118
kellyton@gmail.com
Corpos de triggers
O corpo de um trigger no pode exceder 32K , caso isso ocorra, voc pode reduzi-lo, movendo o cdigo para procedures ou pacotes.
CREATE OR REPLACE TRIGGER secure_employees BEFORE INSERT OR UPDATE OR DELETE ON employees BEGIN secure_dml; END secure_employees;
119
kellyton@gmail.com
Privilgios de trigger
H cinco privilgios de sistema que podem ser atribudos aos usurios do banco de dados, so eles: CREATE TRIGGER cria triggers no prprio schema CREATE ANY TRIGGER cria triggers em qualquer schema ALTER ANY TRIGGER altera triggers em qualquer schema DROP ANY TRIGGER Exclui trigger em qualquer schema ADMINISTER DATABASE TRIGGER. Crie database triggers
120
kellyton@gmail.com
121
kellyton@gmail.com
DROP TRIGGER nome_do_trigger; ALTER TRIGGER nome_do_trigger {DISABLE | ENABLE}; ALTER TABLE nome_tabela DISABLE ALL TRIGGERS;
122
kellyton@gmail.com
123
kellyton@gmail.com
Execute immediate
Script: Parte V - Execute immediate com bind variables.sql
124
kellyton@gmail.com
Table Functions
Criando uma tabela dinmicamente
CREATE TYPE numset_t AS TABLE OF NUMBER; CREATE FUNCTION f1(x number) RETURN numset_t PIPELINED IS BEGIN FOR i IN 1..x LOOP PIPE ROW(i); END LOOP; RETURN; END; select * from table(f1(3));
125
kellyton@gmail.com
Pacote avanado
Alm dos recursos de linguagem que examinamos nas sees anteriores, a PL/SQL tem vrios pacotes predefinidos, sendo que o pacote UTL_FILE um dos mais utilizados. UTL_FILE, permite a um programa PL/SQL ler e graver dados em arquivos do sistema operacional no servidor.
126
kellyton@gmail.com
Utl_file
SQL> CREATE DIRECTORY MEU_DIR AS 'C:\'; Directory created. SQL> DECLARE v_FileHandle UTL_FILE.FILE_TYPE; BEGIN v_FileHandle := UTL_FILE.FOPEN('MEU_DIR', 'utl_file.txt', 'w'); -- Write some lines to the file. UTL_FILE.PUT_LINE(v_FileHandle, 'This is line 1!'); FOR v_Counter IN 2..11 LOOP UTL_FILE.PUTF(v_FileHandle, 'This is line %s!\n', v_Counter); END LOOP; -- And close the file. UTL_FILE.FCLOSE(v_FileHandle); END;
127
kellyton@gmail.com
Criptografando o cdigo
Utilize o aplicativo wrap wrap iname=input_file [oname=output_file]
128
kellyton@gmail.com