Εργαστήριο βάσεων δεδομένων MySQL Stored Procedures
Stored Procedures Μια store procedure είναι μια διαδικασία. Είναι ένα πρόγραμμα που αποτελείται από SQL εντολές. Αποθηκεύεται και εκτελείται στον database server χωρίς ενδιάμεση επικοινωνία με το πρόγραμμα εφαρμογής.
Παράδειγμα 1 mysql > create procedure hello_world() >select 'hello world'; mysql> call hello_world(); +-------------+ hello world +-------------+ hello world +-------------+
Γιατί να χρησιμοποιούμε store procedures Εφόσον εκτελούνται στον database server είναι ανεξάρτητες από την πλατφόρμα εφαρμογής. Μειώνεται η καθυστέρηση λόγω της επικοινωνίας μέσω του δικτύου. Εφόσον ο υπολογισμός γίνεται στον database server και τα αποτελέσματα παρέχονται στο πρόγραμμα εφαρμογής απευθείας, δεν είναι απαραίτητη η ενδιάμεση επικοινωνία.
Δημιουργία και χρήση Οι stored procedures δημιουργούνται με την εντολή: create procedure Καλούνται με την εντολή: call Για να δούμε τον ορισμό μιας stored procedure χρησιμοποιούμε την εντολή: show create stored procedure
Παράδειγμα 2 mysql> show create procedure hello_world; +-------------+----------+--------------------------------------------------------+ Procedure sql_mode Create Procedure +-------------+----------+--------------------------------------------------------+ hello_world CREATE DEFINER=`root`@`localhost` PROCEDURE `hello_wrld` () select 'hello world' +-------------+----------+--------------------------------------------------------+
Procedures με πολλές γραμμές Για να συμπεριλάβουμε πολλές εντολές σε μια procedure δημιουργούμε ένα μπλοκ begin-end Πρέπει να καθορίσουμε τον χαρακτήρα με τον οποίο θα τελειώνει η εντολή ορισμού. Πρέπει να είναι δαφορετικός από το (;) εφόσον οι εσωτερκές εντολές θα τελειώνουν με αυτό. Χρησιμοποιούμε την εντολή: delimeter
Παράδειγμα 3 mysql> delimiter $ mysql> create procedure hello_world2() > begin > select 'hello world'; > end$ mysql> call hello_world2()$ +-------------+ hello world +-------------+ hello world +-------------+
Μεταβλητές Οι μεταβλητές συμβολίζονται ως εξής: @όνομα_μεταβλητής Η ανάθεση τιμής σε μια μεταβλητή γίνεται με χρήση της εντολής: set
Παράδειγμα 4 mysql> delimiter $ mysql> create procedure my_multiply() > begin > set @x=2; > select @x; > end > $ mysql> call my_multiply()$ @x 2
Είσοδος - Έξοδος Οι stored procedures μπορούμε να δεχτούν παραμέτρους και να επιστρέψουν τιμές. Υπάρχουν 3 τύποι παραμέτρων: IN: Το default. Η παράμετρος περνά στην procedure και μπορεί να αλλάξει τιμή εσωτερικά αλλά δεν αλλάζει εξωτερικά. OUT: Δεν παρέχεται τιμή στην procedure (θεωρείται null) αλλά αλλάζει εσωτερικά και είναι διαθέσιμη εκτός. INOUT: Συνδυάζει τα χαρακτηριστικά και των 2 τύπων. Μια τιμή μπορεί να δοθεί στην procedure, να μεταβληθεί εσωτερικά και να είναι διαθέσιμη εκτός.
Παράδειγμα 5 mysql> create procedure afairesi(a INT,b INT,OUT result INT) > begin > set result = a-b; > end$ mysql> call afairesi(5,4,@x); mysql> select @x; @x 1
Παράδειγμα 6 mysql> create procedure arnisi(inout num INT) > begin > set num=-num; > end > $ mysql> set @y=17; mysql> call arnisi(@y); mysql> select @y; @y -17
Μεταβλητές των procedures Μέσα στις stored procedures μπορούν να οριστούν μεταβλητές οι οποίες να έχουν εμβέλεια μόνο μέσα στην procedure. Παίρνουν τιμή με την εντολή: set
Παράδειγμα 7 Mysql > create procedure find_author(in book_title VARCHAR(30), OUT author_name VARCHAR(20)) > begin > declare author_key int(11); > select author_id into author_key from book where Title=book_title; > select name into author_name from author where authorid=author_key; > end$ mysql> call find_author('c++',@name_of_author); mysql> select @name_of_author; +-----------------+ @name_of_author +-----------------+ NICK +-----------------+
Δομές ελέγχου ροής Οι stored procedures της mysql υποστηρίζουν εντολές ελέγχου ροής. Οι σημαντικότερες από αυτές είναι: IF-THEN-ELSE CASE WHILE REPEAT UNTIL
IF-THEN-ELSE Σύνταξη: IF condition THEN statements ELSE statement/s ENDIF Παράδειγμα: mysql > create procedure absolute(inout num INT) > BEGIN > IF (num<0) > THEN SET num=-num; > END IF; > END$
IF-THEN-ELSE 2 mysql> create procedure point_of_time(in input_day DATE) > BEGIN > DECLARE current_day DATE; > SET current_day=curdate(); > if (input_day>current_day) > then select 'future'; > elseif(input_day=current_day) > then select 'present'; > else select 'past'; > end if; > END$ mysql> call point_of_time('2007-11-01')$ +--------+ future +--------+ future +--------+ 1 row in set (0.02 sec) Query OK, 0 rows affected (0.02 sec)
CASE Σύνταξη: CASE variable WHEN condition1 statement/s WHEN condition2 statement/s ELSE statement/s END CASE Παράδειγμα: mysql > create procedure nums(in input_num INT) > BEGIN > case (input_num) > when 1 then select 'number one'; > when 2 then select 'number two'; > else select 'unknown number'; > end case; > END$
WHILE REPEAT UNTIL Σύνταξη: WHILE condition DO statement/s END WHILE ή REPEAT statement/s UNTIL condition END REPEAT
WHILE mysql > create procedure counter(in count_lim INT) > BEGIN > DECLARE iter INT; > SET iter=0; > WHILE (iter<count_lim) > DO select iter; > SET iter=iter+1; > END WHILE; > END$ mysql> call counter(2)$ iter 0 iter 1
REPEAT mysql > create procedure counter2(in count_lim INT) > BEGIN > DECLARE iter INT; > SET iter=0; > REPEAT > select iter; > SET iter=iter+1; > UNTIL (iter=count_lim) > END REPEAT; > END$ mysql> call counter2(2)$ iter 0 iter 1
Cursors Οι cursors στη mysql χρησιμοποιούνται για την προσπέλαση ενός συνόλου εγγραφών που χρησιμοποιούνται από ένα ερώτημα. Ο όρος cursor είναι συντομογραφία του Current Set Of Records Δήλωση cursor: DECLARE cursor_name CURSOR FOR select_statement Σε μια stored procedure μπορούμε να ορίσουμε πολλούς cursors. Κάθε cursor θα πρέπει να έχει μοναδικό όνομα. Η δήλωση SELECT δεν μπορεί να περιέχει δήλωση INTO.
Cursors 1 mysql int(11)) > create procedure get_books(in id_of_author > BEGIN > DECLARE book_title varchar(30); > DECLARE book_isbn varchar(13); > DECLARE not_found_message INT; > DECLARE book_cursor CURSOR FOR SELECT Title,ISBN FROM book WHERE author_id=id_of_author; > DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found_message=1; > OPEN book_cursor; > SET not_found_message=0; > REPEAT > FETCH book_cursor INTO book_title,book_isbn; > select book_title,book_isbn; > UNTIL (not_found_message=1) > END REPEAT; > CLOSE book_cursor; > END$ mysql> call get_books(1)$ book_title book_isbn php-mysql 0-472-35696-4 book_title book_isbn Java 2 0-672-31697-8 book_title book_isbn (2ηφορά!!!) Java 2 0-672-31697-8
Cursors 2 mysql > create procedure get_books(in id_of_authorint(11)) > BEGIN > DECLARE book_title varchar(30); > DECLARE book_isbn varchar(13); > DECLARE not_found_message INT; > DECLARE book_cursor CURSOR FOR > SELECT Title,ISBN FROM book WHERE author_id=id_of_author; > DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found_message=1; > OPEN book_cursor; > SET not_found_message=0; > REPEAT > FETCH book_cursor INTO book_title,book_isbn; > IF (not_found_message=0) > THEN select book_title,book_isbn; > END IF; > UNTIL (not_found_message=1) > END REPEAT; > CLOSE book_cursor; > END$ Query OK, 0 rows affected (0.01 sec) mysql> call get_books(1)$ book_title book_isbn php-mysql 0-472-35696-4 1 row in set (0.01 sec) book_title book_isbn 1 φορά!!! Java 2 0-672-31697-8 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec)