Blog JSystems - uwalniamy wiedzę!

Szukaj

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ć.

Mapa wersji: 18c → 19c → 21c → 23ai

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:

  • 19cLong Term Release. Stabilna, produkcyjna, z najdłuższym wsparciem. To na niej do dziś stoi większość systemów w bankach i telco.
  • 21cInnovation Release. Krótkie wsparcie, poligon nowych funkcji (natywny JSON, makra SQL, JavaScript w bazie, blockchain tables). Świetna do nauki i PoC, rzadziej na produkcję.
  • 23ai – nowy Long Term Release (początkowo wydany jako "23c Free", potem przemianowany na 23ai, bo flagową funkcją stało się AI Vector Search). To tu wlądowała większość długo wyczekiwanych usprawnień składni: prawdziwy typ BOOLEAN, SELECT bez FROM, IF EXISTS w poleceniach DDL, GROUP BY po aliasie kolumny, typ VECTOR oraz JSON Relational Duality – każde z działającym przykładem w dalszej części artykułu.
Uwaga o 20c: wersja 20c nigdy nie wyszła jako produkt on-premise – była tylko preview w chmurze. Część funkcji "z 20c", o których pisano w sieci, faktycznie trafiła dopiero do 21c lub 23ai.

Oracle 19c – dojrzała stabilizacja

19c to nie rewolucja składni, tylko automatyzacja i wydajność. Cztery rzeczy, które realnie zmieniają codzienną pracę z bazą:

LISTAGG z DISTINCT – koniec sztuczek na duplikaty

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

Automatic Indexing – baza sama dobiera indeksy

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ć.

Real-Time Statistics – statystyki zbierane w locie

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.

SQL Quarantine – kwarantanna zabójczych zapytań

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');

Oracle 21c – poligon dla programistów

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.

Natywny typ JSON – szybciej niż CLOB

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;

SQL Macros – reużywalne fragmenty zapytań

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);

JavaScript w bazie – pakiet DBMS_MLE

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;
/

Blockchain Tables – tabele, których nie zmienisz

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.

Oracle 23ai – największy skok dla developera

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.

Prawdziwy typ BOOLEAN

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

IF [NOT] EXISTS w DDL

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);

GROUP BY po aliasie (i pozycji) kolumny

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;

SELECT bez FROM – koniec z DUAL

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

Wstawianie wielu wierszy jednym VALUES

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);

Złączenia bezpośrednie w UPDATE i DELETE

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';

RETURNING ze starą i nową wartością

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;
/

SQL Domains – wielokrotnie używalne reguły kolumn

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
);

Adnotacje (Annotations) – metadane wprost w schemacie

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

JSON Relational Duality Views – jeden model, dwa widoki

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)

JSON Schema – walidacja struktury dokumentów

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

Typ VECTOR i AI Vector Search – sedno "ai" w 23ai

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;
Dlaczego to ważne: wektor + relacja w jednej bazie oznacza, że filtr biznesowy (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.

Ściągawka: co w której wersji

WersjaKluczowe nowości
19cLISTAGG DISTINCT, Automatic Indexing, Real-Time Statistics, SQL Quarantine, Active Data Guard DML Redirect
21cNatywny typ JSON, SQL Macros (SCALAR/TABLE), JavaScript w bazie (DBMS_MLE), Blockchain & Immutable Tables, Automatic In-Memory
23aiBOOLEAN, 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

Jak zacząć korzystać z nowości

  1. Najszybsza droga do zabawy z 23ai to Oracle Database 23ai Free – darmowa edycja do nauki i developmentu (kontener Docker albo instalka na VM). Większość składni z tego artykułu uruchomisz w 5 minut.
  2. Na produkcji sprawdź poziom edycji i licencji – część funkcji (Automatic Indexing, Real-Time Statistics, In-Memory) wymaga Enterprise Edition lub konkretnych opcji.
  3. Przy migracji z 12c/18c zaplanuj test planów wykonania – nowy optymalizator i automatyczne statystyki potrafią zmienić plany; warto porównać wydajność przed przełączeniem.
  4. Nowości składni 23ai (BOOLEAN, GROUP BY po aliasie, IF EXISTS) ułatwiają przenoś ność kodu z PostgreSQL/MySQL – dobry moment, by ujednolicić standardy w zespole.

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 bazach danych Oracle - JSystems

Szkolenie kompleksowe: Tuning wydajności SQL w Oracle -->

Zaawansowany 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.

Sprawdź terminy i zapisz się -->

Szkolenie PL/SQL - Zaawansowany SQL i programowanie w PL/SQL

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

Sprawdź terminy i zapisz się -->

Najczęściej zadawane pytania

Czym różni się Oracle 23ai od 23c?
To ta sama generacja bazy. Wersja została najpierw udostępniona jako "Oracle Database 23c Free", a następnie przemianowana na 23ai - ponieważ jej flagową funkcją stało się AI Vector Search oraz natywny typ VECTOR. Funkcjonalnie 23c i 23ai opisują ten sam Long Term Release.
Czy mogę używać typu BOOLEAN w SQL w starszych wersjach Oracle?
Nie. Przed 23ai BOOLEAN istniał wyłącznie w PL/SQL, ale nie w SQL ani w kolumnach tabel - logikę modelowano przez CHAR(1) lub NUMBER(1). Natywny typ BOOLEAN w SQL (kolumny, warunki, INSERT) pojawił się dopiero w Oracle 23ai.
Co to jest typ VECTOR w Oracle 23ai?
VECTOR to natywny typ danych do przechowywania embeddingów (wektorów cech) bezpośrednio w tabelach. Razem z funkcją VECTOR_DISTANCE umożliwia wyszukiwanie semantyczne (similarity search) zwykłym SQL-em - podstawa dla RAG, rekomendacji i aplikacji AI bez osobnej bazy wektorowej.
Czy SQL Macros zastępują widoki i funkcje PL/SQL?
Nie zastępują, lecz uzupełniają. Makro SQL zwraca fragment tekstu SQL wstawiany do zapytania w czasie parsowania, dzięki czemu nie ma narzutu wywołania funkcji dla każdego wiersza. To dobre rozwiązanie dla reużywalnych, parametryzowanych fragmentów zapytań, gdzie zwykła funkcja PL/SQL byłaby zbyt wolna, a widok - zbyt sztywny.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...