Oracle 12c: Nowości w SQL i PL/SQL Marek Wojciechowski Politechnika Poznańska, PLOUG
Nowe możliwości w klauzuli DEFAULT Odwołania do sekwencji Obsługa jawnie wstawianych wartości NULL Wartości na poziomie metadanych przy dodawaniu kolumny
DEFAULT: Odwołania do sekwencji Możliwe wykorzystanie atrybutów CURRVAL i NEXVAL sekwencji CREATE SEQUENCE seq; CREATE TABLE tab(id NUMBER DEFAULT seq.nextval, val VARCHAR2(1)); INSERT INTO tab(val) VALUES('x'); SELECT * FROM tab; ID VAL ---------- --- 1 x
DEFAULT: ON NULL Możliwość wymuszenia ustawienia wartości domyślnej gdy jawnie ustawiany NULL CREATE SEQUENCE seq; CREATE TABLE tab(id NUMBER DEFAULT ON NULL seq.nextval PRIMARY KEY, val VARCHAR2(1)); INSERT INTO tab(val) VALUES('x'); INSERT INTO tab(id, val) VALUES(NULL, 'x'); SELECT * FROM tab; ID VAL ---------- --- 1 x 2 x
DEFAULT: metadata-only dla dodawanych kolumn nieobowiązkowych Rozwiązanie problemu kosztownego ustawiania wartości w istniejących wierszach tabeli przy dodawaniu nowej kolumny W Oracle 11g dotyczyło tylko kolumn NOT NULL ALTER TABLE tab ADD(col NUMBER(3) DEFAULT 10); SELECT * FROM tab; ID VAL COL ---------- --- ---------- 1 x 10 2 x 10 Wiersze tabeli nie są modyfikowane Wartości pobierane z metadanych
Kolumny IDENTITY (1/4) Zgodny ze standardem mechanizm nadawania automatycznie inkrementowanych wartości (ułatwia migrację do Oracle) Dla jednej kolumny typu numerycznego w tabeli Kolumna automatycznie staje się NOT NULL Wewnętrznie IDENTITY wykorzystuje sekwencję Można ustawić jej parametry w klauzuli IDENTITY Opcje generacji: ALWAYS (domyślnie) BY DEFAULT [ON NULL]
Kolumny IDENTITY (2/4) = GENERATED ALWAYS AS IDENTITY CREATE TABLE tab(id NUMBER GENERATED AS IDENTITY, val VARCHAR2(1)); INSERT INTO tab(val) VALUES('x'); INSERT INTO tab(id, val) VALUES(10, 'x'); INSERT INTO tab(id, val) VALUES(NULL, 'x'); -- ORA-32795 -- ORA-32795 SELECT sequence_name FROM user_sequences; SEQUENCE_NAME --------------- ISEQ$$_92492 SELECT ISEQ$$_92492.CURRVAL FROM dual; CURRVAL ---------- 1
Kolumny IDENTITY (3/4) CREATE TABLE tab(id NUMBER GENERATED BY DEFAULT AS IDENTITY, val VARCHAR2(1)); INSERT INTO tab(val) VALUES('x'); INSERT INTO tab(id, val) VALUES(10, 'x'); INSERT INTO tab(id, val) VALUES(NULL, 'x'); -- ORA-01400 CREATE TABLE tab(id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, val VARCHAR2(1)); INSERT INTO tab(val) VALUES('x'); INSERT INTO tab(id, val) VALUES(10, 'x'); INSERT INTO tab(id, val) VALUES(NULL, 'x');
Kolumny IDENTITY (4/4) CREATE TABLE tab(id NUMBER GENERATED AS IDENTITY ( START WITH 10 INCREMENT BY 5), val VARCHAR2(1)); Ustawienia jak dla sekwencji Specyficzne operacje dla kolumn IDENTITY: Tylko dla kolumn IDENTITY! ALTER TABLE tab MODIFY id GENERATED ALWAYS AS IDENTITY (START WITH LIMIT VALUE); ALTER TABLE tab MODIFY id DROP IDENTITY;
Sekwencje o zasięgu sesji Dodane z myślą o globalnych tabelach tymczasowych Zwracają sekwencję wartości unikalnych w obrębie sesji Stan sekwencji tracony wraz z końcem sesji CREATE SEQUENCE seq SESSION; ALTER SEQUENCE seq GLOBAL; Domyślnie zasięg GLOBAL Uwaga: Zmiana zasięgu może powodować duplikaty w aktywnych sesjach
Limit wierszy zwracanych przez zapytanie Może być użyty do zapytań top-n We wcześniejszych wersjach Oracle stosowane: Podzapytanie w klauzuli FROM i warunek na ROWNUM Funkcje analityczne SELECT * FROM emp FETCH FIRST 5 ROWS ONLY; SELECT * FROM emp ORDER BY sal DESC FETCH FIRST 5 ROWS ONLY; SELECT * FROM emp ORDER BY sal DESC FETCH FIRST 2 ROWS WITH TIES SELECT * FROM emp ORDER BY sal DESC FETCH FIRST 20 PERCENT ROWS ONLY; SELECT * FROM emp ORDER BY sal DESC OFFSET 5 ROWS FETCH NEXT 3 ROWS ONLY;
Niewidzialne kolumny Dodawanie nowych kolumn bez wpływu na istniejące aplikacje DESC tab Name Null Type ---- ---- ------ X NUMBER INSERT INTO tab VALUES(5); SELECT * FROM tab; X ---------- 5 CREATE TABLE tab(x NUMBER); ALTER TABLE tab ADD (z NUMBER INVISIBLE); INSERT INTO tab(x, z) VALUES(5, 7); SELECT x, z FROM tab; X Z ---------- ---------- 5 5 7 ALTER TABLE tab MODIFY z VISIBLE; ALTER TABLE tab MODIFY z INVISIBLE; ORA-54039: table must have at least one column that is not invisible
Kaskadowa operacja TRUNCATE CREATE TABLE parent (id NUMBER PRIMARY KEY); CREATE TABLE child (id NUMBER, parent_id NUMBER REFERENCES parent(id) ON DELETE CASCADE); INSERT INTO parent VALUES(1); INSERT INTO child VALUES (10, 1); INSERT INTO child VALUES (10, null); TRUNCATE TABLE parent CASCADE; Tabela child również zostanie przycięta
Lateral inline views SELECT d.deptno, dname, ename FROM dept d, LATERAL(SELECT * FROM emp e WHERE e.deptno = d.deptno); DEPTNO DNAME ENAME ---------- -------------- ---------- 20 RESEARCH SMITH 30 SALES ALLEN 30 SALES WARD 20 RESEARCH JONES 30 SALES MARTIN 30 SALES BLAKE 10 ACCOUNTING CLARK 20 RESEARCH SCOTT 10 ACCOUNTING KING 30 SALES TURNER 20 RESEARCH ADAMS 30 SALES JAMES 20 RESEARCH FORD 10 ACCOUNTING MILLER
CROSS APPLY, OUTER APPLY CROSS APPLY = wariant CROSS JOIN standardu ANSI ze wsparciem lewostronnej korelacji OUTER APPLY= wariant LEFT OUTER JOIN stand. ANSI ze wsparciem lewostronnej korelacji Po prawej stronie operatora może się znajdować: tabela, perspektywa inline, wyrażenie TABLE kolekcja (nested table lub varray) zwracana przez: podzapytanie, odwołanie do kolumny, funkcję, konstruktor kolekcji
CROSS APPLY SELECT d.deptno, d.dname, v.ename FROM dept d CROSS APPLY (SELECT * FROM emp e WHERE e.deptno = d.deptno) v WHERE d.deptno IN (10,20,40); DEPTNO DNAME ENAME ---------- -------------- ---------- 20 RESEARCH SMITH 20 RESEARCH JONES 10 ACCOUNTING CLARK 20 RESEARCH SCOTT 10 ACCOUNTING KING 20 RESEARCH ADAMS 20 RESEARCH FORD 10 ACCOUNTING MILLER Lewostronna korelacja
OUTER APPLY SELECT d.deptno, d.dname, v.ename FROM dept d OUTER APPLY (SELECT * FROM emp e WHERE e.deptno = d.deptno) v WHERE d.deptno IN (10,20,40); DEPTNO DNAME ENAME ---------- -------------- ---------- 20 RESEARCH SMITH 20 RESEARCH JONES 10 ACCOUNTING CLARK 20 RESEARCH SCOTT 10 ACCOUNTING KING 20 RESEARCH ADAMS 20 RESEARCH FORD 10 ACCOUNTING MILLER 40 OPERATIONS Lewostronna korelacja
Zwiększony rozmiar typów SQL: VARCHAR2, NVARCHAR2 i RAW Maksymalny dopuszczalny rozmiar zwiększony do 32767 bajtów Ewentualny indeks podlega ograniczeniu na rozmiar klucza (zależny od rozmiaru bloku) Korzyści: Ułatwiona migracja do Oracle z innych systemów Uniknięcie w wielu przypadkach jawnego użycia LOB-ów Wymagane ustawienie parametru MAX_STRING_SIZE = EXTENDED (domyślnie STANDARD!) Zmiana ustawienia może spowodować inwalidację obiektów zależnych np. perspektyw (dostępny jest skrypt utl32k.sql i szczegółowo opisana procedura migracji) Składowane out-of-line (jako LOB) gdy rozmiar kolumny zadeklarowany powyżej : 4000 bajtów dla VARCHAR2/NVARCHAR2 2000 bajtów dla RAW
Niejawne zbiory wynikowe (1/2) Zapewniają zgodność z innymi systemami i pełniejsze wsparcie standardowych interfejsów programistycznych Dotychczas w Oracle należało jawnie zwracać REF CURSOR CREATE OR REPLACE PROCEDURE find_emps (p_job VARCHAR2) IS cur_emp SYS_REFCURSOR; BEGIN OPEN cur_emp FOR SELECT ename FROM emp WHERE job = p_job; DBMS_SQL.return_result (cur_emp); END; /
Niejawne zbiory wynikowe (2/2) SQL> BEGIN 2 find_emps('clerk'); 3 END; 4 / PL/SQL procedure successfully completed. ResultSet #1 ENAME ---------- SMITH ADAMS JAMES MILLER
Typy danych PL/SQL na styku PL/SQL i SQL Obsługa typu BOOLEAN przy wywołaniu anonimowego bloku PL/SQL z SQL CREATE OR REPLACE PROCEDURE proc (p_boo BOOLEAN) AS BEGIN IF p_boo THEN DBMS_OUTPUT.PUT_LINE('p_boo is TRUE'); END IF; END; / DECLARE stmt VARCHAR2(100); v_boo BOOLEAN := TRUE; BEGIN stmt := 'BEGIN proc(:p1); END;'; EXECUTE IMMEDIATE stmt USING v_boo; END; /
Zapytania SQL do typów kolekcji zdefiniowanych w PL/SQL Wcześniej dostępne tylko dla typów kolekcji zdefiniowanych w bazie danych CREATE OR REPLACE PACKAGE pak IS TYPE dept_collection IS TABLE OF dept%rowtype; PROCEDURE test; END; / CREATE OR REPLACE PACKAGE BODY pak IS PROCEDURE test IS dept_data dept_collection; BEGIN SELECT * BULK COLLECT INTO dept_data FROM dept; FOR d IN (SELECT * FROM TABLE(dept_data)) LOOP dbms_output.put_line(d.dname); END LOOP; END; END; /
Funkcje definiowane w klauzuli WITH WITH FUNCTION tax (salary NUMBER) RETURN NUMBER IS BEGIN RETURN salary * 0.18; END; SELECT ename, sal, tax(sal) FROM emp; / Większa wydajność niż przy wywoływaniu składowanych Rozwiązanie dla baz danych read-only
Nowe możliwości nadawania uprawnień do podprogramów PL/SQL Nadawanie ról pakietom i podprogramomom Umożliwia wykorzystanie praw wywołującego (IR) w połączeniu z rolami zamiast praw definiującego (DR) GRANT role1, To unit1, ; Ograniczenie możliwości wywołania jednostki PL/SQL do wskazanych jednostek z tego samego schematu (mechanizm white list ) Użycie white list uniemożliwia wywoływanie jednostki PL/SQL przez kod z innego schematu CREATE PACKAGE pak AUTHID DEFINER ACCESSIBLE BY (pak1, proc1, fun1) IS
Podsumowanie Oracle 12c wprowadza szereg nowości w obrębie podstawowej funkcjonalności serwera bazy danych Nowe konstrukcje w SQL Nowości w PL/SQL Nowe rozwiązania na styku PL/SQL i SQL Wiele rozszerzeń wynika z dostosowania Oracle do aktualnego standardu SQL i rozwiązań dostępnych w konkurencyjnych produktach Kolumny IDENTITY Ograniczanie liczby wierszy zwracanych przez zapytanie Niejawne zbiory wynikowe
Q & A Q: Czy %ROWTYPE uwzględnia kolumny INVISIBLE? A: NIE. Również nie działa deklaracja tab.invcol%type dla kolumny niewidzialnej Q: Czy w CROSS APPLY można użyć funkcji PIPELINED? A: TAK Q: Czy niejawne zbiory wynikowe można odebrać z poziomu PL/SQL? A: TAK. Korzystając z dbms_sql.get_next_result Q: Czy metadata-only defaults obowiązują też gdy ustawi się DEFAULT dla istniejącej kolumny? A: Nie. Ustawienie DEFAULT dla istniejącej kolumny nie powoduje ustawienia wartości domyślnej w miejsce NULL w istniejących wierszach.
Q & A Q: Czy nowe konstrukcje do limitowania wierszy działają też w podzapytaniach? A: TAK Q: Czy da się w klauzuli WITH wykorzystać i podzapytania i funkcje? A: TAK, ale w odpowiedniej kolejności! Najpierw muszą być podprogramy PL/SQL, a potem nazwane podzapytania. Q: Czy OFFSET też można wyrazić w procentach? A: NIE
Q & A Q: Czy sekwencja dla IDENTITY zniknie przy DROP TABLE? A: NIE od razu. Tzn. zniknie, ale dopiero po opróżnieniu kosza (purge recycle bin;) Q: Czy sekwencja dla IDENTITY i ograniczenie NOT NULL znikną przy ALTER TABLE DROP IDENTITY? A: TAK. Zniknie sekwencja i NOT NULL. Q: Co gdy ustawimy jawnie wartość w kolumnie IDENTITY BY DEFAULT? Czy przestawi się sekwencja? Czy ryzykujemy duplikat? A: Sekwencja się NIE przestawi. Może w przyszłości być duplikat. Q: Co gdy ktoś dostanie prawa do tabeli z kolumną IDENTITY bez praw do wykorzystywanej sekwencji? A: Może dodawać wiersze. Prawa do sekwencji musi mieć właściciel tabeli.