Blog JSystems - uwalniamy wiedzę!
Blog JSystems - uwalniamy wiedzę!
Jeśli ostatni raz pisałeś kod pod Oracle 12c albo 18c, to baza danych, którą znasz, zmieniła się bardziej, niż myślisz. Przez ostatnie lata Oracle dorzucił do języka SQL i PL/SQL rzeczy, na które programiści czekali latami: prawdziwy typ BOOLEAN, SELECT bez FROM, natywny typ JSON, JavaScript wykonywany wewnątrz bazy, makra SQL, a w 23ai – typ VECTOR i wyszukiwanie semantyczne pod AI. Ten artykuł to przegląd najważniejszych nowości wprowadzonych po 18c, wersja po wersji, z konkretnym kodem, który możesz wkleić i uruchomić.
Najpierw porządek w nazewnictwie, bo Oracle sam namieszał. Po 18c numeracja przestała oznaczać "co roku jedna duża wersja" i podzieliła się na dwa nurty:
19c to nie rewolucja składni, tylko automatyzacja i wydajność. Cztery rzeczy, które realnie zmieniają codzienną pracę z bazą:
Przed 19c LISTAGG nie znało słowa DISTINCT. Żeby skleić tylko unikalne wartości, trzeba było albo odsiać duplikaty osobnym podzapytaniem, albo posłużyć się brzydkim trikiem z REGEXP_REPLACE na gotowym stringu:
-- Przed 19c, wariant 1: duplikaty odsiane wczesniej, w podzapytaniu
SELECT department_id,
LISTAGG(job_id, ', ') WITHIN GROUP (ORDER BY job_id) AS stanowiska
FROM (SELECT DISTINCT department_id, job_id FROM employees)
GROUP BY department_id;
-- Przed 19c, wariant 2: trik regexem usuwajacy powtorzenia w gotowym stringu
SELECT department_id,
REGEXP_REPLACE(
LISTAGG(job_id, ', ') WITHIN GROUP (ORDER BY job_id),
'([^,]+)(, \1)+', '\1') AS stanowiska
FROM employees
GROUP BY department_id;
Od 19c to jedno słowo – DISTINCT prosto w LISTAGG, bez podzapytań i trików:
-- 19c: DISTINCT bezpośrednio w LISTAGG
SELECT department_id,
LISTAGG(DISTINCT job_id, ', ')
WITHIN GROUP (ORDER BY job_id) AS stanowiska
FROM employees
GROUP BY department_id;
-- DEPARTMENT_ID STANOWISKA
-- 50 SH_CLERK, ST_CLERK, ST_MAN
-- 80 SA_MAN, SA_REP
Jedna z największych nowości 19c (Enterprise Edition oraz Autonomous Database). Co kilkanaście minut baza analizuje rzeczywiste obciążenie, wykrywa zapytania, którym brakuje indeksu, i zakłada kandydujące indeksy jako niewidoczne (invisible) – optymalizator korzysta z nich tylko w trybie testowym. Potem porównuje wydajność tych samych zapytań z indeksem i bez niego: jeśli indeks realnie pomaga, publikuje go (staje się widoczny dla wszystkich), a jeśli nie – odrzuca. Automatycznie utworzone indeksy poznasz po nazwie zaczynającej się od SYS_AI_ i fladze AUTO = 'YES'.
Sterujesz tym jedną procedurą z pakietu DBMS_AUTO_INDEX – zwykle najpierw w trybie raportowym, a po sprawdzeniu przełączasz na produkcyjny:
-- Tryb testowy: baza TYLKO rekomenduje, nic nie tworzy
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE', 'REPORT ONLY');
-- Tryb produkcyjny: automat sam tworzy i publikuje pomocne indeksy
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE', 'IMPLEMENT');
-- Ogranicz automat do wybranych schematow (np. tylko HR i SALES)
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', 'HR', TRUE);
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', 'SALES', TRUE);
-- Ile dni trzymac nieuzywane auto-indeksy, zanim baza je skasuje
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_AUTO', '30');
Gdzie podejrzeć, co automat utworzył? Auto-indeksy leżą w tych samych widokach słownikowych co zwykłe, tylko z flagą AUTO = 'YES' – do tego masz widok konfiguracji i gotowy raport tekstowy:
-- Lista indeksow utworzonych automatycznie (nazwy SYS_AI_...)
SELECT owner, index_name, table_name, auto, visibility, status
FROM dba_indexes
WHERE auto = 'YES'
ORDER BY owner, table_name;
-- Biezaca konfiguracja automatu (tryb, schematy, retencja)
SELECT parameter_name, parameter_value
FROM dba_auto_index_config;
-- Pelny raport za ostatnia dobe: co utworzono/odrzucono,
-- o ile przyspieszyly zapytania, ile zajely miejsca
SELECT DBMS_AUTO_INDEX.REPORT_ACTIVITY(
SYSTIMESTAMP - 1, SYSTIMESTAMP) AS raport
FROM dual;
Tak to wygląda na żywej bazie. Sam widok konfiguracji podejrzysz na każdej edycji – poniżej realny zrzut dba_auto_index_config ze świeżej instancji. Domyślnie automat jest wyłączony (AUTO_INDEX_MODE = OFF), nieużywane auto-indeksy baza trzyma 373 dni, a raporty 40 dni:
SQL> SELECT parameter_name, parameter_value FROM dba_auto_index_config;
PARAMETER_NAME PARAMETER_VALUE
-------------------------------------- ----------------
AUTO_INDEX_COMPRESSION OFF
AUTO_INDEX_DEFAULT_TABLESPACE
AUTO_INDEX_INCLUDE_DML_COST ON
AUTO_INDEX_MODE OFF
AUTO_INDEX_REPORT_RETENTION 40
AUTO_INDEX_RETENTION_FOR_AUTO 373
AUTO_INDEX_RETENTION_FOR_MANUAL
AUTO_INDEX_SCHEMA
AUTO_INDEX_SPACE_BUDGET 50
AUTO_INDEX_TABLE
10 rows selected.
Uwaga licencyjna. Samo włączenie automatu (AUTO_INDEX_MODE = IMPLEMENT) i powstające indeksy SYS_AI_ to funkcja Enterprise Edition oraz Autonomous Database. Na Standard Edition i w bezpłatnym Oracle Database Free ta sama procedura zwraca błąd:
SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE', 'IMPLEMENT');
BEGIN DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE', 'IMPLEMENT'); END;
*
ERROR at line 1:
ORA-40216: feature not supported
Lista utworzonych indeksów. Na wspieranej platformie (Autonomous Database lub Exadata) ta sama procedura przechodzi i automat realnie zakłada indeksy. Auto-indeks poznasz po prefiksie SYS_AI_ i fladze AUTO = 'YES'; kolumna VISIBILITY pokazuje etap weryfikacji (najpierw INVISIBLE – optymalizator testuje indeks w ukryciu, a po potwierdzeniu zysku VISIBLE), zaś STATUS = VALID oznacza indeks gotowy do użycia. Oto autentyczny przebieg z Autonomous Database 19c: po przełączeniu na IMPLEMENT i cyklu automatu nad naszym obciążeniem (tabela 1 mln wierszy, powtarzane zapytania po nieindeksowanej kolumnie KLIENT_ID) powstał jeden indeks. Na Standard Edition i w Oracle Free to samo zapytanie zwraca brak wierszy – automat tam nie działa:
SQL> SELECT owner, index_name, table_name, auto, visibility, status
FROM dba_indexes WHERE auto = 'YES';
OWNER INDEX_NAME TABLE_NAME AUTO VISIBILITY STATUS
----- -------------------- ---------- ---- ---------- ------
ADMIN SYS_AI_99zjgtmjmwt9a ZAMOWIENIA YES VISIBLE VALID
Raport aktywności. Skoro indeks już jest, REPORT_ACTIVITY daje gotowe podsumowanie dla administratora: które indeksy powstały, o ile procent przyspieszyły konkretne zapytania, ile zajęły miejsca i które kandydatury baza odrzuciła jako nieprzydatne – bez ręcznego zgadywania. Z tego samego przebiegu:
SQL> SELECT DBMS_AUTO_INDEX.REPORT_ACTIVITY() FROM dual;
GENERAL INFORMATION
-------------------------------------------------------------------------------
Activity start : 23-JUN-2026 16:04:28
Activity end : 23-JUN-2026 17:04:28
Executions completed : 1
SUMMARY (AUTO INDEXES)
-------------------------------------------------------------------------------
Index candidates : 1
Indexes created (visible / invisible) : 1 (1 / 0)
Space used (visible / invisible) : 13.63 MB (13.63 MB / 0 B)
SQL statements verified : 2
SQL statements improved (improvement factor) : 2 (389.5x)
Overall improvement factor : 389.5x
INDEX DETAILS
-------------------------------------------------------------------------------
| Owner | Table | Index | Key | Type |
| ADMIN | ZAMOWIENIA | SYS_AI_99zjgtmjmwt9a | KLIENT_ID | B-TREE |
VERIFICATION DETAILS
-------------------------------------------------------------------------------
SQL ID : 7p9s5mbztk5zn
SQL Text : SELECT SUM(KWOTA) S FROM ZAMOWIENIA
WHERE KLIENT_ID = MOD(:B1*13,50000)
Improvement Factor : 220.17x
Z raportu czytasz wprost: 1 kandydat, 1 utworzony indeks (13,63 MB), 2 zapytania zweryfikowane i poprawione, B-drzewo na KLIENT_ID – ze współczynnikiem poprawy 389,5x. To samo zadanie z czasem usuwa też nieużywane auto-indeksy i samo wycofuje zmiany, które nie przyniosły poprawy – bez udziału administratora. Same zapytania kontrolne (widoki słownikowe + REPORT_ACTIVITY) są identyczne na każdej edycji – różni się tylko to, czy automat ma prawo działać.
Do tej pory statystyki optymalizatora robił DBMS_STATS w oknie nocnym, a między zbieraniami potrafiły się "zestarzeć". W 19c (Enterprise Edition na Exadata) baza dozbiera podstawowe statystyki automatycznie podczas zwykłych operacji INSERT / UPDATE, dzięki czemu optymalizator ma świeższe dane bez czekania na nocny job.
Gdy Resource Manager zabije zapytanie za zbyt żarłoczne zużycie CPU/IO, 19c zapamiętuje jego plan wykonania i "kwarantannuje" go – kolejne uruchomienie tego samego, kosztownego planu jest odrzucane od razu, bez ponownego zarżynania serwera.
-- Podgląd skwarantannowanych planów
SELECT name, plan_hash_value, last_executed
FROM dba_sql_quarantine;
-- Ręczne usunięcie konfiguracji kwarantanny
EXEC DBMS_SQLQ.DROP_QUARANTINE('SQL_QUARANTINE_abc123');
21c to wersja, w której Oracle przestaje być "tylko relacyjną bazą". Pojawia się natywny JSON, JavaScript w środku silnika, makra SQL i tabele kryptograficzne. Nawet jeśli nie wdrożysz 21c na produkcji, warto znać te funkcje – większość z nich jest dostępna też w 23ai.
Wcześniej JSON trzymaliśmy w VARCHAR2 / CLOB z ograniczeniem IS JSON. 21c wprowadza dedykowany typ JSON, w którym dokument jest parsowany raz, przy zapisie – odczyt i aktualizacja są wielokrotnie szybsze.
CREATE TABLE zamowienia (
id NUMBER GENERATED ALWAYS AS IDENTITY,
dane JSON -- natywny typ, nie VARCHAR2/CLOB
);
INSERT INTO zamowienia (dane) VALUES (
'{"klient":"Nowak Sp. z o.o.","pozycje":[{"sku":"A1","ilosc":3}],"kwota":1499.00}'
);
-- Dot-notation prosto po polach JSON, bez funkcji:
SELECT z.dane.klient AS klient,
z.dane.kwota.number() AS kwota
FROM zamowienia z
WHERE z.dane.kwota.number() > 1000;
Makra SQL to funkcje, które zamiast wartości zwracają fragment tekstu SQL wstawiany do zapytania w czasie parsowania. Działają jak szablon, ale bez narzutu wywołania funkcji PL/SQL dla każdego wiersza. Są dwa rodzaje: SCALAR (do SELECT/WHERE) i TABLE (do FROM).
-- MAKRO SKALARNE: czytelny warunek "między datami"
CREATE OR REPLACE FUNCTION between_dates(p_col DATE, p_from DATE, p_to DATE)
RETURN VARCHAR2 SQL_MACRO(SCALAR)
IS
BEGIN
RETURN 'p_col BETWEEN p_from AND p_to';
END;
/
SELECT * FROM employees
WHERE between_dates(hire_date, DATE '2020-01-01', DATE '2020-12-31');
-- MAKRO TABELARYCZNE: parametryzowany "TOP N" jako źródło w FROM
CREATE OR REPLACE FUNCTION top_n_salary(p_n NUMBER)
RETURN CLOB SQL_MACRO
IS
BEGIN
RETURN 'SELECT employee_id, last_name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST p_n ROWS ONLY';
END;
/
SELECT * FROM top_n_salary(5);
Multilingual Engine (MLE) pozwala uruchomić kod JavaScript wewnątrz bazy, z dwukierunkową wymianą danych z PL/SQL i SQL. Idealne, gdy masz gotową logikę w JS albo potrzebujesz przetwarzania, które w SQL jest niewygodne.
DECLARE
l_ctx DBMS_MLE.context_handle_t;
l_source CLOB;
BEGIN
l_ctx := DBMS_MLE.create_context();
l_source := q'~
// JavaScript wykonywany wewnątrz Oracle
const result = session.execute(
"SELECT last_name FROM employees WHERE rownum <= 3");
let names = [];
while (result.rows && result.rows.length) {
names = result.rows.map(r => r[0]);
break;
}
soda; // dostęp do kolekcji JSON także z JS
console.log("Pracownicy: " + names.join(", "));
~';
DBMS_MLE.eval(l_ctx, 'JAVASCRIPT', l_source);
DBMS_MLE.drop_context(l_ctx);
END;
/
Tabele typu blockchain pozwalają wyłącznie na INSERT. Każdy wiersz jest kryptograficznie połączony (hash) z poprzednim – próba modyfikacji lub usunięcia historii jest wykrywana. Świetne do logów audytowych, które muszą być niepodważalne (compliance, AML, RODO).
CREATE BLOCKCHAIN TABLE audyt_operacji (
id NUMBER,
operacja VARCHAR2(100),
uzytkownik VARCHAR2(50),
ts TIMESTAMP
)
NO DROP UNTIL 31 DAYS IDLE -- nie skasujesz tabeli od ręki
NO DELETE LOCKED -- wierszy nie da się usunąć
HASHING USING "SHA2_512" VERSION "v1";
-- Działa tylko INSERT; UPDATE/DELETE = błąd ORA-05715
Pokrewną funkcją są Immutable Tables (też 21c) – niezmienne tabele bez całego łańcucha hashy, gdy potrzebujesz tylko "insert-only" bez pełnej kryptografii blockchaina.
To wersja, na którą programiści czekali najdłużej. 23ai usuwa irytujące różnice między Oracle a PostgreSQL/MySQL i dorzuca rzeczy, których w ogóle nie było. Przejdźmy przez nie z kodem.
Koniec z CHAR(1) i NUMBER(1) udającymi logikę. 23ai ma natywny BOOLEAN w SQL – w kolumnach, warunkach i INSERT. Akceptuje też wartości tekstowe jak 'yes'/'no', 'on'/'off', 1/0.
CREATE TABLE uzytkownicy (
id NUMBER GENERATED ALWAYS AS IDENTITY,
login VARCHAR2(50),
aktywny BOOLEAN, -- natywny typ logiczny
archiwum BOOL DEFAULT FALSE -- BOOL = synonim BOOLEAN
);
INSERT INTO uzytkownicy (login, aktywny, archiwum) VALUES
('anowak', TRUE, FALSE),
('jkowal', 'yes', 'no'), -- wartości tekstowe też działają
('bzych', 1, 0);
SELECT login FROM uzytkownicy WHERE aktywny; -- bez = TRUE
Skrypty migracyjne bez blokuów BEGIN ... EXCEPTION WHEN OTHERS. 23ai pozwala warunkowo tworzyć i usuwać obiekty:
DROP TABLE IF EXISTS logi_tymczasowe;
CREATE TABLE IF NOT EXISTS slownik_statusow (
kod VARCHAR2(10) PRIMARY KEY,
opis VARCHAR2(100)
);
CREATE INDEX IF NOT EXISTS idx_status_opis ON slownik_statusow(opis);
Klasyczny zgrzyt dla osób znających PostgreSQL: w Oracle nie dało się grupować po aliasie z SELECT. W 23ai już można – po aliasie albo po numerze pozycji:
SELECT TRUNC(hire_date, 'MM') AS miesiac,
COUNT(*) AS liczba
FROM employees
GROUP BY miesiac -- alias zamiast powtarzania TRUNC(...)
ORDER BY miesiac;
-- Można też po pozycji:
SELECT department_id, job_id, COUNT(*)
FROM employees
GROUP BY 1, 2;
Drobiazg, który cieszy. Proste wyliczenia i wywołania funkcji bez sztucznego FROM dual:
SELECT 25.50 * 25.25; -- 643.875
SELECT SYSDATE; -- bieżąca data
SELECT 'Witaj ' || USER; -- bez FROM dual
Tzw. Table Value Constructor. Zamiast wielu osobnych INSERT albo INSERT ALL – jedna lista wartości. Działa też w SELECT:
INSERT INTO slownik_statusow (kod, opis) VALUES
('NEW', 'Nowy'),
('PRC', 'W realizacji'),
('FIN', 'Zakończony'),
('ERR', 'Błąd');
-- VALUES jako źródło wierszy w SELECT:
SELECT * FROM (VALUES (1,'a'), (2,'b'), (3,'c')) AS t(nr, litera);
23ai pozwala użyć FROM z innymi tabelami wprost w UPDATE i DELETE, bez korelowanych podzapytań:
-- Podwyżka dla działu IT - złączenie wprost w UPDATE
UPDATE employees e
SET e.salary = e.salary * 1.10
FROM departments d
WHERE e.department_id = d.department_id
AND d.department_name = 'IT';
-- DELETE ze złączeniem
DELETE FROM order_items oi
FROM orders o
WHERE oi.order_id = o.order_id
AND o.status = 'CANCELLED';
Klauzula RETURNING w 23ai potrafi zwrócić jednocześnie wartość przed i po zmianie – idealne do audytu i logów bez dodatkowego SELECT:
DECLARE
v_old NUMBER;
v_new NUMBER;
BEGIN
UPDATE employees
SET salary = salary * 1.10
WHERE employee_id = 100
RETURNING OLD salary, NEW salary INTO v_old, v_new;
DBMS_OUTPUT.PUT_LINE('Przed: '||v_old||' Po: '||v_new);
END;
/
Domena to nazwany zestaw typu + ograniczeń + formatowania, który przypisujesz wielu kolumnom. Definiujesz regułę (np. poprawny e-mail) raz, a używasz wszędzie:
CREATE DOMAIN email_dom AS VARCHAR2(255)
CONSTRAINT email_chk CHECK (REGEXP_LIKE(email_dom, '^[^@]+@[^@]+\.[^@]+$'));
CREATE TABLE kontakty (
id NUMBER,
email VARCHAR2(255) DOMAIN email_dom -- reguła dziedziczona z domeny
);
Lekka alternatywa dla komentarzy – pary nazwa/wartość opisujące kolumny i tabele, czytelne dla narzędzi i aplikacji (np. "to pole jest wrażliwe", "ukryj w UI"):
CREATE TABLE pacjenci (
id NUMBER,
pesel VARCHAR2(11) ANNOTATIONS (PII, Display 'Numer PESEL'),
imie VARCHAR2(50) ANNOTATIONS (Display 'Imię')
) ANNOTATIONS (Schemat 'medyczny');
SELECT * FROM user_annotations_usage; -- przegląd adnotacji
Sztandarowa funkcja 23ai. Te same dane relacyjne możesz czytać i zapisywać jako dokumenty JSON – baza synchronizuje oba światy. Aplikacja webowa dostaje wygodny JSON, a integralność i transakcyjność pilnuje relacyjny silnik:
CREATE JSON RELATIONAL DUALITY VIEW dzial_dv AS
SELECT JSON {
'_id' : d.department_id,
'nazwa' : d.department_name,
'pracownicy' :
[ SELECT JSON { 'id': e.employee_id, 'nazwisko': e.last_name }
FROM employees e WITH INSERT UPDATE
WHERE e.department_id = d.department_id ]
}
FROM departments d WITH INSERT UPDATE DELETE;
-- Czytasz jako dokument:
SELECT data FROM dzial_dv WHERE json_value(data, '$._id') = 50;
-- ...i zapisujesz jako dokument - baza rozkłada to na tabele:
-- (INSERT/UPDATE na widoku dualnym)
23ai pozwala wymusić zgodność dokumentu JSON ze schematem wprost w CHECK:
CREATE TABLE produkty (
id NUMBER,
dane JSON VALIDATE '{
"type": "object",
"properties": {
"sku": {"type": "string"},
"cena": {"type": "number", "minimum": 0}
},
"required": ["sku", "cena"]
}'
);
-- INSERT niezgodny ze schematem zostanie odrzucony
Najważniejsza nowość całej wersji. Natywny typ VECTOR przechowuje embeddingi (wektory cech) obok danych biznesowych, a funkcja VECTOR_DISTANCE liczy podobieństwo semantyczne. Dzięki temu wyszukiwanie "po znaczeniu" (RAG, rekomendacje, semantic search) robisz zwykłym SQL-em – bez osobnej bazy wektorowej:
CREATE TABLE dokumenty (
id NUMBER,
tytul VARCHAR2(200),
tresc CLOB,
embedding VECTOR(768, FLOAT32) -- 768 wymiarów, liczby 32-bit
);
-- Wyszukiwanie semantyczne: 5 dokumentów najbliższych zapytaniu
SELECT id, tytul
FROM dokumenty
ORDER BY VECTOR_DISTANCE(embedding, :wektor_pytania, COSINE)
FETCH FIRST 5 ROWS ONLY;
-- Indeks wektorowy HNSW dla szybkiego wyszukiwania przybliżonego
CREATE VECTOR INDEX idx_emb ON dokumenty(embedding)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE;
WHERE status='AKTYWNY') i wyszukiwanie semantyczne dzieją się w jednym zapytaniu, w jednej transakcji. To właśnie ta funkcja dała wersji literę "ai" w nazwie.To nie tylko wektory. Drugą twarzą AI w 23ai jest Select AI – odpytujesz bazę po ludzku, a ona sama pisze SQL. Wystarczy SELECT AI 'przychód w podziale na miesiące', by dostać gotowe zapytanie i wynik – bez znajomości schematu i składni. Wyszukiwanie wektorowe, Select AI oraz uczenie maszynowe w samej bazie rozkładamy na czynniki pierwsze, na realnych danych i zrzutach z żywej bazy, w osobnym artykule: AI w bazie Oracle – Vector Search, Select AI i Machine Learning. Zobaczysz tam m.in. realne SELECT AI nad danymi sprzedażowymi i to, jak baza sama zwraca gotowy SQL. Jeśli temat AI w 23ai Cię wciągnął – to naturalny następny krok.
| Wersja | Kluczowe nowości |
|---|---|
| 19c | LISTAGG DISTINCT, Automatic Indexing, Real-Time Statistics, SQL Quarantine, Active Data Guard DML Redirect |
| 21c | Natywny typ JSON, SQL Macros (SCALAR/TABLE), JavaScript w bazie (DBMS_MLE), Blockchain & Immutable Tables, Automatic In-Memory |
| 23ai | BOOLEAN, IF [NOT] EXISTS, GROUP BY po aliasie, SELECT bez FROM, multi-row VALUES, JOIN w UPDATE/DELETE, RETURNING OLD/NEW, SQL Domains, Annotations, JSON Duality Views, JSON Schema, typ VECTOR + AI Vector Search |
Nowe wersje Oracle to nie kosmetyka – to realne narzędzia, które skracają kod, podnoszą wydajność i otwierają bazie drogę do zastosowań AI. Jeśli chcesz przećwiczyć je na prawdziwych przykładach – od zaawansowanego SQL, przez tuning wydajności, po programowanie w PL/SQL – zajrzyj na szkolenia Oracle JSystems.
Szkolenie kompleksowe: Tuning wydajności SQL w Oracle -->
Funkcje analityczne i okienkowe, zapytania hierarchiczne, pivot/unpivot, wyrażenia regularne i optymalizacja złożonych zapytań – pełne wyciskanie możliwości SQL-a w Oracle.
5 dni intensywnych warsztatów z Moniką Lewandowską - jedną z najbardziej doświadczonych ekspertek Oracle w Polsce (Oracle ACE Pro). Dynamiczny SQL, kolekcje, kursory, optymalizacja, utPLSQL. Terminy gwarantowane, ocena 4.9/5.
5 dni
Komentarze (0)
Brak komentarzy...