Ściąga - SQL
0. Grupy poleceń
Section titled “0. Grupy poleceń”- DDL (definicja struktury):
CREATE,ALTER,DROP,TRUNCATE - DML (modyfikacja danych):
INSERT,UPDATE,DELETE - DQL (zapytania):
SELECT - DCL (uprawnienia):
GRANT,REVOKE - TCL (transakcje):
COMMIT,ROLLBACK
Dane w MySQL trzyma się w bazach (katalogi w podkatalogu data). Domyślny silnik to InnoDB (obsługuje klucze obce i transakcje).
1. SELECT, kolejność klauzul
Section titled “1. SELECT, kolejność klauzul”SELECT kolumnyFROM tabelaWHERE warunek_wierszyGROUP BY kolumnyHAVING warunek_grupORDER BY kolumny [ASC|DESC]LIMIT [offset,] ile;WHEREfiltruje wiersze (przed grupowaniem),HAVINGfiltruje grupy (poGROUP BY).- Alias kolumny nie działa w
WHERE, działa wSELECT,HAVING,ORDER BY. - Stałe wyrażenie jest poprawne:
SELECT 123+456 FROM tab;zwróci 579 dla każdego wiersza tabeli.
2. WHERE, operatory
Section titled “2. WHERE, operatory”WHERE salary > 1500WHERE salary BETWEEN 1000 AND 2000WHERE name IN ('sales', 'finance')WHERE id NOT IN (1, 10, 20)-- % dowolny ciąg, _ jeden znakWHERE credit_rating LIKE 'EXCEL%'WHERE country IS NULLWHERE country IS NOT NULL-- AND wiąże mocniej niż ORWHERE a = 1 AND b = 2 OR c = 3LIKEdomyślnie nie rozróżnia wielkości liter. Aby rozróżniać, dodajBINARY:LIKE BINARY 'ExCeLLeNT'.- Daty zawsze w formacie
RRRR-MM-DD('1992-01-01'). Inny format może dać błędny wynik bez ostrzeżenia.
3. ORDER BY, LIMIT, DISTINCT
Section titled “3. ORDER BY, LIMIT, DISTINCT”SELECT * FROM emp ORDER BY salary DESC, last_name ASC;-- pierwsze 10SELECT * FROM emp LIMIT 10;-- pomiń 20, weź 10SELECT * FROM emp LIMIT 20, 10;-- usuwa duplikaty (UNIQUE to synonim)SELECT DISTINCT dept_id FROM emp;4. Aliasy
Section titled “4. Aliasy”SELECT first_name AS Imie, last_name AS "Nazwisko", start_date AS "Data zatrudnienia"FROM emp E;ASjest opcjonalne. Warto je pisać, żeby zgubiony przecinek nie utworzył przypadkowego aliasu.- Cudzysłów potrzebny tylko gdy alias ma spację. Alias tabeli (
emp E) to identyfikator, bez cudzysłowu.
5. NULL
Section titled “5. NULL”-- nie używaj = NULLWHERE country IS NULLSELECT IFNULL(state, '-'), IFNULL(country, '?') FROM emp;NULL to wartość nieznana. Porównania z NULL dają NULL (nie TRUE), dlatego IS NULL zamiast = NULL.
6. Funkcje agregujące, GROUP BY, HAVING
Section titled “6. Funkcje agregujące, GROUP BY, HAVING”SELECT MAX(salary), MIN(salary), AVG(salary), SUM(salary), COUNT(salary) FROM emp;
SELECT dept_id, SUM(salary), AVG(salary)FROM empWHERE salary > 800GROUP BY dept_idHAVING SUM(salary) > 5000ORDER BY dept_id;- Agregat bez
GROUP BYzwraca dokładnie jeden wiersz (pusta tabela: jeden wiersz z NULL). COUNT(*)liczy wszystkie wiersze,COUNT(kolumna)pomija NULL w tej kolumnie.- W
SELECTzGROUP BYmogą być tylko: funkcje agregujące, kolumny zGROUP BY, wyrażenia stałe. AVG(cena+cena)jest poprawne (jeden argument),AVG(cena, cena)nie.
7. Złączenia tabel
Section titled “7. Złączenia tabel”-- Iloczyn kartezjański (cross join): brak warunku, kazdy z kazdym-- |emp| * |dept| wierszySELECT * FROM emp, dept;
-- Inner / equi join: warunek laczenia (PK = FK)SELECT e.first_name, d.nameFROM emp e JOIN dept d ON e.dept_id = d.id;-- starszy zapis: FROM emp e, dept d WHERE e.dept_id = d.id;
-- Self join: tabela z sama soba (np. pracownik i jego szef)SELECT e.last_name, s.last_name AS szefFROM emp e JOIN emp s ON e.manager_id = s.id;
-- Outer join: zachowuje wiersze bez dopasowania (uzupelnia NULL-ami)SELECT d.name, e.last_nameFROM dept d LEFT OUTER JOIN emp e ON d.id = e.dept_id;
SELECT d.name, e.last_nameFROM emp e RIGHT OUTER JOIN dept d ON d.id = e.dept_id;- Iloczyn kartezjański dla 15, 25, 16 rekordów:
15 * 25 * 16 = 6000. FULL OUTER JOINnie jest wspierany w MySQL (emuluje się go przezLEFT UNION RIGHT).
8. UNION, UNION ALL
Section titled “8. UNION, UNION ALL”SELECT first_name FROM empUNIONSELECT name FROM dept;UNIONłączy wyniki i usuwa duplikaty,UNION ALLzostawia duplikaty (szybsze).- Liczba i typy kolumn w łączonych zapytaniach muszą się zgadzać. Nagłówki bierze się z pierwszego
SELECT.
9. Podzapytania
Section titled “9. Podzapytania”-- jeden rekordSELECT * FROM emp WHERE salary > (SELECT AVG(salary) FROM emp);
-- wiele rekordów: IN / ANY / ALLSELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE region_id = 5);SELECT * FROM emp WHERE salary > ALL (SELECT salary FROM emp WHERE last_name LIKE 'S%');SELECT * FROM emp WHERE salary > ANY (SELECT salary FROM emp WHERE dept_id = 41);
-- skorelowane: EXISTS / NOT EXISTSSELECT id, first_name FROM emp EWHERE EXISTS (SELECT 1 FROM ord O WHERE O.sales_rep_id = E.id);
-- podzapytanie w FROM (widok dynamiczny)SELECT t.dept_id, t.sredniaFROM (SELECT dept_id, AVG(salary) AS srednia FROM emp GROUP BY dept_id) tWHERE t.srednia > 1500;> ALLto większe od wszystkich (czyli od maksimum),> ANYto większe od któregokolwiek (od minimum).EXISTSzwraca prawdę, gdy podzapytanie zwróci choć jeden wiersz.
10. Funkcje tekstowe
Section titled “10. Funkcje tekstowe”-- sklejanie (bez spacji po CONCAT)CONCAT('a', 'b')-- podciag od pozycji 2, dlugosc 3SUBSTR(last_name, 2, 3)-- dlugoscLENGTH(first_name)UPPER(s), LOWER(s)-- dopelnianie do dlugosciLPAD(s, 20, '*'), RPAD(s, 20, '.')LTRIM(s), RTRIM(s)-- BOTH | LEADING | TRAILINGTRIM(BOTH '*' FROM '***xyz***')11. Funkcje liczbowe
Section titled “11. Funkcje liczbowe”-- 2ROUND(1.56)-- 1.2ROUND(1.234, 1)-- 1FLOOR(1.56)-- 2CEIL(1.56)-- -2FLOOR(-1.56)-- -2ROUND(-1.56)-- obcina bez zaokraglaniaTRUNCATE(1.567, 1)MOD(10, 3), ABS(-5), POWER(2, 3), SQRT(9)12. Funkcje daty i czasu
Section titled “12. Funkcje daty i czasu”-- data i czasNOW(), CURRENT_TIMESTAMP, SYSDATE()-- sama dataCURDATE(), CURRENT_DATE()-- formatowanie wg maskiDATE_FORMAT(start_date, '%d-%m-%Y')-- tekst na dateSTR_TO_DATE('31-12-2023', '%d-%m-%Y')DATE_ADD(SYSDATE(), INTERVAL 5 DAY)DATE_SUB(NOW(), INTERVAL 1 MONTH)YEAR(d), MONTH(d), DAY(d)Maski: %Y rok 4 cyfry, %m miesiac, %d dzien, %H:%i:%s czas, %W nazwa dnia, %M nazwa miesiaca.
13. INSERT
Section titled “13. INSERT”-- wszystkie kolumny w kolejnosci tabeliINSERT INTO emp VALUES (102, 'Kowalski', '2004-05-01', ...);
-- wybrane kolumny (reszta dostaje DEFAULT lub NULL, AUTO_INCREMENT sam)INSERT INTO emp (id, last_name, start_date) VALUES (102, 'Kowalski', '2004-05-01');
-- wiele wierszy narazINSERT INTO test VALUES (1), (2), (3);
-- skladnia SETINSERT INTO emp SET first_name='Tomasz', last_name='Wisniewski';
-- z innej tabeliINSERT INTO emp2 (imie, nazwisko) SELECT first_name, last_name FROM emp WHERE salary > 1500;
-- ignorowanie duplikatow kluczaINSERT IGNORE INTO test VALUES (1), (1), (2);14. UPDATE
Section titled “14. UPDATE”UPDATE empSET salary = salary * 1.1WHERE dept_id IN (100, 101);Bez WHERE zmodyfikuje wszystkie wiersze. UPDATE jest transakcyjny (przy InnoDB).
15. DELETE, TRUNCATE
Section titled “15. DELETE, TRUNCATE”DELETE FROM emp WHERE id = 100;-- usuwa wszystkie wiersze (mozna cofnac w transakcji)DELETE FROM emp;-- szybkie czyszczenie, resetuje AUTO_INCREMENTTRUNCATE TABLE emp;- Próba usunięcia wiersza nadrzędnego, do którego istnieje odwołanie FK, daje błąd 1451. Można to obejść klauzulą
ON DELETE CASCADEprzy definicji klucza obcego.
16. CREATE TABLE i typy
Section titled “16. CREATE TABLE i typy”CREATE TABLE studenci ( stud_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, imie VARCHAR(20) NOT NULL, nazwisko VARCHAR(30) NOT NULL, zarobki DECIMAL(11,2), plec ENUM('M','K') NOT NULL, data_ur DATE) ENGINE = InnoDB;Typy: INT/INTEGER, DECIMAL(p,s), VARCHAR(n) (długość wymagana), CHAR(n), DATE, DATETIME, ENUM(...) (jedna wartość ze zbioru), SET(...) (wiele wartości ze zbioru).
CREATE TABLE IF NOT EXISTS ...nie zgłosi błędu gdy tabela istnieje.ENGINE = InnoDBjest obowiązkowe przy kluczach obcych.
17. Ograniczenia (constraints)
Section titled “17. Ograniczenia (constraints)”| Ograniczenie | Działanie |
|---|---|
NOT NULL |
kolumna nie może być pusta |
PRIMARY KEY |
unikalne i różne od NULL, jedno na tabelę |
UNIQUE |
unikalne, dopuszcza NULL, może być wiele |
FOREIGN KEY |
integralność referencyjna |
DEFAULT v |
wartość domyślna |
CHECK (war) |
warunek (w starszym MySQL ignorowany) |
ENUM / SET |
wartości ze zdefiniowanego zbioru |
-- definicja kolumnowaprac_id INTEGER PRIMARY KEY,pesel INTEGER NOT NULL UNIQUE,
-- definicja tablicowa (wymagana dla kluczy zlozonych)PRIMARY KEY (osoba_id),UNIQUE (imie, nazwisko, pseudo)PRIMARY KEY vs UNIQUE: klucz główny nie dopuszcza NULL i jest tylko jeden, UNIQUE dopuszcza NULL i może być wiele. Jedna kolumna może mieć kilka ograniczeń (np. FOREIGN KEY + UNIQUE + NOT NULL).
18. Klucze obce
Section titled “18. Klucze obce”-- A) w CREATE TABLE (najpierw nadrzedna, potem podrzedna)CREATE TABLE pracownicy ( prac_id INTEGER PRIMARY KEY AUTO_INCREMENT, miasto_id INTEGER, CONSTRAINT pracownicy_miasta_id_fk FOREIGN KEY (miasto_id) REFERENCES miasta (miasto_id)) ENGINE = InnoDB;
-- B) przez ALTER TABLE (kolejnosc tabel nieistotna)ALTER TABLE pracownicy ADD CONSTRAINT pracownicy_miasta_id_fk FOREIGN KEY (miasto_id) REFERENCES miasta (miasto_id);- Kolumna FK musi być tego samego typu co kolumna nadrzędna.
- FK może dopuszczać NULL i może być
UNIQUE(relacja 1:1). Kolumna może być jednocześnie PK i FK. - Nazwa ograniczenia (
CONSTRAINT nazwa) jest opcjonalna. Konwencja:tabela_kolumna_fk. - Kolejność tworzenia (FK w CREATE TABLE): nadrzędna, potem podrzędna. Kasowanie: odwrotnie, najpierw podrzędna.
19. AUTO_INCREMENT
Section titled “19. AUTO_INCREMENT”-- id samoINSERT INTO region (name) VALUES ('Dolnoslaskie');- Wstawia max dotychczasowego id + 1 (liczy się max, nie liczba wierszy).
- Nie odzyskuje skasowanych numerów.
20. Widoki (VIEW)
Section titled “20. Widoki (VIEW)”CREATE OR REPLACE VIEW emp_dept_view ASSELECT e.first_name, e.last_name, d.nameFROM emp e JOIN dept d ON e.dept_id = d.id;
SELECT * FROM emp_dept_view;- Widok przechowuje tylko definicję, dane pobiera na bieżąco.
INSERT/UPDATE/DELETEna widoku są czasami możliwe (tylko proste, modyfikowalne widoki, bez agregacji,GROUP BY,DISTINCT, złączeń wielu tabel). W praktyce głównie do odczytu.
21. Indeksy
Section titled “21. Indeksy”CREATE TABLE pracownicy ( -- indeks automatyczny prac_id INTEGER PRIMARY KEY, -- UNIQUE to tez indeks pseudo VARCHAR(10) UNIQUE, nazwisko VARCHAR(30), -- INDEX = KEY (synonimy) INDEX (nazwisko), KEY (data_ur)) ENGINE = InnoDB;
CREATE INDEX idx_naz ON pracownicy (nazwisko);- Indeks zakładany automatycznie dla
PRIMARY KEYiUNIQUE. Można na dowolnym typie kolumny, na jednej lub wielu. - Koszt: zajmuje miejsce, spowalnia
INSERT/UPDATE/DELETE(przebudowa). Nadmiar szkodzi.
22. ALTER TABLE
Section titled “22. ALTER TABLE”ALTER TABLE prac RENAME TO pracownicy;ALTER TABLE prac ADD COLUMN zarobki DECIMAL(11,2) NOT NULL;-- zmiana typuALTER TABLE prac MODIFY COLUMN imie VARCHAR(40) NOT NULL;-- zmiana nazwy + typuALTER TABLE prac CHANGE COLUMN pseudo ksywka VARCHAR(8);ALTER TABLE prac DROP COLUMN imie2;ALTER TABLE prac ADD PRIMARY KEY (prac_id);ALTER TABLE prac ADD UNIQUE (ksywka);MODIFY zmienia typ kolumny (zachowuje nazwę), CHANGE zmienia też nazwę.
23. DROP
Section titled “23. DROP”DROP TABLE emp;DROP TABLE IF EXISTS child;DROP VIEW emp_dept_view;DROP INDEX idx_naz ON pracownicy;DROP TRIGGER before_update_emp_audit;Kasując tabele połączone FK, najpierw usuwa się podrzędne (child), potem nadrzędne (parent).
24. Procedury składowane
Section titled “24. Procedury składowane”DELIMITER $$CREATE PROCEDURE GetEmpByID (IN emp_ID INT)BEGIN SELECT first_name, last_name FROM emp WHERE id = emp_ID;END $$DELIMITER ;
CALL GetEmpByID(11);DELIMITER $$zmienia separator na czas definicji (bo w ciele są średniki), potem wraca do;.- Parametry:
IN(wejściowy),OUT(wyjściowy),INOUT. Wywołanie przezCALL.
25. Wyzwalacze (triggery)
Section titled “25. Wyzwalacze (triggery)”CREATE TRIGGER trigger_name{BEFORE | AFTER} {INSERT | UPDATE | DELETE}ON table_nameFOR EACH ROWtrigger_body;Przykład audytu zmian:
DELIMITER $$CREATE TRIGGER before_update_emp_auditBEFORE UPDATE ON emp FOR EACH ROWBEGIN INSERT INTO emp_audit(empID, sal_old, sal_new, action) VALUES (OLD.id, OLD.salary, NEW.salary, 'before update');END $$DELIMITER ;- 6 rodzajów: BEFORE/AFTER w połączeniu z INSERT/UPDATE/DELETE.
NEW.kolumnato wartość nowa (INSERT, UPDATE),OLD.kolumnato wartość stara (UPDATE, DELETE).FOR EACH ROWznaczy, że wyzwalacz uruchamia się dla każdego zmienianego wiersza.
Pułapki egzaminacyjne (szybkie odpowiedzi)
Section titled “Pułapki egzaminacyjne (szybkie odpowiedzi)”SELECT * FROM t1, t2, t3;przy 15, 25, 16 rekordach: 6000 wierszy.- Klucz główny może być liczbowy lub znakowy.
SELECT 123+456 FROM tab;jest poprawne (579 na wiersz).VARCHARbez długości jest niepoprawny.- Alias tabeli nie w cudzysłowie. Alias kolumny w cudzysłowie tylko gdy ma spację.
- Kopiowanie tabeli: CREATE TABLE … AS SELECT lub LIKE (nie ma DUPLICATE TABLE).
- Klucz obcy musi mieć ten sam typ co kolumna nadrzędna.
- Kolejność tworzenia (FK w CREATE): najpierw nadrzędna, potem podrzędna. Przy ALTER nieistotna.
- Kolejność kasowania: najpierw podrzędna, potem nadrzędna.
- Klucz obcy z NULL może być UNIQUE.
- Nazwa ograniczenia jest opcjonalna.
- AUTO_INCREMENT wstawia max + 1 i nie odzyskuje skasowanych numerów.
AVG(kol)bez GROUP BY zwraca zawsze jeden wiersz.- Poprawny agregat: AVG(cena+cena). Błędne: AVG(cena, cena).
AVG(100)+MIN(50)= 150.AVG(salary)-SUM(salary)przy dodatnich zarobkach: ujemny.- Indeks: kolumna dowolnego typu, INDEX = KEY, automatyczny dla PK i UNIQUE.
- DML na widoku: czasami możliwy.
- Kolumna może być naraz kluczem głównym i obcym: prawda.
- Każda tabela relacyjna może (nie musi) mieć klucz główny.
> ALLto większe od maksimum,> ANYto większe od minimum.UNIONusuwa duplikaty,UNION ALLje zostawia.LIKEbezBINARYnie rozróżnia wielkości liter. Daty w formacieRRRR-MM-DD.MODIFYzmienia typ kolumny,CHANGEzmienia typ i nazwę.FULL OUTER JOINnie istnieje w MySQL.- Wyzwalacze: 6 rodzajów (BEFORE/AFTER × INSERT/UPDATE/DELETE),
NEW.iOLD.,FOR EACH ROW.