Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałAntoni Węgierski Został zmieniony 10 lat temu
1
Bazy Danych Programowanie w SQL Wojciech St. Mościbrodzki wojmos@wojmos.com
2
Prawa dostępu do obiektów w mySQL
Główne zadania DBMS: Identyfikacja i autoryzacja użytkowników Definiowanie poziomów dostępu Zarządzanie prawami dostępu do obiektów Obsługa sytuacji wyjątkowych
3
Prawa dostępu w mySQL Prawa dotyczą obiektów bazodanowych:
Połączeń, baz, tablic, triggerów Użytkowników (w mySQL - w kontekście logowania!) Polecenia związane z zarządzaniem prawami: CREATE USER RENAME USER DROP USER GRANT REVOKE SHOW GRANTS SET PASSWORD
4
GRANT Polecenie GRANT służy do nadawania: PRAW na OBIEKTY
określonym UŻYTKOWNIKOM GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ... ON [object_type] priv_level TO user_specification [, user_specification] ... [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}] [WITH with_option ...] PRAWA (przywileje) to operacje dozwolone, np. CREATE, INSERT, SELECT, EXECUTE, FILE, RELOAD itp. OBIEKTY to tabele, kolumny, funkcje, procedury UŻYTKOWNIK jest określony kontekstem: login+hasło+adres(połączenie)
5
PRAWA (przywileje) W MySQL definiuje się następujące poziomy praw:
global (odnosi się do całości obiektów serwera) – GRANT <prawo> on *.* database (tylko dla danej bazy danych) – GRANT <prawo> on moja.* table (tylko dla jednej tablicy w bazie) – GRANT <prawo> on moja.auto column (tylko dla określonej kolumny) – GRANT <prawo> on moja.auto(id) W zależności od poziomu prawa, są one inaczej pamiętane w systemowej bazie danych: global level – tablica mysql.user database level – tablica mysql.db table level – tablica mysql.tables_priv column level – tablica mysql.columns_priv
6
GRANT – SQL vs mySQL mySQL nadaje prawa w kontekście logowania (nie tylko usera) mySQL implementuje prawa globalne i bazodanowe mySQL rozszerza zakres praw w mySQL usunięcie tabeli nie usuwa praw(!); prawa-zombie mySQL pozwala na nadanie prawa INSERT do określonych kolumn, przy jednoczesnym zabraniu go na inne (użyte zostaną wartości DEFAULT)
7
Prawa dostępu - mySQL Najczęściej używane: Prawa do zarządzania:
ALL, ALTER, DELETE, DROP, INSERT, SELECT, TRIGGER, UPDATE Prawa do zarządzania: CREATE USER, CREATE VIEW, CREATE, INDEX, EXECUTE, RELOAD, SHOW DATABASES, SHOW VIEW, SHUTDOWN, SUPER, Pozostałe: ALTER ROUTINE, CREATE ROUTINE, CREATE TEMPORARY TABLES, EVENT, FILE, LOCK TABLES, PROCESS, REPLICATION CLIENT, REPLICATION SLAVE, GRANT SELECT ON moja.samochod TO wojmos WITH GRANT OPTION Specjalne prawo: GRANT OPTION – możliwość przekazywania uprawnień
8
Implementacja kontekstu użytkownika
Prawa użytkownika przypisuje się parze (user, host) Identyfikacja odbywa się za pomocą pary (user, password) CREATE USER user_specification [IDENTIFIED BY [PASSWORD] 'password'] UWAGA: niestosowanie klauzuli IDENTIFIED BY umożliwia logowania bez hasła IDENTIFIED BY PASSWORD umożliwia ominięcie podawania hasła otwartym tekstem mysql> create user wojmos; mysql> select user, host, password from mysql.user; | user | host | password | | root | localhost | *E35C24480CDB BA0DCF2E4648A7E6C | | wojmos | % | |
9
CREATE USER, DROP USER i SET PASSWORD
CREATE USER – tworzenie użytkowników DROP USER – usuwanie użytkowników (z prawami!) SET PASSWORD – ustawianie haseł RENAME USER – zmiana nazwy GRANT USAGE CREATE USER user_specification [IDENTIFIED BY [PASSWORD] 'password'] DROP USER user [, user] ... RENAME USER old_user TO new_user SET PASSWORD [FOR user] = { 'encrypted password‘ | PASSWORD('some password') | OLD_PASSWORD('some password') } GRANT USAGE ON *.* TO IDENTIFIED BY 'newpass';
10
Hasła podawane w CREATE USER i SET PASSWORD
mysql> create user 'sample1'; mysql> create user 'sample2' identified by 'lipton'; mysql> create user 'sample3' identified by password '*90E462C37378CED12064BB D2BA3A9B689'; mysql> create user 'sample3' identified by password 'lipton'; ERROR 1372 (HY000): Password hash should be a 41-digit hexadecimal number mysql> create user 'sample4'; mysql> set password for sample4 = PASSWORD('lipton'); mysql> create user 'sample5'; mysql> set password for sample5 = OLD_PASSWORD('lipton'); mysql> select user, host, password from mysql.user; | user | host | password | | root | localhost | *E35C24480CDB BA0DCF2E4648A7E6C | | sample2 | % | *D0CD8B382FCD172A273DE23563C530DB2E12D059 | | wojmos | % | | | sample1 | % | | | sample3 | % | *90E462C37378CED12064BB D2BA3A9B689 | | sample4 | % | *D0CD8B382FCD172A273DE23563C530DB2E12D059 | | sample5 | % | 58ac86b863e0cbbf |
11
Przykład działania GRANT OPTION
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON [object_type] priv_level FROM user [, user] ... REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ... GRANT ALL ON *.* TO wojmos with GRANT OPTION root GRANT ALL ON sample.* TO sample1 with GRANT OPTION wojmos GRANT ALL ON sample.* TO sample2 sample1 CREATE TABLE X(id int) sample2 DROP USER SAMPLE1 CREATE TABLE Y(id int) <===========? sample2
12
Kontekst użytkownika mySQL umożliwia dość szerokie i elastyczne zarządzanie prawami: mysql> create user mysql> create user koza identified by 'lipton'; mysql> create user mysql> create user mysqlmysql> select user, host, password from mysql.user where user like 'koza'; | user | host | password | | koza | localhost | | | koza | % | *D0CD8B382FCD172A273DE23563C530DB2E12D059 | | koza | | | | koza | | |
13
Szyfrowanie tablic – bezpieczeństwo w mySQL
Rozważmy typową bazę, z dostępem via Internet / PHP: USER(id int, login char(10), pass char(10), firstname char(20), lastname char(50)) Typowy (powszechne rozwiązanie) plik show.php: * from product where id=7’ Typowy atak: * from user’
14
Tworzenie własnych funkcji i procedur
15
Tworzenie własnych funkcji i procedur
Funkcje są definiowanymi przez użytkownika rozszerzeniami SQL. MySQL pozwala na 3 mechanizmy: Funkcje wkompilowywane w kod serwera Funkcje w postaci kompilowanych bibliotek Funkcje i procedury składowane (stored functions/procedures) (Zwykły użytkownik zasadniczo używa jedynie 3 drogi) Stored function (funkcja składowana) jest wywoływana tak, jak zwykła funkcja SQL. Stored procedure (procedura składowana) jest wywoływana przez call select concat('Ala', ' ma kota'); select count(*) from user; select moja_funkcja(); call moja_procedura();
16
Własne funkcje CREATE PROCEDURE/FUNCTION DROP PROCEDURE/FUNCTION
SHOW PROCEDURE/FUNCTION STATUS SHOW CREATE PROCEDURE/FUNCTION Procedury i funkcje są obiektami konkretnej bazy (od )! Procedury i funkcje są obiektami serwera (do 5.0.0)! mysql> show function status; | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | | poligon | nazwa | FUNCTION | | :36:12 | :36:12 | DEFINER | | | populacja | exp2lvl | FUNCTION | | :35:32 | :35:32 | DEFINER | | 2 rows in set (0.00 sec)
17
Funkcje vs procedury Funkcje i procedury składowane mają podobną budowę i znaczenie Funkcje wymagają określenia RETURNS Funkcje składowane i UDF dzielą ze sobą przestrzeń nazw Parametry funkcji są zawsze IN (nie mogą zmienić wartości) Funkcje są wywoływane jak normalne funkcje SQL CREATE [DEFINER] FUNCTION sp_name ([func_parameter[,...]]) RETURNS type [special ...] routine_body func_parameter: name type special: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string' routine_body: SQL | BEGIN...END
18
Funkcje vs procedury Funkcje i procedury składowane mają podobną budowę i znaczenie Procedury nie określają RETURNS – nie zwracają wartości Procedury przekazują wartości tylko przez zmienne Parametry procedur mogą być IN, OUT lub INOUT Procedury wywoływane są tylko poprzez call CREATE [DEFINER] PROCEDURE sp_name ([proc_parameter[,...]]) [special...] routine_body proc_parameter: [ IN | OUT | INOUT ] name type special: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string' routine_body: SQL | BEGIN...END
19
Porównanie CREATE dla funkcji i procedur
[DEFINER = { user | CURRENT_USER }] PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body FUNCTION sp_name ([func_parameter[,...]]) RETURNS type proc_parameter: [ IN | OUT | INOUT ] param_name type func_parameter: param_name type type: Any valid MySQL data type characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string'
20
DELIMITER i jego znaczenie
Procedury i funkcje składają się zwykle z wielu linii kodu. Oznacza to problem z interpretacją znaku ; po stronie klienta. PRZYPOMINAMY: znak terminalny „;” powoduje natychmiastowe wysłanie poleceń do serwera (w celu interpretacji). Druga jego rola to oddzielanie kolejnych poleceń. CREATE FUNCTION nazwa () RETURNS VARCHAR(20) BEGIN RETURN 'Hello world'; END; w tym miejscu kod zostanie wysłany do serwera CREATE FUNCTION nazwa () RETURNS VARCHAR(20) BEGIN RETURN 'Hello world'; powyższy fragment NIE JEST jednak poprawny!
21
DELIMITER – zmiana znaku terminalnego
WNIOSEK: musimy chwilowo zmienić znaczenie znaku ; (aby przestał wysyłać kod do serwera). DELIMITER ;; nowy symbol terminalny CREATE FUNCTION nazwa () RETURNS VARCHAR(20) BEGIN RETURN ‘Hello world'; END; tworzymy funkcję koniec polecenia ;; wysyłamy do serwera DELIMITER ; stary symbol terminalny (sprzątamy po sobie!)
22
Prosta funkcja składowana
Stworzenie funkcji mysql> DROP FUNCTION IF EXISTS Hello; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> show warnings; | Level | Code | Message | | Note | 1305 | FUNCTION Hello does not exist | DELIMITER ;; CREATE FUNCTION Hello() RETURNS VARCHAR(20) BEGIN RETURN 'Hello world'; END; ;; DELIMITER ;
23
Prosta funkcja składowana
Stworzenie i wywołanie funkcji DROP FUNCTION IF EXISTS Hello; DELIMITER ;; CREATE FUNCTION Hello() RETURNS VARCHAR(20) BEGIN RETURN 'Hello world'; END; ;; DELIMITER ; mysql> select hello(); | hello() | | Hello world | 1 row in set (0.00 sec)
24
Prosta procedura składowana
Stworzenie procedury mysql> DROP PROCEDURE IF EXISTS Hello; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> show warnings; | Level | Code | Message | | Note | 1305 | PROCEDURE Hello does not exist | DELIMITER ;; CREATE PROCEDURE Hello() BEGIN SELECT('Hello world'); END; ;; DELIMITER ;
25
Prosta funkcja składowana
Stworzenie i wywołanie procedury DROP PROCEDURE IF EXISTS Hello; DELIMITER ;; CREATE PROCEDURE Hello() BEGIN SELECT('Hello world'); END; ;; DELIMITER ; mysql> call hello(); | Hello world | 1 row in set (0.00 sec)
26
Parametry przekazywane do obiektów składowanych
Funkcje – parametry zawsze są traktowane jako IN Procedury – parametry mogą mieć typ IN, OUT lub INOUT IN – parametr wejściowy, modyfikacja nie jest widoczna na zewnątrz (inicjalizuje go obiekt wywołujący funkcję) OUT – parametr wyjściowy, pełni rolę wartości zwracanej przez zmienną, ma inicjalnie ustawianą wartość na NULL (inicjalizuje go funkcja) INOUT - parametr wejściowo-wyjściowy, pełni rolę wartości zwracanej przez zmienną, ma inicjalnie ustawianą wartość przez obiekt wywołujący funkcję Dane do przykładu mysql> select * from pracownik; | Jan | Kowalski | polski | | Gdansk | | Jan | Kowalski | niemiecki | | Gdansk | | Piotr | Nowak | polski | | Szczecin | | Stefan | Kozlowski | polski | | Warszawa | | Piotr | Nowak | angielski | | Szczecin | | Jan | Kurski | polski | | Gdansk |
27
Parametry IN Procedura z parametrem typu IN Wywołanie
CREATE PROCEDURE Sample(IN parametr char(30)) BEGIN SELECT * FROM pracownik WHERE i LIKE parametr; END; mysql> call Sample('Jan'); | i | n | j | p | miasto | | Jan | Kowalski | polski | | Gdansk | | Jan | Kowalski | niemiecki | | Gdansk | | Jan | Kurski | polski | | Gdansk | 3 rows in set (0.00 sec)
28
Parametry OUT Procedura z parametrem typu OUT Wywołanie
CREATE PROCEDURE Sample(OUT parametr char(30)) BEGIN SELECT count(*) FROM pracownik into parametr; END; call Query OK, 0 rows affected (0.00 sec) | | | 1 row in set (0.00 sec)
29
Parametry OUT Parametr typu OUT ma inicjalną wartość NULL Wywołanie
CREATE PROCEDURE Sample(OUT parametr char(30)) BEGIN SELECT parametr; SELECT count(*) FROM pracownik into parametr; END; mysql> call | parametr | | NULL | mysql> call sample('Jan'); ERROR 1414 (42000): OUT or INOUT argument 1 for routine wojmos.sample is not a variable or NEW pseudo-variable in BEFORE trigger
30
Parametry OUT Parametr typu OUT ma ZAWSZE inicjalną wartość NULL
Wywołanie CREATE PROCEDURE Sample(OUT parametr char(30)) BEGIN SELECT parametr; SELECT count(*) FROM pracownik into parametr; END; mysql> call | | | | parametr | | NULL |
31
Parametry INOUT Procedura z parametrem typu INOUT
Wywołanie (parametr inicjowany przez obiekt wołający!) CREATE PROCEDURE Sample(INOUT parametr char(30)) BEGIN SELECT parametr; SELECT count(*) FROM pracownik into parametr; END; mysql> call | | | | parametr | | |
32
Parametry INOUT Procedura z parametrem typu INOUT
Wywołanie (parametr inicjowany przez obiekt wołający!) CREATE PROCEDURE Sample(INOUT parametr char(30)) BEGIN SELECT parametr; SELECT count(*) FROM pracownik into parametr; END; mysql> call | parametr | | | | | 6 |
33
Własne funkcje SHOW PROCEDURE/FUNCTION STATUS
mysql> show function status; | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | | poligon | nazwa | FUNCTION | | :36:12 | :36:12 | DEFINER | | | populacja | exp2lvl | FUNCTION | | :35:32 | :35:32 | DEFINER | | 2 rows in set (0.00 sec) mysql> show function status; | Db | Name | Type | Definer | | poligon | nazwa | FUNCTION | | | populacja | exp2lvl | FUNCTION | |
34
Budowa obiektów składowanych - zmienne
Zmienne w programach składowanych zmienne sesyjne zmienne lokalne (dla bloków BEGIN-END) Zmienne lokalne: deklarowane za pomocą DECLARE muszą być deklarowane istnieją tylko w kontekście swoich bloków nie wymagają mogą być ustawiane za pomocą SET mogą być ustawiane za pomocą SELECT i SELECT INTO
35
Zmienne w obiektach składowanych
Zliczamy byty o podanym imieniu w 2 tablicach CREATE PROCEDURE Sample(IN parametr char(30)) BEGIN DECLARE x1 CHAR(30) DEFAULT 0; DECLARE x2 CHAR(30) DEFAULT 0; SELECT count(*) into x1 FROM czlowiek where imie like parametr; SELECT count(*) into x2 FROM pracownik where i like parametr; select x1 as czlowiek, x2 as pracownik; END; mysql> call sample('jan'); | czlowiek | pracownik | | | | 1 row in set (0.00 sec)
36
INSTRUKCJE sterowania (nie mylić z FUNKCJAMI)
Funkcje sterowania są zwykłymi funkcjami SQL IF(), CASE(), IFNULL(), NULLIF() Instrukcje sterowania są przeznaczone tylko dla obiektów składowanych. Oczywiście w obiektach składowanych MOŻNA używać również funkcji sterowania IF, CASE, LOOP, LEAVE, ITERATE, REPEAT, WHILE
37
Instrukcja IF Instrukcja IF IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ... [ELSE statement_list] END IF CREATE PROCEDURE Sample(IN parametr char(30)) BEGIN IF parametr='Jan' THEN SELECT ('Janek!') as wynik; ELSE SELECT ('NIE Janek?') as wynik; END IF; END; mysql> call sample('Jan'); | wynik | | Janek! | mysql> call sample('Janusz'); | wynik | | NIE Janek? |
38
Instrukcja IF IF z wykorzystaniem bloku BEGIN-END
DROP PROCEDURE IF EXISTS Sample; DELIMITER ;; CREATE PROCEDURE Sample(IN parametr char(30)) BEGIN IF parametr='Jan' THEN SELECT ('Janek!') as wynik; SELECT ('Kope lat!') as wynik; END; ELSE SELECT ('NIE Janek?') as wynik; END IF; ;; DELIMITER ;
39
Instrukcja CASE Instrukcja CASE mysql> call sample(1);
| JEDEN | Instrukcja CASE CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE mysql> call sample(2); | DWA | CREATE PROCEDURE Sample(IN parametr int) BEGIN CASE parametr WHEN 1 THEN SELECT('JEDEN'); WHEN 2 THEN SELECT('DWA'); ELSE SELECT ('MNOSTWO!!!'); END; END CASE; mysql> call sample(5); | MNOSTWO!!! |
40
Instrukcje LOOP i LEAVE
LOOP jest pętlą nieskończoną, z której wyjście zapewnia LEAVE nie jest to rozwiązanie "eleganckie" [begin_label:] LOOP statement_list END LOOP [end_label] mysql> call sample(3); | (parametr) | | | 1 row in set (0.00 sec) | | CREATE PROCEDURE Sample(IN parametr int) BEGIN select (parametr); petla: LOOP IF parametr>10 THEN LEAVE petla; END IF; SET parametr = parametr + 1; END LOOP; END;
41
Instrukcje LOOP i LEAVE
REPEAT jest pętlą warunkową, która wykonuje się minimum 1 raz [begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label] mysql> call sample(8); | (parametr) | | | 1 row in set (0.00 sec) | | | | CREATE PROCEDURE Sample(IN parametr int) BEGIN REPEAT select (parametr); SET parametr = parametr + 1; UNTIL parametr>10 END REPEAT; END;
42
Instrukcje LOOP i LEAVE
mysql> call sample(4); | (n) | | 0 | | 1 | | 2 | | 3 | 1 row in set (0.00 sec) WHILE jest typową pętlą warunkową [begin_label:] WHILE search_condition DO statement_list END WHILE [end_label] CREATE PROCEDURE Sample(IN parametr int) BEGIN DECLARE n INT; SET n = 0; WHILE n<parametr DO select (n); SET n = n + 1; END WHILE; END;
43
Wykorzystanie obiektów składowanych
CREATE PROCEDURE MakeCzlowiek() BEGIN DECLARE ile_sylab INT; DECLARE nazwisko char(50) default ''; DECLARE imie1 char(50) default ''; DECLARE temp char(10) default ''; select 2+CAST(2*rand() as signed) into ile_sylab; while (ile_sylab>0) do select dana into temp from sylaba order by rand() limit 1; set nazwisko := concat(nazwisko,temp); set ile_sylab := ile_sylab - 1; end while; set nazwisko := concat(nazwisko,'cki'); set nazwisko := concat(ucase(substring(nazwisko,1,1)),substring(nazwisko,2)); select dana into imie1 from imie order by rand() limit 1; SELECT nazwisko; insert into czlowiek(imie, nazwisko) values (imie1, nazwisko); END; mysql> call MakeCzlowiek(); select * from czlowiek; | Nazanacki |
44
Wykorzystanie obiektów składowanych
DROP PROCEDURE IF EXISTS MakeLudzie; DELIMITER ;; CREATE PROCEDURE MakeLudzie(IN ilu int) BEGIN delete from czlowiek; while (ilu>0) do call MakeCzlowiek(); set ilu := ilu - 1; end while; select count(*) as ilu_mamy_ludzi from czlowiek; END; ;; DELIMITER ; mysql> call MakeLudzie(100); | ilu_mamy_ludzi | | | 1 row in set (0.06 sec)
45
TRIGGER – specyficzna stored procedure
TRIGGER – funkcja składowana wywoływana automatycznie, przez serwer po zaistnieniu pewnego zdarzenia TRIGGER (wyzwalacz) jest więc swego rodzaju event guardianem obiekt standardowy SQL99 update licznik set imie_ile=select count(*) from imie | imie | |Jan | |Tadeusz | |Piotr | |Kacper | mysql> insert into imie values ('Czesio')
46
Klasyfikacja TRIGGERÓW
Triggery (wyzwalacze) możemy podzielić: według kryterium czasu: triggery BEFORE triggery AFTER triggery INSTEAD OF (rzadko implementowane) według kryterium rodzaju operacji (związek z type operacji, a nie poleceniem!) triggery ON INSERT (działa także w przypadku LOAD DATA) triggery ON DELETE triggery ON UPDATE według kryterium obiektu strzeżonego triggery modyfikacji danych triggery modyfikacji struktury (trigger ALTER, DROP) triggery eventowe (trigger LOGIN)
47
Budowa TRIGGERA Ogólna postać: Prawa (MySql):
CREATE [DEFINER = { user | CURRENT_USER }] TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt delimiter | CREATE TRIGGER testref BEFORE INSERT ON test1 FOR EACH ROW BEGIN UPDATE test4 SET b4 = b4 + 1 WHERE a4 = 3; END; | delimiter ; Prawa (MySql): tworzenie triggerów wymaga praw TRIGGER dla danej tablicy (wcześniej: prawo globalne SUPER)
48
obiekty NEW i OLD Obiekty przechowujące wartość poprzednią i nową:
create table t1 (id int, auto_increment primary key, liczba int); create table historia (z char(100), stamp timestamp) delimiter | CREATE TRIGGER moj1 AFTER UPDATE ON t1 FOR EACH ROW BEGIN INSERT INTO history(z) values (CONCAT(OLD.liczba,'->',NEW.liczba)); END; | delimiter ; update t1 set liczba=2 where id=1; insert into t1(liczba) values (222);
49
Obiekty OLD i NEW MySQL ułatwia wywołania obiektów poprzez nadanie im nazw delimiter | CREATE TRIGGER pensja_trigger BEFORE UPDATE ON pracownicy_table REFERENCING NEW ROW AS n, OLD ROW AS o FOR EACH ROW IF n.pensja <> o.pensja THEN --wykonaj odpowiednie działania; END IF; delimiter ;
50
Bezpieczniejsze tworzenie triggerów
DROP TRIGGER IF EXISTS moj1; delimiter | CREATE TRIGGER moj1 AFTER UPDATE ON t1 FOR EACH ROW BEGIN INSERT INTO history (zapis) values (3); END; | delimiter ;
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.