SQL-команды разделяются на три основные категории:
DDL (Data Definition Language) — язык определения данных:
DML (Data Manipulation Language) — язык манипулирования данными:
DCL (Data Control Language) — язык управления доступом:
MySQL 8.1CREATE TABLE students ( student_id INT PRIMARY KEY, name VARCHAR(100), age INT );
MySQL 8.1CREATE TABLE enrollments ( enrollment_id INT PRIMARY KEY, student_id INT, course_id INT, FOREIGN KEY (student_id) REFERENCES students(student_id), FOREIGN KEY (course_id) REFERENCES courses(course_id) );
До нормализации:
После нормализации:
Таблица Students
Таблица Courses
Таблица Enrollments
Подробный разбор темы с примерами — в статье «Нормализация баз данных: нормальные формы простыми словами».
INNER JOIN:
Возвращает записи, у которых есть соответствующие записи в обеих таблицах.
LEFT JOIN (или LEFT OUTER JOIN):
Возвращает все записи из левой таблицы и соответствующие записи из правой таблицы. Если соответствия нет, возвращает NULL для правой таблицы.
RIGHT JOIN (или RIGHT OUTER JOIN):
Возвращает все записи из правой таблицы и соответствующие записи из левой таблицы. Если соответствия нет, возвращает NULL для левой таблицы.
FULL OUTER JOIN:
Возвращает все записи, когда есть соответствие в одной из таблиц.
CROSS JOIN:
Выполняет декартово произведение двух таблиц, объединяя каждую строку первой таблицы с каждой строкой второй таблицы.
MySQL 8.1SELECT name FROM employees WHERE department_id = (SELECT id FROM departments WHERE name = 'IT');
MySQL 8.1SELECT sub.department, COUNT(*) FROM ( SELECT department_id AS department FROM employees ) sub GROUP BY sub.department;
Использовать ключевое слово DISTINCT в операторе SELECT, чтобы вернуть только уникальные записи.
Пример:
MySQL 8.1SELECT DISTINCT position FROM employees;
Пример:
MySQL 8.1SELECT department_id, COUNT(*) FROM employees WHERE salary > 50000 GROUP BY department_id;
Пример:
MySQL 8.1SELECT department_id, COUNT(*) AS num_employees FROM employees GROUP BY department_id HAVING COUNT(*) > 5;
Индексы ускоряют операции чтения, но могут замедлять операции записи (вставка, обновление, удаление), так как индексы нужно обновлять при изменении данных.
MySQL 8.1-- Создание индекса на столбце name таблицы employees CREATE INDEX idx_employees_name ON employees(name);
Пример:
MySQL 8.1DELETE FROM employees WHERE salary < 30000;
Пример:
MySQL 8.1TRUNCATE TABLE employees;
Подробный разбор темы с примерами — в статье «TRUNCATE, DELETE и DROP: в чём разница и что выбрать».
Атомарность (Atomicity):
Согласованность (Consistency):
Изоляция (Isolation):
Долговечность (Durability):
Подробный разбор темы с примерами — в статье «Что такое ACID: 4 свойства транзакций простыми словами».
MySQL 8.1CREATE TRIGGER trg_after_insert_employee AFTER INSERT ON employees FOR EACH ROW BEGIN INSERT INTO audit_log (employee_id, action, action_time) VALUES (NEW.id, 'INSERT', NOW()); END;
MySQL 8.1CREATE VIEW employee_details AS SELECT e.id, e.name, d.name AS department, e.salary FROM employees e JOIN departments d ON e.department_id = d.id;
MySQL 8.1SELECT * FROM employee_details WHERE salary > 50000;
Оператор LIKE используется в условиях WHERE для поиска строк, соответствующих определенному шаблону. В шаблонах используются подстановочные символы:
MySQL 8.1SELECT * FROM employees WHERE name LIKE 'А%';
MySQL 8.1SELECT * FROM employees WHERE name LIKE '%e';
MySQL 8.1SELECT * FROM employees WHERE name LIKE '_а%';
Агрегатные функции выполняют вычисления над набором значений и возвращают одно значение. Они часто используются в сочетании с оператором GROUP BY.
MySQL 8.1SELECT COUNT(*) FROM employees;
MySQL 8.1SELECT department_id, AVG(salary) AS average_salary FROM employees GROUP BY department_id;
MySQL 8.1SELECT MAX(salary) FROM employees;
MySQL 8.1SELECT SUM(amount) FROM sales WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31';
Синтаксис
MySQL 8.1SELECT column_list FROM table1 UNION SELECT column_list FROM table2;
Синтаксис
MySQL 8.1SELECT column_list FROM table1 UNION ALL SELECT column_list FROM table2;
Пример хранимой процедуры:
MySQL 8.1CREATE PROCEDURE GetEmployeeByID(IN emp_id INT) BEGIN SELECT * FROM employees WHERE id = emp_id; END;
Вызов процедуры:
MySQL 8.1CALL GetEmployeeByID(1);
Пример функции:
MySQL 8.1CREATE FUNCTION GetEmployeeSalary(emp_id INT) RETURNS DECIMAL(10,2) BEGIN DECLARE salary DECIMAL(10,2); SELECT e.salary INTO salary FROM employees e WHERE e.id = emp_id; RETURN salary; END;
Использование функции:
MySQL 8.1SELECT name, GetEmployeeSalary(id) FROM employees;
Использовать индексы:
Избегать SELECT *:
Оптимизировать условия JOIN и WHERE:
Использовать ограничения результатов (LIMIT):
Избегать подзапросов, где возможны соединения:
Кеширование часто используемых данных:
Профилирование и анализ запросов:
Подробный разбор темы с примерами — в статье «Оптимизация SQL-запросов: 10 способов ускорить медленный запрос».
Ограничения обеспечивают целостность и надежность данных в таблице, определяя правила для данных в столбцах.
Виды ограничений:
NOT NULL:
Пример:
MySQL 8.1CREATE TABLE products ( product_id INT PRIMARY KEY, name VARCHAR(100) NOT NULL );
UNIQUE:
Пример:
MySQL 8.1CREATE TABLE users ( user_id INT PRIMARY KEY, email VARCHAR(100) UNIQUE );
PRIMARY KEY:
FOREIGN KEY:
Пример:
MySQL 8.1CREATE TABLE orders ( order_id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(user_id) );
CHECK:
Пример:
MySQL 8.1CREATE TABLE employees ( id INT PRIMARY KEY, age INT CHECK (age >= 18) );
DEFAULT:
MySQL 8.1CREATE TABLE tasks ( task_id INT PRIMARY KEY, status VARCHAR(20) DEFAULT 'Pending' );
1. Параметризированные запросы (Prepared Statements):
Пример (на языке Java с использованием JDBC)
MySQL 8.1String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement stmt = connection.prepareStatement(sql); stmt.setString(1, username); stmt.setString(2, password); ResultSet rs = stmt.executeQuery();
2. Использование ORM (Object-Relational Mapping):
3. Проверка и фильтрация вводимых данных:
4. Ограничение прав доступа:
5. Использование хранимых процедур:
Пример:
MySQL 8.1SELECT * FROM employees e INNER JOIN departments d ON e.department_id = d.id;
LEFT OUTER JOIN (LEFT JOIN):
Пример:
MySQL 8.1SELECT * FROM employees e LEFT JOIN departments d ON e.department_id = d.id;
RIGHT OUTER JOIN (RIGHT JOIN):
Пример:
MySQL 8.1SELECT * FROM employees e RIGHT JOIN departments d ON e.department_id = d.id;
FULL OUTER JOIN (FULL JOIN):
MySQL 8.1SELECT * FROM employees e FULL OUTER JOIN departments d ON e.department_id = d.id;
Для проверки на NULL используется оператор IS NULL или IS NOT NULL.
MySQL 8.1-- Поиск записей с неизвестной датой рождения SELECT * FROM employees WHERE birth_date IS NULL; -- Поиск записей с известной датой рождения SELECT * FROM employees WHERE birth_date IS NOT NULL;
COALESCE
Возвращает первый элемент списка, не равный NULL
MySQL 8.1COALESCE(val1[, val2, ...., val_n])
ISNULL
Возвращает 1 или 0 в зависимости от того, равно ли выражение NULL
MySQL 8.1ISNULL(value)
IFNULL
Возвращает значение, переданное 1-ым аргументом, если оно не равно NULL. В противном случае возвращает значение, переданное вторым аргументом.
MySQL 8.1IFNULL(value, alternative_value)
Подробный разбор темы с примерами — в статье «COALESCE в SQL: замена NULL и связка с NULLIF».
Оператор CASE используется для реализации условной логики в SQL-запросах. Он позволяет возвращать значения на основе условий, подобно оператору IF-ELSE.
MySQL 8.1CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... ELSE default_result END
MySQL 8.1SELECT name, salary, CASE WHEN salary >= 80000 THEN 'Высокая' WHEN salary >= 50000 THEN 'Средняя' ELSE 'Низкая' END AS salary_category FROM employees;
MySQL 8.1BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE account_id = 1; UPDATE accounts SET balance = balance + 100 WHERE account_id = 2; COMMIT;
MySQL 8.1BEGIN TRANSACTION; DELETE FROM orders WHERE order_date < '2022-01-01'; -- Если передумали ROLLBACK;
Память и производительность:
Применение:
Пример:
MySQL 8.1CREATE TABLE products ( code CHAR(10), -- Код товара фиксированной длины name VARCHAR(100) -- Название товара переменной длины );
Вставка данных:
MySQL 8.1INSERT INTO products (code, name) VALUES ('A123', 'Ноутбук Lenovo');
В столбце code значение будет дополненно пробелами до 10 символов.
MySQL 8.1CREATE TEMPORARY TABLE TempTable ( id INT, name VARCHAR(100) );
MySQL 8.1-- Вставка данных во временную таблицу INSERT INTO #TempTable (id, name) VALUES (1, 'Иван'), (2, 'Петр'); -- Выборка данных из временной таблицы SELECT * FROM #TempTable; -- Временная таблица будет автоматически удалена после завершения сессии
Подробное объяснение работы оконных функций есть в нашем курсе.
Подробный разбор темы с примерами — в статье «ROW_NUMBER, RANK и DENSE_RANK: отличия на одном примере».
Он улучшает читаемость и структуру сложных запросов.
MySQL 8.1WITH CTEName (column1, column2, ...) AS ( -- Ваш запрос SELECT ... ) SELECT * FROM CTEName;
Подробное объяснение работы CTE в нашем курсе.
Подробный разбор темы с примерами — в статье «CTE в SQL: что такое Common Table Expression — с рекурсией».
Для этого используется команда DROP TABLE, которая удаляет таблицу и все ее данные из базы данных.
MySQL 8.1DROP TABLE table_name;
Он обеспечивает ссылочную целостность, гарантируя, что значения в столбце внешнего ключа соответствуют существующим значениям в связанной таблице.
Ограничивается вставка некорректных данных Невозможно вставить значение в столбец внешнего ключа, если такого значения нет в связанной таблице.
Ограничивается удаление связанных записей Невозможно удалить запись из родительской таблицы, если на нее ссылаются записи в дочерней таблице, без дополнительных действий.
MySQL 8.1CREATE TABLE Employees ( EmployeeID INT PRIMARY KEY, Name VARCHAR(100), DepartmentID INT, FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID) );
Для этого используется команда ALTER TABLE с оператором ADD для добавления нового столбца в таблицу.
MySQL 8.1ALTER TABLE table_name ADD column_name data_type [constraints];
Допустим, у нас есть таблица employees, и мы хотим добавить столбец email типа VARCHAR(255).
MySQL 8.1ALTER TABLE employees ADD email VARCHAR(255);
Добавление столбца с ограничением NOT NULL и значением по умолчанию:
MySQL 8.1ALTER TABLE employees ADD date_of_birth DATE NOT NULL DEFAULT '1900-01-01';
Особенность
При добавлении столбца с ограничением NOT NULL,
если в таблице уже есть данные, необходимо указать значение по умолчанию, иначе будет ошибка.
Есть таблица employees и departments.
MySQL 8.1SELECT e.name, e.salary FROM employees e WHERE e.salary > ( SELECT AVG(salary) FROM employees WHERE department_id = e.department_id );
Больше информации о коррелированных подзапросах в нашем курсе.
MySQL 8.1DELETE FROM table_name [WHERE condition];
MySQL 8.1TRUNCATE TABLE table_name;
MySQL 8.1DROP TABLE table_name;
Подробный разбор темы с примерами — в статье «TRUNCATE, DELETE и DROP: в чём разница и что выбрать».
Чтобы получить список сотрудников и их менеджеров:
MySQL 8.1SELECT e.name AS Employee, m.name AS Manager FROM Employee e LEFT JOIN Employee m ON e.managerId = m.employeeId;
В этом запросе мы соединяем таблицу Employee с самой собой, чтобы сопоставить каждого сотрудника с его менеджером.
Резервное копирование и восстановление базы данных — это критически важные операции для обеспечения сохранности данных и возможности их восстановления в случае сбоя или потери.
Методы резервного копирования зависят от используемой системы управления базами данных (СУБД).
Ниже приведены примеры для некоторых популярных СУБД.
Резервное копирование с помощью утилиты mysqldump:
MySQL 8.1mysqldump -u username -p mydatabase > backup.sql
Резервное копирование с помощью утилиты pg_dump:
MySQL 8.1pg_dump -U username mydatabase > backup.sql
Восстановление базы данных из файла backup.sql:
MySQL 8.1mysql -u username -p mydatabase < backup.sql
Восстановление базы данных с помощью утилиты psql:
MySQL 8.1psql -U username mydatabase < backup.sql
Отношения многие-ко-многим в реляционных базах данных возникают, когда одна запись в первой таблице может соответствовать нескольким записям во второй таблице, и наоборот.
В SQL такие отношения реализуются с помощью промежуточной таблицы (также известной как таблица связей или соединительная таблица), которая связывает две основные таблицы посредством внешних ключей.
Представим сценарий с таблицами Student (Студенты) и Course (Курсы), где один студент может записаться на несколько курсов, и один курс может быть пройден несколькими студентами.
MySQL 8.1CREATE TABLE Student ( StudentID INT PRIMARY KEY, Name VARCHAR(100) );
MySQL 8.1CREATE TABLE Course ( CourseID INT PRIMARY KEY, Title VARCHAR(100) );
MySQL 8.1CREATE TABLE StudentCourse ( StudentID INT, CourseID INT, PRIMARY KEY (StudentID, CourseID), FOREIGN KEY (StudentID) REFERENCES Student(StudentID), FOREIGN KEY (CourseID) REFERENCES Course(CourseID) );
В результате:
Команды GRANT и REVOKE в SQL используются для управления правами доступа пользователей к объектам базы данных. Они позволяют предоставлять или отзывать определенные привилегии у пользователей или ролей, обеспечивая безопасность и контроль над тем, кто и какие действия может выполнять в базе данных.
Команда GRANT предоставляет пользователям или ролям определенные привилегии на объекты базы данных.
MySQL 8.1GRANT privileges ON object TO user [WITH GRANT OPTION];
Пример:
Предоставить пользователю user1 право выбора данных из таблицы employees можно следующим способом:
MySQL 8.1GRANT SELECT ON employees TO user1;
Команда REVOKE отзывает ранее предоставленные привилегии у пользователей или ролей.
MySQL 8.1REVOKE privileges ON object FROM user;
Пример:
Отозвать у пользователя user1 право выбора данных из таблицы employees:
MySQL 8.1REVOKE SELECT ON employees FROM user1;
Хеш-функции в SQL используются для преобразования входных данных произвольной длины в фиксированную строку определенной длины. Это преобразование называется хешированием, и оно широко применяется для обеспечения безопасности, целостности данных и оптимизации операций сравнения и поиска.
Хеш-функции позволяют определить, были ли данные изменены. Создавая хеш от исходных данных и сравнивая его с текущим хешем, можно обнаружить изменения.
Хеш-значения могут использоваться для быстрого сравнения больших объемов данных или создания индексов для ускорения поиска.
Хеширование помогает генерировать уникальные идентификаторы для записей на основе их содержимого.
MySQL 8.1-- Создаем таблицу пользователей CREATE TABLE Users ( UserID INT PRIMARY KEY, Username VARCHAR(50) NOT NULL, PasswordHash VARBINARY(512) NOT NULL ); -- При добавлении нового пользователя хешируем пароль INSERT INTO Users (UserID, Username, PasswordHash) VALUES (1, 'user1', HASHBYTES('SHA2_512', 'password123')); -- Проверяем соответствие введенного пароля хешу в базе данных SELECT UserID FROM Users WHERE Username = 'user1' AND PasswordHash = HASHBYTES('SHA2_512', 'password123');
Храните хеши в бинарном формате (VARBINARY) вместо строкового (VARCHAR) для сохранения точности и экономии места.
Помните, что хеширование является односторонней функцией; исходные данные невозможно восстановить из хеша.
Триггер активируется автоматически в ответ на заданное событие (например, добавление новой записи в таблицу).
Внутри триггера можно обращаться к старым и новым значениям данных через специальные псевдотаблицы: OLD и NEW.
Есть таблица Employees, и нужно автоматически сохранять историю изменений зарплат сотрудников в таблицу SalaryHistory при обновлении данных.
Создание таблиц:
MySQL 8.1-- Таблица сотрудников CREATE TABLE Employees ( EmployeeID INT PRIMARY KEY, Name VARCHAR(100), Salary DECIMAL(10, 2) ); -- Таблица истории зарплат CREATE TABLE SalaryHistory ( EmployeeID INT, OldSalary DECIMAL(10, 2), NewSalary DECIMAL(10, 2), ChangeDate DATETIME DEFAULT CURRENT_TIMESTAMP );
Создание триггера:
MySQL 8.1DELIMITER $$ CREATE TRIGGER trg_AfterSalaryUpdate AFTER UPDATE ON Employees FOR EACH ROW BEGIN IF OLD.Salary <> NEW.Salary THEN INSERT INTO SalaryHistory (EmployeeID, OldSalary, NewSalary) VALUES (NEW.EmployeeID, OLD.Salary, NEW.Salary); END IF; END$$ DELIMITER ;