03/01/[email protected] databases

100
15/06/22 [email protected] obuda.hu 1 DATABASES http://nik.uni-obuda.hu/ szabozs/

Upload: posy-king

Post on 21-Jan-2016

220 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 1

DATABASEShttp://nik.uni-obuda.hu/

szabozs/

Page 2: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 2

USER AND RIGHTS MANAGEMENT

http://download-uk.oracle.com/docs/cd/B14117_01/server.101/b10759/statements_9013.htm

Page 3: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 3

SYSTEM PRIVILEGES

• CREATE SESSION – REQUIRED TO LOG IN• CREATE TABLE• CREATE VIEW• CREATE PROCEDURE• CREATE USER• ALTER ANY TABLE• ALTER ANY TRIGGER• SELECT ANY TABLE• DROP ANY TABLE• DROP USER• ALL PRIVILEGES

Page 4: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 4

ROLES, USERS

• CREATE USER {name} IDENTIFIED BY {password};

• DROP USER {name};

• Role ~ Group of privileges

• CREATE ROLE {name};

• DROP ROLE {name};

Page 5: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 5

SETTING SYSTEM PRIVILEGES

• GRANT {privileges} TO {role/user};

• "WITH GRANT OPTION"

• GRANT {role} TO {user};

• REVOKE {privileges / role} FROM {user};

Page 6: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 6

OBJECT-PRIVILEGES

• SELECT• INSERT• UPDATE• DELETE• ALTER• EXECUTE (for PL/SQL)• READ (for files)• REFERENCES (for constraints)• INDEX (for CREATE INDEX)

Page 7: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 7

SETTING OBJECT-PRIVILEGES

• GRANT {privileges} ON {object} TO {user} [WITH GRANT OPTION];

• REVOKE {privileges / ALL} ON {object} FROM {user};

Page 8: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 8

PL/SQL

Page 9: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 9

