420 likes | 512 Views
Linguagens hospedeiras. Aplicações interrogar a BD tomar decisões dialogar com o utilizador etc. linguagem de programação convencional C, Cobol, Ada, Java. linguagem de manipulação de dados optimizada para acesso rápido a grandes BD.
E N D
Linguagens hospedeiras Aplicações • interrogar a BD • tomar decisões • dialogar com o utilizador • etc. • linguagem de programação convencional • C, Cobol, Ada, Java linguagem de manipulação de dados optimizada para acesso rápido a grandes BD O SGBD fornece um conjunto de procedimentos que implementam as principais funções da LMD
Acesso à BD ligação directa (API) ODBC JDBC dados locais BD aplicação chamadasLMD
Comunicação • os programas de aplicação não escrevem directamente na BD • usam operações do nível conceptual - a bem da independência dos dados • se uma chamada da LMD produz uma relação • esta pode ser maior que a área de dados local • as linguagens convencionais são record-oriented • logo • é transferido para a área local um tuplo de cada vez • o seguinte é obtido com uma instrução de fetch • os dados na área local são variáveis normais do programa
PL/SQL - Ambiente Motor PL/SQL Execução da expressão procedimental PL/SQL PL/SQL Block PL/SQL Block SQL Execução da expressão SQL Servidor Oracle
PL/SQL - Benefícios • Pode ser usado para agrupar várias perguntas SQL num só bloco e enviá-lo de uma só vez para o servidor. • PL/SQL pode cooperar com as ferramentas de desenvolvimento de aplicações Oracle tais como Developer Forms e Reports adicionando poder de processamento procedimental a estas ferramentas. • Podemos tirar vantagens das capacidades procedimentais do PL/SQL que não estão presentes no SQL.
PL/SQL - Benefícios • Os programas podem ser transportados para qualquer ambiente (SO ou plataforma) que suporte o servidor Oracle e PL/SQL, ou seja, os programas PL/SQL podem correr em qualquer sítio onde o servidor Oracle corra. • Pode-se escrever programas e criar bibliotecas que podem ser reutilizadas em diferentes ambientes. • Pode-se declarar variáveis dinamicamente baseadas em estruturas de dados ou tabelas e colunas da BD (%TYPE, %ROWTYPE)
Declare o o o Begin o o o Exception o o o End; PL/SQL - Benefícios • Desenvolvimento modular de programas. • Permite executar instruções condicionais. • Permite executar instruções num ciclo. • Permite processar várias linhas devolvidas por uma pergunta através de cursores. • Os erros podem ser processados com rotinas de tratamento de excepções.
Estruturas de controlo • Instruções condicionais: • IF-THEN-END IF • IF-THEN-ELSE-END IF • IF-THEN-ELSIF-END IF • Ciclos • LOOP • FOR • WHILE
Estruturas de controlo LOOP statement1; … EXIT [WHEN condition]; END LOOP; condition - é uma variável booleana ou uma expressão que evolui para (TRUE, FALSE ou NULL) Exercício: bloco que insira 10 linhas numa tabela de linhas de encomenda, para a encomenda 0017
Exemplo de ciclo DECLARE v_num_enc itens.no_enc%TYPE := 134; Contador number(2) := 1; BEGIN LOOP INSERT INTO itens( no_enc, linha ) values(v_num_enc, contador ); Contador:= contador+1; Exit when contador >10; End loop; END;
Estruturas de controlo FOR counter IN [REVERSE] lower_bound . . uper_bound LOOP statement1; statement2; . . . END LOOP; WHILE condition LOOP statement1; statement2; . . . END LOOP;
Frases SQL em PL/SQL • Extrair uma única linha de dados da BD usando SELECT; • Alterar linhas da BD usando comandos DML; • Controlar transacções com COMMIT, ROLLBACK ou SAVEPOINTS; • Determinar a saída gerada por DML com cursores; • PL/SQL não suporta DDL (create/alter/drop table); • PL/SQL não suporta DCL (Grant,…);
Declare o o o Begin o o o Exception o o o End; Estrutura DECLARE - Optativo Variáveis, cursores, excepções definidas pelo utilizador BEGIN - Obrigatório Expressões SQL Expressões PL/SQL EXCEPTION - Optativo Acções a executar quando ocorrem erros END - Obrigatório
Tipos de Blocos Anónimo Procedimento Função PROCEDURE name IS BEGIN --statements [EXCEPTION] END; FUNCTION name RETURN datatype IS BEGIN -- statements RETURN value; [EXCEPTION] END; [DECLARE] BEGIN --statements [EXCEPTION] END; • Um bloco dentro de outro funciona como uma instrução (composta) • Nível de encaixe arbitrário • Funções SQL disponíveis em PL/SQL excepto as de agregação
Procedimentos Sintaxe: CREATE [OR REPLACE] PROCEDURE procedure_name (parameter1 [mode1] datatype1, parameter2 [mode2] datatype2, …) IS | AS PL/SQL Block Exemplo: SQL> CREATE OR REPLACE PROCEDURE raise_salary 2 (v_id in emp.empno%TYPE) 3 IS 4 BEGIN 5 UPDATE emp 6 SET sal = sal * 1.1 7 WHERE empno = v_id; 8 END raise_salary; 9 / Executar: SQL> EXECUTE raise_salary (7369) PL/SQL> raise_salary(7369)
Funções Sintaxe: CREATE [OR REPLACE] FUNCTION function_name (parameter1 [mode1] datatype1, parameter2 [mode2] datatype2, …) RETURN datatype IS | AS PL/SQL Block Exemplo: SQL>CREATE OR REPLACE FUNCTION get_sal 2 (v_id IN emp.empno%TYPE) 3 RETURN NUMBER 4 IS v_salary emp.sal%TYPE :=0; 5 BEGIN 6 SELECT sal INTO v_salary 7 FROM emp WHERE empno = v_id; 8 RETURN (v_salary); 9 END get_sal; 10 /
Gatilhos • Um gatilho é um bloco PL/SQL que executa implicitamente sempre que um evento particular acontece. • Um gatilho pode ser da BD ou da aplicação. • Quando executa? • BEFORE - Antes de executar uma frase DML sobre uma tabela. • AFTER - Depois da frase DML • INSTEAD OF - Executa o corpo do gatilho em vez da frase que activou o gatilho.
Gatilhos • Que frase DML activa gatilhos? • INSERT; UPDATE; DELETE. • Tipo de gatilhos: (quantas vezes deve o gatilho executar ao acontecer o evento?) • Statement - executa uma vez; • Row - executa uma vez para cada linha afectada pelo gatilho. • Corpo do gatilho • Bloco PL/SQL ou chamada a procedimento.
Gatilhos Sintaxe CREATE [OR REPLACE] TRIGGER trigger_name timing event1 [OR event2 OR event3] ON table_name trigger_body Ou (gatilho de linha) CREATE [OR REPLACE] TRIGGER trigger_name timing event1 [OR event2 OR event3] ON table_name [REFERENCING OLD AS old / NEW AS new] FOR EACH ROW [WHEN condition] trigger_body
Gatilhos • Exemplo • SQL> CREATE OR REPLACE TRIGGER derive_commission_pct • 2 BEFORE INSERT OR UPDATE OF sal ON emp • 3 FOR EACH ROW • 4 BEGIN • 5 IF NOT (:NEW.JOB IN (‘MANAGER’,’PRESIDENT’)) • 6 and :NEW.SAL > 5000 • 7 THEN • 8 RAISE_APPLICATION_ERROR • 9 (-20202,’Employee cannot earn this amount’); • 10 END IF; • 11 END; • UPDATE EMP SET SAL=6500 WHERE ENAME=‘MILLER’;
Tipos de variáveis • PL/SQL variáveis: • Escalar (valor único); • Composta (records); • Referência (apontador); • LOB (especificam a localização de objectos grandes. Ex: imagens) • Variáveis não PL/SQL: “bind or host variables” • Usadas para passar valores obtidos durante a execução de PL/SQL para o ambiente SQL*Plus
Variáveis ligadas • Variáveis definidas no PL/SQL não são visíveis pelo SQL*Plus • Bind variables -> Variáveis ligadas são variáveis que são criadas no SQL*Plus e podem ser referidas no PL/SQL. • Como criar • Ex: VARIABLE ret_val NUMBER; • Para referir vars ligadas no PL/SQL usa-se (:) imediatamente antes da variável • Ex: :ret_val :=1; • Para mudar o valor desta variável no SQL*Plus é necessário escrever um bloco PL/SQL. • Ex: SQL> begin • 2 :ret_val:=4; • 3 end; • 4 /
Exemplo em SQL/Plus SQL> VARIABLE g_sal_mensal NUMBER SQL> ACCEPT p_sal_anual PROMPT ‘Salário anual: ‘ SQL> DECLARE SQL> v_sal NUMBER(9,2) := &p_sal_anual; SQL> BEGIN SQL> :g_sal_mensal := v_sal / 12; SQL> END; SQL> / SQL> PRINT g_sal_mensal SQL> /* ou: SET SERVEROUTPUT ON SQL> DBMS_OUTPUT.PUT_LINE(‘Salário mensal de ‘ || TO_CHAR(v_sal)); SQL> */
Declaração e atribuição Sintaxe: identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr]; Exemplos: Declare v_hiredate DATE; v_deptno NUMBER(2) NOT NULL :=10; c_comm CONSTANT NUMBER :=1400; v_ename emp.ename%TYPE; Atribuição: v_hiredate := ‘31-DEC-98’; Variáveis %TYPE herdam o tipo da coluna base e suportam mudanças nessa definição
Tipos escalares • Varchar2(max_comp) • Number[(precisão,casas decimais)] • Date • Char [(max_comp)] • Long • Long Raw • Boolean • true, false, null • Binary_integer • Pls_integer ATENÇÃO: As variáveis não devem ter nomes iguais a nomes das colunas da BD. Ambiguidade: não se sabe se se escreve na BD ou na variável!
Exercício sobre variáveis • Quais as declarações erradas? DECLARE v_id number(4); v_x, v_y, v_z varchar2(10); v_aniversario date not null; v_em_stock boolean := 1;
Alcance das variáveis • Qual o valor de cada variável em ambos os blocos? DECLARE V_sal number(7,2) := 60000; V_com number(7,2) := v_sal*0.2; V_mensagem varchar2(255) := ‘ de qualidade.’; Begin ... Declare V_sal number(7,2) := 50000; V_com number(7,2) := 0; V_total number(7,2) := v_sal+v_com; Begin ... V_mensagem := ‘Operario’ || v_mensagem; End; V_mensagem := ‘Secretario ’ || v_mensagem; END;
PL/SQL - SELECT em PL/SQL SINTAXE: SELECT select_list INTO {variable_name[, variable_name]… | record_name} FROM table WHERE condition; Exemplo:DECLARE v_sum_sal emp.sal%TYPE; v_deptno NUMBER NOT NULL :=10; BEGIN SELECT SUM(sal) --group function INTO v_num_sal FROM emp WHERE dptno=v_deptno; END; • erro se pergunta devolver 0 (NO_DATA_FOUND) ou mais do que 1 linha (TOO_MANY_ROWS) • cláusula INTO crucial
PL/SQL - INSERT/UPDATE em PL/SQL BEGIN INSERT INTO emp(empno, ename, job, deptno) VALUES empno_sequence.nextval,’Harding’,’Clerk’, 10); END; DECLARE v_sal_increase emp.sal%TYPE := 2000; BEGIN UPDATE emp SET sal:= sal + v_sal_increase WHERE job = ‘ANALYST’; END;
Registos • Definir um tipo RECORD para agrupar dados heterogéneos • TYPE nome_tipo IS RECORD (campo[, campo]...); • nome_campo tipo [[NOT NULL] {:= | DEFAULT} expressão] • Pode-se herdar a definição de um registo DECLARE registo_emp emp%ROWTYPE BEGIN SELECT * INTO registo_emp FROM emp WHERE... • Tornando desnecessário conhecer em detalhe a tabela base
Registos encaixados • DECLARE TYPE TimeRec IS RECORD (mins SMALLINT, hrs SMALLINT); TYPE MeetingRec IS RECORD ( day DATE, time_of TimeRec, -- nested record room_no INTEGER(4)); TYPE PartyRec IS RECORD ( day DATE, time_of TimeRec, -- nested record place VARCHAR2(25)); seminar MeetingRec; party PartyRec; BEGIN ... party.time_of := seminar.time_of; END;
Tabelas • Coluna de Binary integer funciona como índice; segunda coluna (de conteúdo) pode ser simples ou composta DECLARE TYPE CourseList IS TABLE OF VARCHAR2(10); courses CourseList; BEGIN courses := CourseList('Biol 4412', 'Psyc 3112', 'Anth 3001'); courses.DELETE(3); -- delete element 3 /* PL/SQL keeps a placeholder for element 3. So, the next statement appends element 4, not element 3. */ courses.EXTEND; -- append one null element /* Now element 4 exists, so the next statement does not raise SUBSCRIPT_BEYOND_COUNT. */ courses(4) := 'Engl 2005';
Tabelas DECLARE TYPE NumList IS TABLE OF NUMBER; depts NumList := NumList(10, 20, 30, 40); BEGIN depts.DELETE(3); -- apaga terceiro elemento FORALL i IN depts.FIRST..depts.LAST – ligação em massa DELETE FROM emp WHERE deptno = depts(i); -- causa erro END; • Métodos para tabelas • Exists First Prior Extend Delete • Count Last Next Trim
PL/SQL - Cursores • Um cursor é uma área privada do SQL. • Há dois tipos de cursores: • Implícitos (chamados SQL) • Explícitos • O servidor Oracle usa cursores implícitos para analisar e executar código SQL. • Os cursores explícitos são explicitamente declarados pelo programador.
Atributos do cursor SQL • Através dos atributos do cursor implícito (chamado SQL) podemos testar a saída produzida por uma pergunta SQL: • SQL%ROWCOUNT - nº de linhas afectadas pela mais recente frase SQL; • SQL%FOUND - TRUE se a mais recente frase SQL afecta uma ou mais linhas; • SQL%NOTFOUND - TRUE se a mais recente frase SQL não afecta nenhuma linha; • SQL%ISOPEN - Sempre FALSE porque o PL/SQL fecha sempre os cursores implícitos depois de os executar;
Controlo de cursores explícitos cria uma área no SQL no Empty? Declare Open Fetch Close yes identifica conjunto activo carrega linha corrente testa fim de dados liberta conjunto activo
Cursores - declaração CURSOR cursor_name [(parameter[, parameter]...)] [RETURN return_type] IS select_statement; • cursor_parameter_name [IN] datatype [{:= | DEFAULT} expression] DECLARE CURSOR c1 IS SELECT empno, ename, job, sal FROM emp WHERE sal > 2000; CURSOR c2 RETURN dept%ROWTYPE IS SELECT * FROM dept WHERE deptno = 10; • sem cláusula INTO
Cursor num Package CREATE PACKAGE BODY emp_stuff AS CURSOR c1 RETURN emp%ROWTYPE IS SELECT * FROM emp WHERE deptno = 20; -- new WHERE clause ... END emp_stuff;
Processamento das linhas DECLARE emp_rec emp%ROWTYPE; -- ou emp_rec emp_stuff.c1%ROWTYPE ... BEGIN ... OPEN emp_stuff.c1; LOOP FETCH emp_stuff.c1 INTO emp_rec; EXIT WHEN emp_suff.c1%NOTFOUND; ... END LOOP; CLOSE emp_stuff.c1; END;
Atributos dos cursores explícitos • Através dos atributos dos cursores explícitos podemos controlar o processamento do resultado: • SQL%ROWCOUNT - nº de linhas devolvidas até ao momento; • SQL%FOUND - TRUE se o fetch mais recente devolveu linha; • SQL%NOTFOUND - TRUE se o fetch mais recente não devolveu linha; • SQL%ISOPEN – TRUE se o cursor estiver aberto • Convém fechar o cursor; máximo de cursores abertos (50) no parâmetro da BD OPEN_CURSORS
Cursor de ciclo FOR DECLARE result temp.col1%TYPE; CURSOR c1 IS SELECT n1, n2, n3 FROM data_table WHERE exper_num = 1; BEGIN FOR c1_rec IN c1 LOOP /* calcula e armazena os resultados */ result := c1_rec.n2 / (c1_rec.n1 + c1_rec.n3); INSERT INTO temp VALUES (result, NULL, NULL); END LOOP; COMMIT; END;
Cursor de sub-pergunta DECLARE bonus REAL; BEGIN FOR emp_rec IN (SELECT empno, sal, comm FROM emp) LOOP bonus := (emp_rec.sal * 0.05) + (emp_rec.comm * 0.25); INSERT INTO bonuses VALUES (emp_rec.empno, bonus); END LOOP; COMMIT; END; • Neste caso não se pode usar os atributos de cursor porque o cursor não tem nome