SQL od podstaw · część 07

CREATE: baza, tabele i ograniczenia

Zamień projekt w strukturę, która pilnuje danych. Porównaj AUTO_INCREMENT, IDENTITY, Oracle identity i COUNTER w Access.

Część bazodanowa INF.03

Od projektu do tabeli

CREATE to polecenie DDL: buduje strukturę. Nie dodaje jeszcze klientów ani zamówień. Najpierw wybierz osobną bazę ćwiczeniową, potem utwórz tabele nadrzędne, a na końcu tabele z kluczami obcymi. Pracuj na nowej nazwie, aby nie pomylić ćwiczeń z bazą aplikacji.

-- MySQL 8.4 / MariaDB 10.4+, rzeczywisty serwer
CREATE DATABASE cn_sql_cwiczenia CHARACTER SET utf8mb4;
USE cn_sql_cwiczenia;

CREATE TABLE kategorie (
  id INT PRIMARY KEY,
  nazwa VARCHAR(60) NOT NULL UNIQUE
) ENGINE=InnoDB;

CREATE TABLE towary (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nazwa VARCHAR(120) NOT NULL,
  cena DECIMAL(10,2) NOT NULL,
  stan INT NOT NULL DEFAULT 0,
  kategoria_id INT NOT NULL,
  CONSTRAINT ck_towary_cena CHECK (cena >= 0),
  CONSTRAINT ck_towary_stan CHECK (stan >= 0),
  CONSTRAINT fk_towary_kategoria FOREIGN KEY (kategoria_id)
    REFERENCES kategorie(id)
) ENGINE=InnoDB;

Jeżeli baza już istnieje, zatrzymaj się i wybierz inną nazwę lub sprawdź, czy jest to Twoja baza ćwiczeniowa. Nie dodawaj DROP DATABASE tylko po to, aby skrypt przestał zgłaszać konflikt. CREATE DATABASE i USE nie należą do zakresu edytora w przeglądarce.

Ograniczenia są częścią projektu

ElementRolaPrzykład naruszenia
PRIMARY KEYJednoznaczny, niepusty identyfikator wiersza.Drugi wiersz z tym samym id.
NOT NULLWartość jest wymagana.Brak nazwy produktu.
UNIQUEWartości albo kombinacje kolumn nie mogą się powtarzać.Dwie kategorie o tej samej nazwie według kolacji.
FOREIGN KEYOdwołanie do istniejącego klucza nadrzędnego.Towar z kategorią 99, której nie ma.
CHECKWarunek dla zapisywanego wiersza.Ujemna cena lub stan.
DEFAULTWartość domyślna przy pominięciu kolumny.Nie jest zabezpieczeniem przed podaniem błędnej wartości.

CHECK sam nie zastępuje NOT NULL: wynik UNKNOWN może nie odrzucić wiersza. Łącz oba wymagania, jeżeli cena ma istnieć i być nieujemna. W starszym MySQL przed 8.0.16 CHECK bywał przyjmowany bez egzekwowania; sprawdzaj wersję. MariaDB ma własną historię obsługi i nie jest numerowaną odmianą MySQL.

Klucz obcy wymaga zgodnych typów i odpowiedniego klucza po stronie wskazywanej. W MySQL użyj silnika obsługującego więzy, np. InnoDB. Samo podobieństwo nazw id i kategoria_id nie tworzy relacji. UNIQUE przy NULL zachowuje się różnie: typowe MySQL dopuszcza wiele NULL, natomiast zwykły unikatowy indeks jednej kolumny w SQL Server dopuszcza tylko jeden NULL. To wymaga osobnego projektu ograniczenia.

Automatyczne id w czterech środowiskach

Ten sam cel — nowy produkt otrzymuje numer — zapisuje się inaczej. To przykłady do właściwego silnika, celowo nieprzepuszczane przez emulację.

-- MySQL / MariaDB
CREATE TABLE produkty_demo (
 id INT AUTO_INCREMENT PRIMARY KEY,
 nazwa VARCHAR(120) NOT NULL
);

-- SQL Server (T-SQL)
CREATE TABLE produkty_demo (
 id INT IDENTITY(1,1) PRIMARY KEY,
 nazwa NVARCHAR(120) NOT NULL
);

-- Oracle 19c, identity dostępne od 12c
CREATE TABLE produkty_demo (
 id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
 nazwa VARCHAR2(120 CHAR) NOT NULL
);

-- Microsoft Access / ACE, kwerenda definiująca dane
CREATE TABLE produkty_demo (
 id COUNTER CONSTRAINT pk_produkty_demo PRIMARY KEY,
 nazwa TEXT(120) NOT NULL
);

Automatyczny numer może mieć luki. Usunięcie lub wycofanie wiersza nie zobowiązuje silnika do ponownego użycia numeru. Nie używaj takiego klucza jako gwarantowanie ciągłej numeracji dokumentów. Oracle ma też osobne sekwencje, np. CREATE SEQUENCE seq_demo START WITH 1; i seq_demo.NEXTVAL; sekwencja nie tworzy sama klucza głównego.

Wersja dydaktyczna w przeglądarce

Poniższa tabela pozwala przećwiczyć CREATE, NOT NULL i CHECK. INTEGER, TEXT i REAL opisują uproszczony schemat SQLite. Wartości id podajemy jawnie. Nie jest to test zakresu INT, VARCHAR ani dokładności DECIMAL rzeczywistego serwera.

CREATE TABLE notatki (
 id INTEGER PRIMARY KEY,
 temat TEXT NOT NULL,
 priorytet INTEGER NOT NULL CHECK (priorytet >= 1)
);

Wypróbuj zapytanie

SQLite w przeglądarce — ograniczona emulacja składni MySQL / SQL Server. To nie są rzeczywiste serwery. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.

Ładowanie edytora…

Ćwiczenia

  1. Utwórz w edytorze tabelę notatki. Rozwiń schemat i sprawdź, że tabela ma zero wierszy.
  2. Zaprojektuj tabelę uczniowie: identyfikator, wymagane imię, wymagany unikatowy numer ewidencyjny. Wybierz typy dla MySQL/MariaDB.
  3. Wyjaśnij, czym różnią się PRIMARY KEY, AUTO_INCREMENT oraz DEFAULT 0.
Rozwiązania

1. Wykonaj powyższy CREATE tylko raz albo użyj Reset bazy przed ponownym utworzeniem. Błąd „table already exists” informuje o istniejącym obiekcie.

CREATE TABLE uczniowie (
 id INT AUTO_INCREMENT PRIMARY KEY,
 imie VARCHAR(60) NOT NULL,
 numer VARCHAR(20) NOT NULL UNIQUE
);

2. Numer ewidencyjny jest tekstem, więc zachowuje początkowe zera. 3. PRIMARY KEY identyfikuje wiersz i wymusza unikalność; AUTO_INCREMENT generuje wartości; DEFAULT podaje wartość przy pominięciu kolumny i nie zapewnia unikalności.

Dokumentacja: MySQL CREATE TABLE, T-SQL CREATE TABLE, Oracle CREATE TABLE, Access CREATE TABLE. INF.03.4: tworzenie struktur i kontrola spójności. Dalej: ALTER i DROP.

Przewijanie do góry