PL/* INTRODUCTION

Page 10: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 10

TRADITIONAL SQL

CLIENT SERVER

QUERY

RESPONSE-HEADER

ROWS

MODIFICATIONS

Page 11: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 11

TRADITIONAL SQL PROCESSING

• Common tasks:– Special tasks that can not be done in SQL or

that are not SQL-specific tasks– Relatively simple processing of big amount of

data– Checks before update/insert/delete

• Even when using localhost, it is better to do these on the server

Page 12: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 12

TRADITIONAL SQL PROCESSING

• Common tasks– More than one type of clients– Some function must be implemented It has

to be done separately for every language– Some common functions are not advised to

be implemented this way

• Even when using localhost, it is better to do these on the server

Page 13: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 13

PL/*

• The server has two engines: the SQL engine and the PL/* engine: Procedural Language Engine

• It is usually a problem-oriented/procedural language, that allows us to do different programming tasks on the server

• Therefore, the server does some of the calculations/methods (usually those methods require a lot of data – high-load applications are not advised!)

Page 14: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 14

PL/*

• Using PL/* programs, we can:– Execute simple, embedded script-code using

different structures– Create and use PROCEDURES for common

functions– Use special error handling: EXCEPTIONS– Create special procedures that are executed

automatically (e.g. to check something before insert/update/delete): TRIGGER

Page 15: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 15

PL/*http://www.stanford.edu/dept/itss/docs/oracle/10g/appdev.101/b10807/01_oview.htm

Page 16: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 16

PL/*

• Oracle uses a language that has an SQL-like syntax: PL/SQL

• PostgreSQL: PL/PGSQL, PL/PERL (2), PL/PYTHON, PL/TCL, PL/JAVA (2), PL/PHP, PL/R, PL/RUBY

• Embedded language vs. PL language

Page 17: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 17

PL/SQL

• Probably the oldest and the most widely used Procedural Language

• A PL/PGSQL in PostgreSQL is similar, little differences GOOGLE

Page 18: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 18

PL/SQL BLOCK• A separated area in the SQL*PLUS script-

program, that is interpreted by the PL/SQL engine

• Syntax:SET SERVEROUTPUT ON[DECLARE {variables}]BEGIN

{commands}[EXCEPTION

{exception handling}]END;/

Page 19: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 19

VARIABLES• Client-side variables:

SET VERIFY ON;ACCEPT sal1 PROMPT 'Lower Bound?';ACCEPT sal2 PROMPT 'Higher Bound?';SELECT * FROM emp WHERE sal>&sal1 AND sal<&sal2; („SUBSTITUTE VARIABLES”)

• Server-side variables: DECLARE {name} {type}; RW in the PL/SQL, Nonexistant outside („LOCAL VARIABLES”)

VARIABLE {name} {type}; Usually RW in the PL/SQL, R outside („BIND VARIABLES”)

Page 20: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 20

set verify off;set serveroutput on;ACCEPT var_I PROMPT 'WRITE

SOMETHING! ';VARIABLE var_II number;

DECLARE var_III number;BEGIN :var_II := &var_I; var_III := :var_II; DBMS_OUTPUT.PUT_LINE('block 1'); DBMS_OUTPUT.PUT_LINE(:var_II); DBMS_OUTPUT.PUT_LINE(var_III); DBMS_OUTPUT.PUT_LINE('ends');END;/PRINT var_II;

DECLARE var_III number;BEGIN var_III := :var_II; DBMS_OUTPUT.PUT_LINE('block 2'); DBMS_OUTPUT.PUT_LINE(:var_II); DBMS_OUTPUT.PUT_LINE(var_III); DBMS_OUTPUT.PUT_LINE('ends');END;/

BIND variables depend on the client as well!

BIND variables are used very often from external programs - parameterized queries

VARIABLES

Page 21: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 21

VARIABLE TYPES

• Basic SQL types

• Reference types– {table}.{column}%TYPE;– {variable}%TYPE;– {table}%ROWTYPE; Record type ~ Pascal

• Record: varname.colname

Page 22: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 22

ROWID

• Automatically generated unique ID for each row in a database

• "Secret column", like the rownum

• select emp.*, rowid, rownum from emp;

• Can be used to match the output rows in different output records

Page 23: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 23

FUNCTIONS

• Traditional functions– UPPER(s), LOWER(s), MOD(x, n)– TO_CHAR(x[, s]), TO_DATE(d, s)

• Random number / text:– http://www.psoug.org/reference/dbms_random.html

– dbms_random.value(),dbms_random.value(2, 5)

Page 24: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 24

PL/SQLSTRUCTURES

Page 25: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 25

SELECTOrder of suffixes (PROCESSING)

1. FROM2. WHERE3. GROUP BY4. HAVING5. UNION/MINUS6. INTERSECT7. ORDER BY8. INTO

THE EXCEPTION!

Page 26: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 26

SELECT Order of suffixes (when using them)

1. INTO2. FROM3. WHERE4. GROUP BY5. HAVING6. UNION/MINUS7. INTERSECT8. ORDER BY

Page 27: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 27

SELECT INTO

• SELECT {field(s)} INTO {variable(s)} {other suffixes}

• The query must return with exactly one row!

• The query must return with exactly as many fields as many variables we list after the INTO

• Or: whole record %ROWTYPE

Page 28: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 28

SELECT INTO

DECLARE var NUMBER;BEGIN SELECT empno INTO var FROM emp;END;/

• ORA-01422: exact fetch returns more than requested number of rows

Page 29: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 29

SELECT INTODECLARE

var NUMBER;

var2 EMP%ROWTYPE;

BEGIN

SELECT empno INTO var FROM emp WHERE ename='KING';

SELECT * INTO var2 FROM emp WHERE ename='KING';

END;

/

Page 30: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 30

IF

IF {condition} THEN{commands}

[ELSIF {condition} THEN{commands}]

[other ELSIF clauses][ELSE

{commands}]END IF;

Page 31: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 31

LOOP

LOOP

{commands}

END LOOP;

To break the loop:

• EXIT;

• EXIT WHEN {condition};

Page 32: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 32

WHILEWHILE {condition}{LOOP}

set serveroutput on;DECLARE

var NUMBER;BEGIN var:=0; WHILE var<=5 LOOP DBMS_OUTPUT.PUT_LINE(var); var:=var+1; END LOOP;END;/

Page 33: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 33

FORFOR {variable} IN {lower} .. {higher}{LOOP}

set serveroutput on;DECLARE

var NUMBER;BEGIN FOR var IN 0 .. 5 LOOP DBMS_OUTPUT.PUT_LINE(var); END LOOP;END;/

Page 34: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 34

FOR . . .

set serveroutput on;set verify on;accept A prompt 'Enter a number:'accept B prompt 'Another number:'DECLARE J NUMBER(5);BEGIN FOR j IN &A..&B LOOP DBMS_OUTPUT.PUT_LINE(j); END LOOP;END;/

Page 35: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 35

SET VERIFY ON(default in sql-developer)

SQL> @x.sql

Enter a number:4

Another number:9

old 3: for j in &A..&B

new 3: for j in 4.9

FOR j IN &A .. &B

Page 36: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 36

EXERCISES

• N!

• NM

• GCD (Greatest Common Divisor)

• LCM (Least Common Multiple)

Page 37: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 37

N!ACCEPT num1 PROMPT 'First number (N)! ';

DECLARE res number;j number;

BEGIN res := 1; FOR j IN 1 .. &num1 LOOP res := res * j; END LOOP; DBMS_OUTPUT.PUT_LINE(res);END;/

Page 38: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 38

NM

ACCEPT num1 PROMPT 'First number (N)! ';ACCEPT num2 PROMPT 'Second number (M)! ';

DECLARE res number;j number;

BEGIN res := 1; FOR j IN 1 .. &num2 LOOP res := res * &num1; END LOOP; DBMS_OUTPUT.PUT_LINE(res);END;/

Page 39: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 39

GCDACCEPT num1 PROMPT 'First number (X)! ';ACCEPT num2 PROMPT 'Second number (Y)! ';

DECLAREX NUMBER;Y NUMBER;

BEGIN X:=&num1; Y:=&num2; WHILE X<>Y LOOP if (X<Y) THEN Y:=Y-X; END IF; if (X>Y) THEN X:=X-Y; END IF; END LOOP; DBMS_OUTPUT.PUT_LINE(X);END;/

Page 40: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 40

LCMACCEPT num1 PROMPT 'First number (X)! ';ACCEPT num2 PROMPT 'Second number (Y)! ';-- LCM = (X*Y) / GCD(X,Y)DECLARE

X NUMBER;Y NUMBER;C NUMBER;

BEGIN X:=&num1; Y:=&num2; C:=X*Y; WHILE X<>Y LOOP if (X<Y) THEN Y:=Y-X; END IF; if (X>Y) THEN X:=X-Y; END IF; END LOOP; DBMS_OUTPUT.PUT_LINE('GCD : '||X); DBMS_OUTPUT.PUT_LINE('LCM : '||C/X);END;/

Page 41: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 41

PL/SQL+ QUERIES

Page 42: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 42

FOR – IMPLICIT CURSORset serveroutput on;DECLARE

someone emp%ROWTYPE;BEGIN FOR someone IN (SELECT * FROM emp) LOOP DBMS_OUTPUT.PUT_LINE('Name = ' ||

someone.ename); DBMS_OUTPUT.PUT_LINE('Salary = ' ||

someone.sal); END LOOP;END;/

Page 43: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 43

DECLARING A CURSOR

DECLAREvar1 NUMBER(5);var2 EMP%ROWTYPE;CURSOR var2 IS

SELECT * FROM EMP;

The query is not executed, we only declare that the given variable will refer to the given query

Page 44: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 44

USING CURSORS [FOR]ACCEPT low_sal PROMPT 'Lower bound! 'ACCEPT upp_sal PROMPT 'Upper bound! 'DECLARE CURSOR curs IS select * from emp; record EMP%ROWTYPE;BEGIN FOR record IN curs LOOP IF record.sal BETWEEN &low_sal AND &upp_sal THEN DBMS_OUTPUT.PUT_LINE(record.ename); END IF; END LOOP;END;

Page 45: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 45

USING CURSORSDECLARE

OPEN

FETCH

CLOSE

EMPTY?

Yes

No

Page 46: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 46

CURSOR ATTRIBUTES

• %FOUND – Successful FETCH?

• %NOTFOUND – Unsuccessful FETCH?

• %ROWCOUNT – Processed number of rows

• %ISOPEN – The cursor opened or not?

Page 47: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 47

USING CURSORSACCEPT low_sal PROMPT 'Lower bound! 'ACCEPT upp_sal PROMPT 'Upper bound! 'DECLARE CURSOR curs IS select * from emp; record EMP%ROWTYPE;BEGIN

OPEN curs;LOOP

FETCH curs INTO record;EXIT WHEN curs%NOTFOUND;IF record.sal BETWEEN &low_sal AND &upp_sal THEN

DBMS_OUTPUT.PUT_LINE(record.ename); END IF;END LOOP;CLOSE curs;

END;

Page 48: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 48

USING CURSORS FOR MODIFICATIONS

CREATE TABLE worker AS …

DECLARE

CURSOR curs IS SELECT * FROM workerFOR UPDATE [OF SAL] [NOWAIT];

record worker%ROWTYPE;

mysal worker.sal%TYPE;

Page 49: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 49

BEGINOPEN cursor;LOOP

FETCH cursor INTO record;EXIT WHEN cursor%NOTFOUND;mysal := record.sal * 1.2;UPDATE worker set sal = mysal

WHERE CURRENT OF cursor; END LOOP;CLOSE cursor;

END;/

USING CURSORS FOR MODIFICATIONS

Page 50: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 50

SEARCHING FOR PAIRS

• Aim: connect pair-records in a table using a calculation

• The searching process is done by a PL/SQL script program

• drop table worker;create table worker as select * from emp;

alter table worker add pair number(4);

update worker set pair=0;

Page 51: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 51

PAIRS• Principle: Using cursorA, we loop through

the records and for each record, we loop again through the records using cursorB

• The calculation is done with the current records of cursorA and cursorB

• Problem: how to identify records that already have pairs?

ROWID CLOSE+OPEN

Page 52: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 52

PAIRS

• Rowid: for every record, we use the ROWID or the primary key field to select the actual record from the table, thus we can check wether the pair field is set or not

• SELECT INTO, easier solution

Page 53: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 53

PAIRS

SET SERVEROUTPUT ON

DECLARECURSOR curs_a IS select * from workers FOR UPDATE;CURSOR curs_b IS select * from workers FOR UPDATE;rec_a curs_a%ROWTYPE;rec_b curs_b%ROWTYPE;DIFF Numeric(5,2);

Page 54: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 54

PAIRS

BEGINOPEN curs_a;LOOP

FETCH curs_a INTO rec_a;EXIT WHEN curs_a%NOTFOUND;IF rec_a.pair=0 THEN

[searching for a pair]END IF;

END LOOP;CLOSE curs_a;

END;/

Page 55: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 55

PAIRSOPEN curs_b;LOOP

FETCH curs_b INTO rec_b;EXIT WHEN curs_b%NOTFOUND;IF (rec_a.sal>rec_b.sal) THEN

Diff:=(rec_a.sal-rec_b.sal)/rec_a.sal; ELSE

Diff:=(rec_b.sal-rec_a.sal)/rec_b.sal; END IF;

IF rec_b.pair=0 AND Diff<0.1 AND rec_a.empno<>rec_b.empno THEN

[setting the pair]END IF;

END LOOP;CLOSE curs_b;

Page 56: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 56

PAIRSDBMS_OUTPUT.PUT_LINE(rec_a.ename ||

' ==> ' || rec_b.ename);UPDATE workers SET pair=rec_a.empno WHERE CURRENT OF curs_b;UPDATE workers SET pair=rec_b.empno WHERE CURRENT OF curs_a;******EXIT;

***** CLOSE curs_a; OPEN curs_a;

Page 57: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 57

PAIRS

• Without Open+Close:

BLAKE ==> JONESJONES ==> FORDMARTIN ==> WARDALLEN ==> TURNERWARD ==> MILLERFORD ==> SCOTT

• With Open+Close:

BLAKE ==> JONESMARTIN ==> WARDALLEN ==> TURNERFORD ==> SCOTT

Page 58: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 58

EXCEPTIONS

Page 59: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 59

EXCEPTION HANDLING

• In other languages: we can mark parts of code for exception handling (try)

• Cause an exception ourselves (throw)

• We can do manual exception handling (catch, except)

• In PL/SQL, exception handling is more automatic: no TRY keyword

• But we can throw/catch!

Page 60: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 60

PL/SQL BLOCK• A separated area in the SQL*PLUS script-

program, that is interpreted by the PL/SQL engine

• Syntax:SET SERVEROUTPUT ON[DECLARE {variables}]BEGIN

{commands}[EXCEPTION

{exception handling}]END;/

Page 61: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 61

USER-DEFINED EXCEPTIONS

ACCEPT var PROMPT "Write something! ";DECLARE MyEx EXCEPTION;BEGIN IF &var=0 THEN RAISE MyEx; END IF; DBMS_output.put_line('Not zero.');EXCEPTION WHEN MyEx THEN DBMS_output.put_line('Zero!');END;/

Page 62: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 62

AUTOMATIC EXCEPTIONS

When using SELECT INTO statement:– NO_DATA_FOUND– TOO_MANY_ROWS– OTHERS

Page 63: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 63

AUTOMATIC EXCEPTIONSACCEPT job PROMPT "Type in a job! ";DECLARE emprec EMP%ROWTYPE;BEGIN SELECT * INTO emprec FROM emp WHERE job='&job'; dbms_output.put_line(emprec.ename);EXCEPTION WHEN No_Data_Found THEN DBMS_output.put_line('No

record!'); WHEN TOO_MANY_ROWS THEN DBMS_output.put_line('Too

much records!'); WHEN OTHERS THEN DBMS_output.put_line('Something

else!');END;/

Page 64: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 64

STORED PROCEDURES

Page 65: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 65

PROCEDURE

• Parameters:– {var.name} [{IN|OUT|IN OUT}] {type}– No size specification for types: VARCHAR2

• SHOW ERROR;(select * from user_errors)

• RAISE_APPLICATION_ERROR(err.code, message); [-20 999 .. -20 000]

Page 66: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 66

PROCEDURE

CREATE OR REPLACE PROCEDURE WriteIt

IS

BEGIN

WriteLn('SzZs');

END;

/

select * from user_errors;

Page 67: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 67

PROCEDURE

CREATE OR REPLACE PROCEDURE WriteLn (text VARCHAR2)

IS text2 VARCHAR2(50);BEGIN text2 := text; dbms_output.put_line(text2);END;/

Page 68: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 68

PROCEDURE

ACCEPT some PROMPT "Write something ";

BEGIN

WriteIt;

WriteLn('&valami');

END;

/

Page 69: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 69

EXECUTION / DELETION

• Execution outside a PL-SQL block:Execute WriteIt;Execute WriteLn('haha');

• Deletion: DROP PROCEDURE xxxxx;

• DROP PROCEDURE WriteLn;Execute WriteIt; Invalid object

Page 70: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 70

FUNCTION

CREATE OR REPLACE FUNCTION {name}[ ({parameters}) ]

RETURN {type}IS

[{local variablees}]BEGIN

{commands}[EXCEPTION …]END;/

Page 71: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 71

FUNCTIONCREATE OR REPLACE FUNCTION CountIt (num1 NUMBER,

num2 NUMBER)RETURN NUMBERIS c NUMBER(6); sum NUMBER(6);BEGIN sum := 0; FOR c IN num1 .. num2 LOOP sum := sum + c; END LOOP; RETURN sum;END;/

Page 72: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 72

FUNCTION

ACCEPT first PROMPT "First num: ";ACCEPT second PROMPT "Second num: ";

BEGIN dbms_output.put_line(CountIt(&first, &second));END;/

DROP FUNCTION CountIt;

Page 73: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 73

TRIGGERS

Page 74: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 74

TRIGGER?

• trigger (n) = a piece (as a lever) connected with a catch or detent as a means of releasing it; esp: the part of the action moved by the finger to fire a gun

• to trigger (v) = to initiate, actuate, or set off by sg

"Event"

Page 75: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 75

TRIGGER?

• In (Oracle) RDBMS: a stored procedure, that runs in connection with some event ("event handler")

• An event can be: DELETE, INSERT, UPDATE, CREATE, ALTER, DROP

• Important: BEFORE, AFTER, INSTEAD OF

Page 76: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 76

TRIGGER

• Typical use: implementing a simple operation that can be integrated with the database Client-independent operations

• E.g. logging, consistency-checking, subquery-dependent checks

Page 77: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 77

TRIGGER

CREATE OR REPLACE TRIGGER {name}[BEFORE | AFTER | INSTEAD OF]{event} [OR {event} …]ON {table}

[FOR EACH ROW [WHEN {condition}]][DECLARE {variables}]BEGIN

{commands}[EXCEPTION …]END;

Page 78: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 78

TRIGGER

• If there is a RAISE_APPLICATION_ERROR() in the trigger's code, then the event that caused the trigger will not be executed (+ automatical ROLLBACK)

• FOR EACH ROW: the trigger is executed once for each row modified/deleted/inserted. Otherwise: once for every command

Page 79: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 79

TRIGGER

• When using a row-level trigger, we have several automatically created variables:

• INSERT - :NEW

• DELETE - :OLD

• UPDATE - :NEW and :OLD

Page 80: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 80

TRIGGER

CREATE OR REPLACE TRIGGER SomeTriggerBEFORE DELETE OR INSERT OR UPDATE ON empFOR EACH ROWBEGIN IF INSERTING THEN DBMS_OUTPUT.PUT_LINE(NEW: ' || :NEW.ename); ELSIF DELETING THEN DBMS_OUTPUT.PUT_LINE(DEL: ' || :OLD.ename); ELSIF UPDATING THEN DBMS_OUTPUT.PUT_LINE(MOD: ' || :OLD.ename || ' ==> '

|| :NEW.ename); END IF;END;/

Page 81: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 81

TRIGGER

delete from emp where ename='KING';update emp set ename='SOME' where

ename='JAMES';insert into emp (empno, ename, mgr, deptno)

values (1, 'NEWMAN', NULL, 20);

DEL: KING1 row deleted.MOD: JAMES ==> SOME1 row updated.NEW: NEWMAN

Page 82: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 82

TRIGGER

CREATE OR REPLACE TRIGGER SomeTrigger2BEFORE INSERT ON empFOR EACH ROWDECLARE

MINSAL NUMERIC(6,2);BEGIN SELECT MIN(SAL) INTO MINSAL FROM EMP; IF (:NEW.sal < MINSAL) THEN RAISE_APPLICATION_ERROR(-20000, 'TOO LOW

SALARY!'); END IF;END;/

Page 83: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 83

TRIGGER

insert into emp (empno, ename, mgr, deptno, sal) values (4, 'NEWMAN2', NULL, 20, 5000);

insert into emp (empno, ename, mgr, deptno, sal) values (5, 'NEWMAN3', NULL, 20, 5);

delete from emp where empno < 100;

Page 84: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 84

TRIGGERUJ: NEWMAN21 row created.insert into emp (empno, ename, mgr, deptno, sal)

values (5, 'NEWMAN3', NULL, 20, 5) *ERROR at line 1:ORA-20000: TOO LOW SALARY!ORA-06512: at "SCOTT.SOMETRIGGER2", line 6ORA-04088: error during execution of trigger

'SCOTT.SOMETRIGGER2'DEL: NEWMANDEL: NEWMAN22 rows deleted.

Page 85: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 85

TABLE-LEVEL TRIGGERCREATE OR REPLACE TRIGGER SomeTrigger2BEFORE DELETE OR INSERT OR UPDATE ON empBEGIN IF INSERTING THEN DBMS_OUTPUT.PUT_LINE('NEW REC'); ELSIF DELETING THEN DBMS_OUTPUT.PUT_LINE('DELETED REC'); ELSIF UPDATING THEN DBMS_OUTPUT.PUT_LINE('MODDED REC'); END IF;END;/

Page 86: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 86

THINGS TO REMEMBER…

• A table-level trigger will be executed once even if affected_rows=0!

• INSTEAD OF: row-level trigger (even without FOR EACH ROW!), used with views

• WHEN: we can define conditions for row-level triggers using the :NEW and the :OLD variables

• DROP TRIGGER xxxx;• ALTER TRIGGER xxxx ENABLE/DISABLE;

Page 87: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 87

10.5

Page 88: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 88

10.5

• Must forbid the insertion of workers who don't apply to some rules

• The condition-checks are done by separated functions!

• The trigger does nothing complicated: it calls the appropriate functions, and raises an exception if the record is considered bad

Page 89: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 89

A TYPICAL TRIGGER

create or replace trigger Checks before insert on xxxxxxxxxxxfor each rowDECLARE

Ex1 Exception;Ex2 Exception;

BEGINif (F1(:NEW.field)<>1) then Raise Ex1; end if;if (F2(:NEW.field1, :NEW.field2)<>1) then Raise Ex2; end if;

EXCEPTIONWHEN Ex1 THEN Raise_Application_Error(-20500, 'Error1');WHEN Ex2 THEN Raise_Application_Error(-20501, 'Error2');WHEN OTHERS THEN Raise_Application_Error(-20999, 'Error');

END;/

Page 90: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 90

Rules

create table dx as select * from emp;

1) The mgr field must point to an already existing boss

2) No boss can have more than two employees

3) The job must be an already existing job

4) The department must be an existing department

Page 91: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 91

FUNCTION 1create or replace function Check_Boss(id int)return intIS

temp int;BEGIN

if id is null then return 0; end if;select distinct mgr into temp from emp where mgr=id;return 1;

EXCEPTIONWHEN NO_DATA_FOUND THEN return 0;WHEN OTHERS THEN return 0;

END;/select * from user_errors;

Page 92: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 92

FUNCTION 1create or replace function Check_Boss(id int)return intIS

temp int;BEGIN

if id is null then return 0; end if;select count(*) into temp from emp where mgr=id;if temp>0 then

return 1;else

return 0;end if;

EXCEPTIONWHEN OTHERS THEN return 0;

END;/select * from user_errors;

Page 93: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 93

THE TRIGGERcreate or replace trigger Checksbefore insert on dxfor each rowDECLARE

NonExistingBoss Exception;BEGIN

if (Check_Boss(:NEW.mgr)<>1) then Raise NonExistingBoss; end if;EXCEPTION

WHEN NonExistingBoss THEN Raise_Application_Error(-20500, ‘The boss does not exist!');WHEN OTHERS THEN Raise_Application_Error(-20999, ‘ERROR');

END;/

insert into dx (empno, sal, mgr, job, deptno) values (10, 500, 5, 'CLERK', 20);

Page 94: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 94

FUNCTION 2create or replace function Check_Workers(id int)return intIS

temp int;BEGIN

select count(*) into temp from emp where mgr=id;if temp<2 then

return 1;else

return 0;end if;

EXCEPTIONWHEN OTHERS THEN return 0;

END;/select * from user_errors;

Page 95: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 95

FUNCTION 3create or replace function Check_Job(job_param varchar2)return intIS

temp int;BEGIN

select count(*) into temp from emp where job=job_param;if temp>0 then

return 1;else

return 0;end if;

EXCEPTIONWHEN OTHERS THEN return 0;

END;/select * from user_errors;

Page 96: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 96

FUNCTION 4create or replace function Check_Dept(dept_param int)return intIS

temp int;BEGIN

select count(*) into temp from dept where deptno=dept_param;if temp>0 then

return 1;else

return 0;end if;

EXCEPTIONWHEN OTHERS THEN return 0;

END;/select * from user_errors;

Page 97: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 97

DECLAREBad_Boss Exception;Bad_Workers Exception;Bad_Job Exception;Bad_Dept Exception;

BEGINif (Check_Boss(:NEW.mgr)<>1) then Raise Bad_Boss; end if;if (Check_Workers(:NEW.mgr)<>1) then Raise Bad_Workers; end if;if (Check_Job(:NEW.job)<>1) then Raise Bad_Job; end if;if (Check_Dept(:NEW.deptno)<>1) then Raise Bad_Dept; end if;

EXCEPTIONWHEN Bad_Boss THEN Raise_Application_Error(-20500, ‘Nonexistant boss');WHEN Bad_Workers THEN Raise_Application_Error(-20501, ‘Too many sub-employees!');WHEN Bad_Job THEN Raise_Application_Error(-20502, ‘Nonexistant job');WHEN Bad_Dept THEN Raise_Application_Error(-20503, ‘Nonexistant department');WHEN OTHERS THEN Raise_Application_Error(-20999, ‘Unknown error');

END;/

Page 98: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 98

TESTING

• Nonexistant boss:– insert into dx (empno, sal, mgr, job, deptno) values

(10, 500, 5, 'CLERK', 20);• Too much sub-employees:

– insert into dx (empno, sal, mgr, job, deptno) values (10, 500, 7698, 'CLERK', 20);

• Nonexistant job:– insert into dx (empno, sal, mgr, job, deptno) values

(10, 500, 7788, 'PÉK', 20);• Nonexistant department:

– insert into dx (empno, sal, mgr, job, deptno) values (10, 500, 7788, 'CLERK', 70);

Page 99: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 99

Rules

5) The salary must be lower than the average salary of the department

6) The salary must be higher than the minimum salary in the given job

Page 100: 03/01/2016szabo.zsolt@nik.uni-obuda.hu1 DATABASES

21/04/23 [email protected] 100

This is the end…

• We add the functions to the trigger code

• We test the functionality of the trigger