🔥 7 ОШИБОК В SQL, КОТОРЫЕ МОГУТ СТОИТЬ КАРЬЕРЫ
SQL — это не просто язык запросов, а мощный инструмент управления данными. Но если им пользоваться неправильно, база может тормозить, данные потеряются, а коллеги будут недовольны. Разберем частые ошибки.
1️⃣ Использовать SELECT * в продакшене
⚠️ Почему это плохо?
🔹 Забирает всю таблицу, даже если нужны 2-3 колонки
🔹 Ломает код при изменении структуры таблицы
🔹 Усложняет работу оптимизатора запросов
✅ Как правильно?
Выбираем только нужные столбцы:
Если нужно получить все столбцы динамически — лучше заранее уточнить их в коде приложения.
Гайд по команде тут
2️⃣ Игнорировать индексы на больших таблицах
⚠️ Почему это плохо?
🔹 Запросы без индексов работают в десятки раз медленнее
🔹 БД вынуждена сканировать всю таблицу
🔹 Производительность падает на глазах
✅ Как правильно?
Добавляем индекс на часто используемые столбцы (например, при фильтрации по salary):
💡 Но не переусердствуй! Лишние индексы замедляют INSERT и UPDATE.
Пост про индексы тут
3️⃣ Хранить пароли в открытом виде
⚠️ Почему это плохо?
🔹Любая утечка данных = утечка всех паролей пользователей
🔹 Это критическая уязвимость
✅ Как правильно?
Пароли всегда хэшируются перед сохранением. Никогда не храни их в открытом виде!
💡 Лучше использовать bcrypt или argon2, так как они более надёжны, чем SHA2.
4️⃣ Забывать про транзакции при изменении данных
⚠️ Почему это плохо?
🔹 Если процесс прервётся, часть данных может остаться несохранённой
🔹 Без ROLLBACK нельзя откатить ошибочные изменения
✅ Как правильно?
Используем транзакции при изменении нескольких таблиц сразу:
💡 Если что-то пошло не так, можно откатить изменения:
Всегда используй COMMIT только тогда, когда уверен, что всё прошло успешно!
5️⃣ Запускать тяжёлые запросы без EXPLAIN
⚠️ Почему это плохо?
🔹 Запрос может внезапно зависнуть на часы
🔹 Может заблокировать всю базу для других пользователей
✅ Как правильно?
Перед выполнением сложного запроса проверяем его план выполнения:
💡 Что важно проверить?
🔹Есть ли Table Scan (это плохо, нужен индекс)
🔹Использует ли SQL ключи и индексы
🔹Какое количество строк реально обрабатывается
6️⃣ Забывать LIMIT при DELETE и UPDATE
⚠️ Почему это плохо?
🔹Если случайно забыть WHERE, можно удалить ВСЕ данные 😱
🔹Один неверный UPDATE может затронуть миллионы строк
✅ Как правильно?
Ограничиваем DELETE и UPDATE, чтобы не изменить слишком много строк:
Пример с лимитами для DELETE:
Пример с лимитами для UPDATE:
💡 В PostgreSQL LIMIT в UPDATE и DELETE не работает. Используй WHERE id IN (SELECT id FROM table LIMIT X).
7️⃣ Злоупотреблять NULL в таблицах
⚠️ Почему это плохо?
🔹NULL ломает агрегатные функции (SUM, AVG)
🔹NULL усложняет условия в JOIN и WHERE
🔹Фильтрация NULL требует специальных проверок (IS NULL, а не =)
✅ Как правильно?
Если NULL можно избежать, используй значения по умолчанию:
💡 Если NULL неизбежен (например, у поля middle_name), всегда пиши COALESCE, чтобы избежать сюрпризов:
Подробнее про COALESCE тут
🔥 Вывод:
Эти ошибки встречаются даже у опытных разработчиков. Теперь ты знаешь, как их избежать!
💬 Какие ошибки ты встречал чаще всего? Пиши в комментариях!
💡Курс от автора канала на Stepik с сертификатом
"DDL в SQL: Определение и управление структурами баз данных"
При переходе по данной ссылке скидка 50%
#Операторы_и_работа_с_данными
#SQL #Оптимизация_SQL #Ошибки_SQL
SQL — это не просто язык запросов, а мощный инструмент управления данными. Но если им пользоваться неправильно, база может тормозить, данные потеряются, а коллеги будут недовольны. Разберем частые ошибки.
1️⃣ Использовать SELECT * в продакшене
⚠️ Почему это плохо?
🔹 Забирает всю таблицу, даже если нужны 2-3 колонки
🔹 Ломает код при изменении структуры таблицы
🔹 Усложняет работу оптимизатора запросов
✅ Как правильно?
Выбираем только нужные столбцы:
SELECT id, name, salary FROM employees;
Если нужно получить все столбцы динамически — лучше заранее уточнить их в коде приложения.
Гайд по команде тут
2️⃣ Игнорировать индексы на больших таблицах
⚠️ Почему это плохо?
🔹 Запросы без индексов работают в десятки раз медленнее
🔹 БД вынуждена сканировать всю таблицу
🔹 Производительность падает на глазах
✅ Как правильно?
Добавляем индекс на часто используемые столбцы (например, при фильтрации по salary):
CREATE INDEX idx_salary ON employees(salary);
💡 Но не переусердствуй! Лишние индексы замедляют INSERT и UPDATE.
Пост про индексы тут
3️⃣ Хранить пароли в открытом виде
⚠️ Почему это плохо?
🔹Любая утечка данных = утечка всех паролей пользователей
🔹 Это критическая уязвимость
✅ Как правильно?
Пароли всегда хэшируются перед сохранением. Никогда не храни их в открытом виде!
INSERT INTO users (username, password)
VALUES ('admin', SHA2('mysecretpass', 256));
💡 Лучше использовать bcrypt или argon2, так как они более надёжны, чем SHA2.
4️⃣ Забывать про транзакции при изменении данных
⚠️ Почему это плохо?
🔹 Если процесс прервётся, часть данных может остаться несохранённой
🔹 Без ROLLBACK нельзя откатить ошибочные изменения
✅ Как правильно?
Используем транзакции при изменении нескольких таблиц сразу:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
💡 Если что-то пошло не так, можно откатить изменения:
ROLLBACK;
Всегда используй COMMIT только тогда, когда уверен, что всё прошло успешно!
5️⃣ Запускать тяжёлые запросы без EXPLAIN
⚠️ Почему это плохо?
🔹 Запрос может внезапно зависнуть на часы
🔹 Может заблокировать всю базу для других пользователей
✅ Как правильно?
Перед выполнением сложного запроса проверяем его план выполнения:
EXPLAIN ANALYZE SELECT * FROM orders WHERE total > 10000;
💡 Что важно проверить?
🔹Есть ли Table Scan (это плохо, нужен индекс)
🔹Использует ли SQL ключи и индексы
🔹Какое количество строк реально обрабатывается
6️⃣ Забывать LIMIT при DELETE и UPDATE
⚠️ Почему это плохо?
🔹Если случайно забыть WHERE, можно удалить ВСЕ данные 😱
🔹Один неверный UPDATE может затронуть миллионы строк
✅ Как правильно?
Ограничиваем DELETE и UPDATE, чтобы не изменить слишком много строк:
Пример с лимитами для DELETE:
DELETE FROM logs WHERE created_at < NOW() - INTERVAL 30 DAY LIMIT 1000;
Пример с лимитами для UPDATE:
UPDATE employees SET salary = salary * 1.1 WHERE department = 'IT' LIMIT 500;
💡 В PostgreSQL LIMIT в UPDATE и DELETE не работает. Используй WHERE id IN (SELECT id FROM table LIMIT X).
7️⃣ Злоупотреблять NULL в таблицах
⚠️ Почему это плохо?
🔹NULL ломает агрегатные функции (SUM, AVG)
🔹NULL усложняет условия в JOIN и WHERE
🔹Фильтрация NULL требует специальных проверок (IS NULL, а не =)
✅ Как правильно?
Если NULL можно избежать, используй значения по умолчанию:
ALTER TABLE users ALTER COLUMN email SET DEFAULT 'не указан';
💡 Если NULL неизбежен (например, у поля middle_name), всегда пиши COALESCE, чтобы избежать сюрпризов:
SELECT COALESCE(middle_name, '—') FROM users;
Подробнее про COALESCE тут
🔥 Вывод:
Эти ошибки встречаются даже у опытных разработчиков. Теперь ты знаешь, как их избежать!
💬 Какие ошибки ты встречал чаще всего? Пиши в комментариях!
💡Курс от автора канала на Stepik с сертификатом
"DDL в SQL: Определение и управление структурами баз данных"
При переходе по данной ссылке скидка 50%
#Операторы_и_работа_с_данными
#SQL #Оптимизация_SQL #Ошибки_SQL
🔥9👍5💯4
🗄 Типы данных в SQL: основы
Типы данных – это фундаментальная часть SQL, влияющая на DML (манипуляции данными) и DDL (структура базы). Они определяют, как хранятся, обрабатываются и извлекаются данные, а неправильный выбор может привести к проблемам с производительностью, точностью и хранением. Тип данных задается при создании таблиц.
1️⃣ Числовые типы
SQL поддерживает два основных вида чисел: целые и дробные.
✔️Целые (INTEGER, SMALLINT, BIGINT) — подходят для хранения чисел без дробной части, например, идентификаторов или количественных данных.
✔️Дробные (DECIMAL, NUMERIC, FLOAT, REAL) — используются для финансовых расчётов и значений с плавающей точкой.
⚠️Важно! FLOAT и REAL могут терять точность из-за особенностей работы с плавающей точкой. Для финансовых операций лучше использовать DECIMAL.
2️⃣ Строковые типы
Строки хранят текстовую информацию, но выбор неправильного типа может повлиять на эффективность.
✔️CHAR(N) — фиксированная длина строки, используется, если длина всегда одинаковая (например, коды стран).
✔️VARCHAR(N) — переменная длина, подходит для большинства текстовых данных.
✔️TEXT или CLOB — для хранения больших текстов (например, описаний или комментариев).
⚠️Важно! TEXT не индексируется напрямую в большинстве СУБД, поэтому его лучше использовать для больших объемов данных, но не для поиска.
3️⃣ Даты и время
Работа со временем в SQL требует понимания разных типов:
✔️DATE — хранит только дату (год, месяц, день).
✔️TIME — хранит только время (часы, минуты, секунды).
✔️TIMESTAMP — объединяет дату и время, может учитывать часовой пояс.
📌 Совет! Для работы с временными зонами, особенно если система поддерживает пользователей из разных регионов, лучше использовать TIMESTAMP WITH TIME ZONE, если это поддерживается в вашей СУБД.
4️⃣ Хранение сложных данных
Современные базы данных позволяют хранить не только числа и строки:
✔️JSON — полезен для структурированных данных, например, в PostgreSQL (jsonb) и MySQL.
✔️XML — используется в корпоративных системах, где требуется строгая структура данных.
📌 Совет! Если часто требуется поиск по JSON, лучше выбирать jsonb в PostgreSQL, так как он индексируется.
Пример создания таблицы с разными типами данных (помним, что создание таблиц в БД это подъязык SQL - DDL)
Разбор типов данных из примера:
✔️ INTEGER — идентификатор, удобен для автоинкремента.
✔️ VARCHAR(255) — хранит строки переменной длины, используется для наименований.
✔️ TEXT — предназначен для больших текстов (например, описание товаров).
✔️ DECIMAL(10,2) — важен для хранения денежных значений, исключает ошибки округления.
✔️ SMALLINT — экономит место, если числовые значения небольшие.
✔️ TIMESTAMP — фиксирует дату и время, можно использовать для аудита изменений.
✔️ BOOLEAN — хранит логические значения, удобен для активных/неактивных элементов.
✔️ JSON — подходит для хранения неструктурированных данных (например, дополнительных характеристик товара).
🔥 Вывод:
Выбор типа данных влияет на размер базы, скорость запросов и корректность вычислений. Ошибки могут привести к избыточному хранению, потерям точности и проблемам с производительностью.
#Операторы_и_работа_с_данными #SQL #Типы_данных
Типы данных – это фундаментальная часть SQL, влияющая на DML (манипуляции данными) и DDL (структура базы). Они определяют, как хранятся, обрабатываются и извлекаются данные, а неправильный выбор может привести к проблемам с производительностью, точностью и хранением. Тип данных задается при создании таблиц.
1️⃣ Числовые типы
SQL поддерживает два основных вида чисел: целые и дробные.
✔️Целые (INTEGER, SMALLINT, BIGINT) — подходят для хранения чисел без дробной части, например, идентификаторов или количественных данных.
✔️Дробные (DECIMAL, NUMERIC, FLOAT, REAL) — используются для финансовых расчётов и значений с плавающей точкой.
⚠️Важно! FLOAT и REAL могут терять точность из-за особенностей работы с плавающей точкой. Для финансовых операций лучше использовать DECIMAL.
2️⃣ Строковые типы
Строки хранят текстовую информацию, но выбор неправильного типа может повлиять на эффективность.
✔️CHAR(N) — фиксированная длина строки, используется, если длина всегда одинаковая (например, коды стран).
✔️VARCHAR(N) — переменная длина, подходит для большинства текстовых данных.
✔️TEXT или CLOB — для хранения больших текстов (например, описаний или комментариев).
⚠️Важно! TEXT не индексируется напрямую в большинстве СУБД, поэтому его лучше использовать для больших объемов данных, но не для поиска.
3️⃣ Даты и время
Работа со временем в SQL требует понимания разных типов:
✔️DATE — хранит только дату (год, месяц, день).
✔️TIME — хранит только время (часы, минуты, секунды).
✔️TIMESTAMP — объединяет дату и время, может учитывать часовой пояс.
📌 Совет! Для работы с временными зонами, особенно если система поддерживает пользователей из разных регионов, лучше использовать TIMESTAMP WITH TIME ZONE, если это поддерживается в вашей СУБД.
4️⃣ Хранение сложных данных
Современные базы данных позволяют хранить не только числа и строки:
✔️JSON — полезен для структурированных данных, например, в PostgreSQL (jsonb) и MySQL.
✔️XML — используется в корпоративных системах, где требуется строгая структура данных.
📌 Совет! Если часто требуется поиск по JSON, лучше выбирать jsonb в PostgreSQL, так как он индексируется.
Пример создания таблицы с разными типами данных (помним, что создание таблиц в БД это подъязык SQL - DDL)
CREATE TABLE products (
product_id INTEGER PRIMARY KEY, -- Целочисленный идентификатор товара
name VARCHAR(255), -- Название товара, переменная строка
denoscription TEXT, -- Описание товара, длинный текст
price DECIMAL(10,2), -- Цена товара с двумя знаками после запятой
stock_quantity SMALLINT, -- Количество товара в наличии, небольшое целое число
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Дата и время создания записи
updated_at TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- Дата и время последнего обновления
is_active BOOLEAN DEFAULT TRUE, -- Флаг активности товара (true/false)
metadata JSON -- Дополнительные данные в JSON-формате (если поддерживается СУБД)
);
Разбор типов данных из примера:
✔️ INTEGER — идентификатор, удобен для автоинкремента.
✔️ VARCHAR(255) — хранит строки переменной длины, используется для наименований.
✔️ TEXT — предназначен для больших текстов (например, описание товаров).
✔️ DECIMAL(10,2) — важен для хранения денежных значений, исключает ошибки округления.
✔️ SMALLINT — экономит место, если числовые значения небольшие.
✔️ TIMESTAMP — фиксирует дату и время, можно использовать для аудита изменений.
✔️ BOOLEAN — хранит логические значения, удобен для активных/неактивных элементов.
✔️ JSON — подходит для хранения неструктурированных данных (например, дополнительных характеристик товара).
🔥 Вывод:
Выбор типа данных влияет на размер базы, скорость запросов и корректность вычислений. Ошибки могут привести к избыточному хранению, потерям точности и проблемам с производительностью.
#Операторы_и_работа_с_данными #SQL #Типы_данных
🔥10👍4💯4
💾 Реляционная модель данных: теория и принципы
Реляционная модель данных – это способ организации и представления данных в виде таблиц (или отношений). Она была предложена Эдгаром Ф. Коддом в 1970 году и стала основой для большинства современных систем управления базами данных (СУБД), таких как MySQL, PostgreSQL, Oracle, SQL Server.
В реляционной модели данные хранятся в виде таблиц (relations), а каждая строка в таблице представляет собой запись (tuple), содержащую значения атрибутов (столбцов).
💾 Основные компоненты реляционной модели:
1️⃣ Отношение (Relation) = Таблица.
Основная структура хранения данных.
Состоит из строк (кортежей) и столбцов (атрибутов).
2️⃣ Атрибут (Attribute) = Столбец таблицы.
Определяет характеристику сущности (например, «Имя», «Цена», «Дата»).
Каждый атрибут имеет свой тип данных (INTEGER, VARCHAR, DATE и т. д.).
3️⃣ Кортеж (Tuple) = Строка в таблице.
Представляет собой один экземпляр сущности (например, одну запись о клиенте).
4️⃣ Домен (Domain) = Диапазон допустимых значений для атрибута.
Например, для атрибута «Возраст» допустимы только целые числа от 0 до 120.
5️⃣ Первичный ключ (Primary Key, PK)
Уникальный идентификатор строки в таблице (например, ID клиента).
6️⃣ Внешний ключ (Foreign Key, FK)
Ссылка на первичный ключ другой таблицы, создающая связь между таблицами.
💾 Принципы реляционной модели
1️⃣ Единообразное представление данных.
Все данные хранятся в виде таблиц, каждая из которых представляет сущность.
2️⃣ Уникальность строк.
Каждая строка (запись) в таблице должна быть уникальной и идентифицироваться первичным ключом.
3️⃣ Отсутствие повторяющихся данных (нормализация).
Повторяющиеся данные должны минимизироваться путём разбиения на связанные таблицы.
4️⃣ Целостность данных.
1. Сущностная целостность – каждый кортеж должен иметь уникальный первичный ключ.
2. Ссылочная целостность – внешний ключ должен ссылаться на существующую запись.
3. Доменная целостность – данные должны соответствовать определённому типу.
5️⃣ Манипуляции с данными через SQL.
Язык SQL используется для выполнения операций над таблицами и управления БД (SELECT, INSERT, UPDATE, DELETE и прочее).
💾 Связи между таблицами
Реляционная модель позволяет строить связи между таблицами:
1️⃣ Один ко многим (1:M)
1. Например, один клиент может иметь несколько заказов.
2. Внешний ключ в таблице заказов ссылается на первичный ключ клиента.
2️⃣ Многие ко многим (M:N)
1. Например, один студент может записаться на несколько курсов, и каждый курс может включать многих студентов.
2. Решается через промежуточную таблицу.
3️⃣ Один к одному (1:1)
Например, один сотрудник может иметь один личный кабинет.
🔹 Преимущества реляционной модели
✅ Гибкость – легко изменять и расширять структуру базы.
✅ Целостность – строгие ограничения предотвращают ошибки и дублирование данных.
✅ Эффективность запросов – возможность использования индексов, оптимизации SQL-запросов.
✅ Универсальность – подходит для большинства бизнес-приложений.
🔹 Недостатки реляционной модели
❌ Производительность на больших объёмах данных – при очень больших данных (миллиарды записей) NoSQL-решения могут быть быстрее.
❌ Сложность масштабирования – горизонтальное масштабирование сложнее, чем в NoSQL.
❌ Жёсткость схемы – структура таблиц фиксирована, что требует продуманного проектирования.
🔥 Вывод
Реляционная модель данных остаётся основным стандартом хранения структурированной информации. Она обеспечивает надёжность, удобство работы и точность данных. Однако, для больших распределённых систем могут использоваться альтернативные модели, такие как NoSQL (документные, графовые, колонночные базы).
💡Курс от автора канала на Stepik с сертификатом
"DDL в SQL: Определение и управление структурами баз данных"
При переходе по данной ссылке скидка 50%
#Реляционные_базы_данных #SQL
Реляционная модель данных – это способ организации и представления данных в виде таблиц (или отношений). Она была предложена Эдгаром Ф. Коддом в 1970 году и стала основой для большинства современных систем управления базами данных (СУБД), таких как MySQL, PostgreSQL, Oracle, SQL Server.
В реляционной модели данные хранятся в виде таблиц (relations), а каждая строка в таблице представляет собой запись (tuple), содержащую значения атрибутов (столбцов).
💾 Основные компоненты реляционной модели:
1️⃣ Отношение (Relation) = Таблица.
Основная структура хранения данных.
Состоит из строк (кортежей) и столбцов (атрибутов).
2️⃣ Атрибут (Attribute) = Столбец таблицы.
Определяет характеристику сущности (например, «Имя», «Цена», «Дата»).
Каждый атрибут имеет свой тип данных (INTEGER, VARCHAR, DATE и т. д.).
3️⃣ Кортеж (Tuple) = Строка в таблице.
Представляет собой один экземпляр сущности (например, одну запись о клиенте).
4️⃣ Домен (Domain) = Диапазон допустимых значений для атрибута.
Например, для атрибута «Возраст» допустимы только целые числа от 0 до 120.
5️⃣ Первичный ключ (Primary Key, PK)
Уникальный идентификатор строки в таблице (например, ID клиента).
6️⃣ Внешний ключ (Foreign Key, FK)
Ссылка на первичный ключ другой таблицы, создающая связь между таблицами.
💾 Принципы реляционной модели
1️⃣ Единообразное представление данных.
Все данные хранятся в виде таблиц, каждая из которых представляет сущность.
2️⃣ Уникальность строк.
Каждая строка (запись) в таблице должна быть уникальной и идентифицироваться первичным ключом.
3️⃣ Отсутствие повторяющихся данных (нормализация).
Повторяющиеся данные должны минимизироваться путём разбиения на связанные таблицы.
4️⃣ Целостность данных.
1. Сущностная целостность – каждый кортеж должен иметь уникальный первичный ключ.
2. Ссылочная целостность – внешний ключ должен ссылаться на существующую запись.
3. Доменная целостность – данные должны соответствовать определённому типу.
5️⃣ Манипуляции с данными через SQL.
Язык SQL используется для выполнения операций над таблицами и управления БД (SELECT, INSERT, UPDATE, DELETE и прочее).
💾 Связи между таблицами
Реляционная модель позволяет строить связи между таблицами:
1️⃣ Один ко многим (1:M)
1. Например, один клиент может иметь несколько заказов.
2. Внешний ключ в таблице заказов ссылается на первичный ключ клиента.
2️⃣ Многие ко многим (M:N)
1. Например, один студент может записаться на несколько курсов, и каждый курс может включать многих студентов.
2. Решается через промежуточную таблицу.
3️⃣ Один к одному (1:1)
Например, один сотрудник может иметь один личный кабинет.
🔹 Преимущества реляционной модели
✅ Гибкость – легко изменять и расширять структуру базы.
✅ Целостность – строгие ограничения предотвращают ошибки и дублирование данных.
✅ Эффективность запросов – возможность использования индексов, оптимизации SQL-запросов.
✅ Универсальность – подходит для большинства бизнес-приложений.
🔹 Недостатки реляционной модели
❌ Производительность на больших объёмах данных – при очень больших данных (миллиарды записей) NoSQL-решения могут быть быстрее.
❌ Сложность масштабирования – горизонтальное масштабирование сложнее, чем в NoSQL.
❌ Жёсткость схемы – структура таблиц фиксирована, что требует продуманного проектирования.
🔥 Вывод
Реляционная модель данных остаётся основным стандартом хранения структурированной информации. Она обеспечивает надёжность, удобство работы и точность данных. Однако, для больших распределённых систем могут использоваться альтернативные модели, такие как NoSQL (документные, графовые, колонночные базы).
💡Курс от автора канала на Stepik с сертификатом
"DDL в SQL: Определение и управление структурами баз данных"
При переходе по данной ссылке скидка 50%
#Реляционные_базы_данных #SQL
🔥11👍5💯4👾1
🔍 Функция CASE – условные конструкции в SQL
Функция CASE работает аналогично if-else в языках программирования. Она позволяет проверять условия и возвращать разные значения в зависимости от их выполнения.
Как работает?
SQL проверяет условия WHEN сверху вниз. Как только условие выполнено, возвращается соответствующее значение THEN. Если ни одно из условий не выполнено, используется ELSE (если он указан).
Пример:
Классифицируем сотрудников по уровню зарплаты.
Допустим, у нас есть следующая таблица employees:
Подготовим запрос для классификации:
Логически функция CASE из данного запроса выглядит так:
После выполнения запроса база данных вернёт следующий результат:
Что происходит?
WHEN 1 - если salary больше 5000 – в столбец salary_category записывается 'Высокая зарплата'
WHEN 2 - если salary от 3000 до 5000 – записывается 'Средняя зарплата'
ELSE - если ни одно из условий не выполнено – записывается 'Низкая зарплата'
Где полезно?
✔️Создание категорий (например, разделение клиентов по уровню покупок).
✔️Генерация текстовых описаний на основе данных.
✔️Гибкая обработка данных прямо в SQL-запросе без изменения исходной таблицы.
#Операторы_и_работа_с_данными #CASE
Подписаться на канал
Функция CASE работает аналогично if-else в языках программирования. Она позволяет проверять условия и возвращать разные значения в зависимости от их выполнения.
Как работает?
SQL проверяет условия WHEN сверху вниз. Как только условие выполнено, возвращается соответствующее значение THEN. Если ни одно из условий не выполнено, используется ELSE (если он указан).
Пример:
Классифицируем сотрудников по уровню зарплаты.
Допустим, у нас есть следующая таблица employees:
name salary
Иван 6000
Ольга 4500
Алексей 3000
Мария 2000
Подготовим запрос для классификации:
SELECT name,
salary,
CASE
WHEN salary > 5000 THEN 'Высокая зарплата'
WHEN salary BETWEEN 3000 AND 5000 THEN 'Средняя зарплата'
ELSE 'Низкая зарплата'
END AS salary_category
FROM employees;
Логически функция CASE из данного запроса выглядит так:
CASE
WHEN -- условие 1
WHEN -- условие 2
ELSE -- иначе, если не соблюдены условия
END AS -- пользовательское название столбца для записи результатов
После выполнения запроса база данных вернёт следующий результат:
name salary salary_category
Иван 6000 Высокая зарплата
Ольга 4500 Средняя зарплата
Алексей 3000 Средняя зарплата
Мария 2000 Низкая зарплата
Что происходит?
WHEN 1 - если salary больше 5000 – в столбец salary_category записывается 'Высокая зарплата'
WHEN 2 - если salary от 3000 до 5000 – записывается 'Средняя зарплата'
ELSE - если ни одно из условий не выполнено – записывается 'Низкая зарплата'
Где полезно?
✔️Создание категорий (например, разделение клиентов по уровню покупок).
✔️Генерация текстовых описаний на основе данных.
✔️Гибкая обработка данных прямо в SQL-запросе без изменения исходной таблицы.
#Операторы_и_работа_с_данными #CASE
Подписаться на канал
🔥11💯3👾3
Какой результат вернёт следующий запрос, если salary = 3500? (теория в посте выше)
#тест
SELECT CASE
WHEN salary > 5000 THEN 'Высокая зарплата'
WHEN salary BETWEEN 3000 AND 5000 THEN 'Средняя зарплата'
ELSE 'Низкая зарплата'
END AS salary_category;
#тест
👾6🔥3
Выберите вариант ответа на тестовое задание:
Anonymous Quiz
15%
Высокая зарплата
79%
Средняя зарплата
6%
Низкая зарплата
🔥5🤔3🌚3🤯1👾1
🔍 Основы COALESCE — защита от NULL в SQL
В SQL часто встречаются ситуации, когда в данных есть NULL — отсутствие значения. Это может вызвать ошибки или неожиданные результаты при обработке данных. Функция COALESCE() решает эту проблему, подставляя первое ненулевое значение из списка.
🛠 Синтаксис
1. SQL проверяет аргументы слева направо и возвращает первое ненулевое значение.
2. Если все аргументы NULL, результат тоже будет NULL.
✔️ Пример 1: Подстановка значения по умолчанию
Допустим, у нас есть таблица users, где phone может быть NULL. Чтобы заменить NULL на строку 'Нет номера', используем COALESCE():
* Если в запросе вместо ненулевого последнего аргумента 'Нет номера' указать просто ' ', то в выгрузке запрос выведет NULL там, где номер телефона NULL в БД.
После выполнения запроса база данных вернет результат:
Как это работает?
1. Если phone не NULL, вернётся его значение.
2. Если phone = NULL, подставится 'Нет номера' в столбец phone_display.
✔️ Пример 2: Выбор приоритета из нескольких колонок
Допустим, у нас есть несколько номеров телефона (work_phone, mobile_phone, home_phone). Нам нужно вывести первый доступный:
После выполнения запроса база данных вернет результат (сократил названия столбов, чтобы таблица корректно отображалась не с десктопа):
Как это работает?
1. SQL сначала проверяет значение work_phone: если оно не NULL, оно и выводится.
2. Если work_phone = NULL, проверяется mobile_phone.
3. Если оба предыдущих столбца NULL, берётся home_phone.
4. Если все три NULL, подставляется последний не нулевой аргумент функции – 'Нет номера' в итоговый столбец preferred_phone.
Где полезно?
✔️ Замена NULL на значения по умолчанию.
✔️ Упрощение логики выбора из нескольких колонок.
✔️ Предотвращение ошибок при работе с NULL.
#Операторы_и_работа_с_данными #COALESCE
📱 Подписаться на канал | Курс автора по SQL DDL
В SQL часто встречаются ситуации, когда в данных есть NULL — отсутствие значения. Это может вызвать ошибки или неожиданные результаты при обработке данных. Функция COALESCE() решает эту проблему, подставляя первое ненулевое значение из списка.
🛠 Синтаксис
COALESCE(значение1, значение2, ..., значениеN)
1. SQL проверяет аргументы слева направо и возвращает первое ненулевое значение.
2. Если все аргументы NULL, результат тоже будет NULL.
✔️ Пример 1: Подстановка значения по умолчанию
Допустим, у нас есть таблица users, где phone может быть NULL. Чтобы заменить NULL на строку 'Нет номера', используем COALESCE():
SELECT name, COALESCE(phone, 'Нет номера') AS phone_display
FROM users;
* Если в запросе вместо ненулевого последнего аргумента 'Нет номера' указать просто ' ', то в выгрузке запрос выведет NULL там, где номер телефона NULL в БД.
После выполнения запроса база данных вернет результат:
name phone phone_display
Иван +10101 +10101
Анна NULL Нет номера
Как это работает?
1. Если phone не NULL, вернётся его значение.
2. Если phone = NULL, подставится 'Нет номера' в столбец phone_display.
✔️ Пример 2: Выбор приоритета из нескольких колонок
Допустим, у нас есть несколько номеров телефона (work_phone, mobile_phone, home_phone). Нам нужно вывести первый доступный:
SELECT name, COALESCE(work_phone, mobile_phone, home_phone, 'Нет') AS preferred_phone
FROM users;
После выполнения запроса база данных вернет результат (сократил названия столбов, чтобы таблица корректно отображалась не с десктопа):
name work_p mobile_p home_p pref_p
Иван NULL NULL 555-1 555-1
Анна 777-5 999-9 NULL 777-5
Олег NULL NULL NULL Нет
Как это работает?
1. SQL сначала проверяет значение work_phone: если оно не NULL, оно и выводится.
2. Если work_phone = NULL, проверяется mobile_phone.
3. Если оба предыдущих столбца NULL, берётся home_phone.
4. Если все три NULL, подставляется последний не нулевой аргумент функции – 'Нет номера' в итоговый столбец preferred_phone.
Где полезно?
✔️ Замена NULL на значения по умолчанию.
✔️ Упрощение логики выбора из нескольких колонок.
✔️ Предотвращение ошибок при работе с NULL.
#Операторы_и_работа_с_данными #COALESCE
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👾5🤔2
📊 Нормальные формы в реляционных базах данных: что это и зачем нужно?
При проектировании и пользовательской эксплуатации реляционной базы данных важно следовать нормальным формам (NF), чтобы избежать избыточности, аномалий обновления и повысить целостность данных. Давайте разберёмся, какие бывают нормальные формы и как они работают.
Нормальная форма в реляционной модели данных — это свойство отношения, характеризующее его с точки зрения избыточности, потенциально приводящей к логически ошибочным результатам выборки или изменения данных, чем меньше избыточность тем выше "нормальность данных"
Процесс преобразования отношений базы данных к виду, отвечающему нормальным формам, называется нормализацией. Нормализация предназначена для приведения структуры БД к виду, обеспечивающему минимальную логическую избыточность. Конечной целью нормализации является уменьшение потенциальной противоречивости хранимой в базе данных информации.
Разберем на примерах первые три вида нормальных форм являющихся фундаментом нормализации БД.
1️⃣ Первая нормальная форма (1NF)
Требование:
1. Все атрибуты содержат только атомарные значения (неделимые).
2. Нет повторяющихся групп (множественных значений в одной ячейке).
❌ Плохо (не 1NF):
✔️ Хорошо (1NF):
Разделили атрибут phones на отдельные строки — теперь каждая ячейка содержит одно значение.
2️⃣ Вторая нормальная форма (2NF)
Требование:
1. Таблица уже в 1NF.
2. Все неключевые атрибуты зависят только от полного первичного ключа (если ключ составной).
❌ Плохо (не 2NF):
course_name зависит только от course_id, а не от полного составного ключа (student_id, course_id).
✔️ Хорошо (2NF):
Разбиваем таблицу на две таблицы содержащие логически единую информацию.
Таблица студентов и курсов:
Таблица курсов:
Теперь course_name зависит только от course_id, а не от полного ключа.
3️⃣ Третья нормальная форма (3NF)
Требование:
1. Таблица уже в 2NF.
2. Нет транзитивных зависимостей (атрибуты зависят только от первичного ключа, а не друг от друга).
❌ Плохо (не 3NF):
dep_name зависит от dep_id, а не от первичного ключа employee_id.
✔️ Хорошо (3NF):
Разделяем таблицы логически делящие информацию.
Таблица сотрудников:
Таблица отделов:
Теперь dep_name хранится отдельно и зависит только от dep_id.
💡Вывод
Нормализация помогает избежать дублирования данных, уменьшить избыточность и повысить целостность БД.
1NF — атомарные значения.
2NF — зависимость только от полного первичного ключа.
3NF — отсутствие транзитивных зависимостей.
#Реляционные_базы_данных #Оптимизация_SQL #Нормализация
📱 Подписаться на канал | Курс автора по SQL DDL
При проектировании и пользовательской эксплуатации реляционной базы данных важно следовать нормальным формам (NF), чтобы избежать избыточности, аномалий обновления и повысить целостность данных. Давайте разберёмся, какие бывают нормальные формы и как они работают.
Нормальная форма в реляционной модели данных — это свойство отношения, характеризующее его с точки зрения избыточности, потенциально приводящей к логически ошибочным результатам выборки или изменения данных, чем меньше избыточность тем выше "нормальность данных"
Процесс преобразования отношений базы данных к виду, отвечающему нормальным формам, называется нормализацией. Нормализация предназначена для приведения структуры БД к виду, обеспечивающему минимальную логическую избыточность. Конечной целью нормализации является уменьшение потенциальной противоречивости хранимой в базе данных информации.
Разберем на примерах первые три вида нормальных форм являющихся фундаментом нормализации БД.
1️⃣ Первая нормальная форма (1NF)
Требование:
1. Все атрибуты содержат только атомарные значения (неделимые).
2. Нет повторяющихся групп (множественных значений в одной ячейке).
❌ Плохо (не 1NF):
id name phones
1 Иван +123, +456, +789
✔️ Хорошо (1NF):
id name phone
1 Иван +123
1 Иван +456
1 Иван +789
Разделили атрибут phones на отдельные строки — теперь каждая ячейка содержит одно значение.
2️⃣ Вторая нормальная форма (2NF)
Требование:
1. Таблица уже в 1NF.
2. Все неключевые атрибуты зависят только от полного первичного ключа (если ключ составной).
❌ Плохо (не 2NF):
student_id course_id course_name
1 SQL101 Основы SQL
2 SQL101 Основы SQL
course_name зависит только от course_id, а не от полного составного ключа (student_id, course_id).
✔️ Хорошо (2NF):
Разбиваем таблицу на две таблицы содержащие логически единую информацию.
Таблица студентов и курсов:
student_id course_id
1 SQL101
2 SQL101
Таблица курсов:
course_id course_name
SQL101 Основы SQL
Теперь course_name зависит только от course_id, а не от полного ключа.
3️⃣ Третья нормальная форма (3NF)
Требование:
1. Таблица уже в 2NF.
2. Нет транзитивных зависимостей (атрибуты зависят только от первичного ключа, а не друг от друга).
❌ Плохо (не 3NF):
employee_id dep_id dep_name
1 10 IT
2 20 HR
dep_name зависит от dep_id, а не от первичного ключа employee_id.
✔️ Хорошо (3NF):
Разделяем таблицы логически делящие информацию.
Таблица сотрудников:
employee_id dep_id
1 10
2 20
Таблица отделов:
dep_id dep_name
10 IT
20 HR
Теперь dep_name хранится отдельно и зависит только от dep_id.
💡Вывод
Нормализация помогает избежать дублирования данных, уменьшить избыточность и повысить целостность БД.
1NF — атомарные значения.
2NF — зависимость только от полного первичного ключа.
3NF — отсутствие транзитивных зависимостей.
#Реляционные_базы_данных #Оптимизация_SQL #Нормализация
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👾5💯4
📊 Продвинутые нормальные формы в реляционных базах данных
Если 1NF, 2NF и 3NF (разобрали в этом посте) помогают избежать дублирования данных и аномалий обновления, то 4NF, 5NF и 6NF направлены на устранение более сложных зависимостей и оптимизацию структуры данных.
Давайте разберёмся, зачем они нужны и когда их применять.
4️⃣ Четвёртая нормальная форма (4NF) — применяется для устранения многозначных зависимостей, где столбец с первичным ключом имеет связь «один-ко-многим» со столбцом, который не является ключом. Эта форма устраняет некорректные отношения «многие-ко-многим».
Требование:
1. Таблица уже в 3NF
2. Нет многозначных зависимостей
❌ Плохо (не 4NF):
Представим, что один преподаватель может вести несколько предметов и работать в нескольких аудиториях.
Преподаватель 1 ведёт несколько предметов и работает в нескольких аудиториях. Предмет и аудитория независимы, но при этом создают дублирование данных.
✔️ Хорошо (4NF):
Разбиваем таблицу на две:
Преподаватель — Предмет:
Преподаватель — Аудитория:
Теперь предмет и аудитория хранятся отдельно, убирая многозначную зависимость.
5️⃣ Пятая нормальная форма (5NF) — разделяет таблицы на более малые таблицы для устранения избыточности данных. Разбиение идёт до тех пор, пока нельзя будет воссоздать оригинальную таблицу путём объединения малых таблиц.
Требование:
1. Таблица уже в 4NF.
2. Нет соединительных (join) зависимостей — данные не должны разлагаться на более мелкие части без потери информации.
❌ Плохо (не 5NF):
Каждый проект связан с сотрудником и его ролью, но возможны дублирования.
✔️ Хорошо (5NF):
Разделяем на три таблицы
Проекты:
Сотрудники:
Связь проектов и сотрудников через роли в новой стаблице:
Теперь данные связаны через таблицы без лишнего дублирования.
6️⃣ Шестая нормальная форма (6NF) — Каждое ограничение в связях между таблицами должно зависеть только от ключей и доменов, т.е допустимых значений столбцов. 6NF предотвращает недопустимые данные, устанавливая ограничения на уровне отношений, а не отдельных таблиц или столбцов.
Требование:
1. Таблица уже в 5NF.
2. Разделение на атомарные отношения (каждое изменение данных должно касаться только одной сущности).
Важно: 6NF встречается редко и полезна в хранилищах данных и системах, требующих историчности данных. По своему опыту скажу, что она скорее теоретическая и направлена на устранение всех возможных избыточностей.
Пример:
Допустим, нам нужно хранить историю изменения зарплаты сотрудников.
❌ Плохо (не 6NF):
Изменение отдела ведёт к дублированию зарплаты, что может привести к несогласованности данных.
✔️Хорошо (6NF):
Разделяем данные на независимые отношения:
История зарплаты
История департаментов
Теперь изменения хранятся отдельно и позволяют вести историю без дублирования.
💡Вывод
Продвинутые нормальные формы помогают устранить избыточные зависимости и дублирование, улучшая целостность данных.
4NF – исключает многозначные зависимости.
5NF – убирает дубли через разбиение отношений.
6NF – делает данные полностью атомарными, что полезно для историчности.
#Реляционные_базы_данных #Оптимизация_SQL #Нормализация
📱 Подписаться на канал | Курс автора по SQL DDL
Если 1NF, 2NF и 3NF (разобрали в этом посте) помогают избежать дублирования данных и аномалий обновления, то 4NF, 5NF и 6NF направлены на устранение более сложных зависимостей и оптимизацию структуры данных.
Давайте разберёмся, зачем они нужны и когда их применять.
4️⃣ Четвёртая нормальная форма (4NF) — применяется для устранения многозначных зависимостей, где столбец с первичным ключом имеет связь «один-ко-многим» со столбцом, который не является ключом. Эта форма устраняет некорректные отношения «многие-ко-многим».
Требование:
1. Таблица уже в 3NF
2. Нет многозначных зависимостей
❌ Плохо (не 4NF):
Представим, что один преподаватель может вести несколько предметов и работать в нескольких аудиториях.
teacher_id subject classroom
1 SQL 101
1 Python 101
1 SQL 102
1 Python 102
Преподаватель 1 ведёт несколько предметов и работает в нескольких аудиториях. Предмет и аудитория независимы, но при этом создают дублирование данных.
✔️ Хорошо (4NF):
Разбиваем таблицу на две:
Преподаватель — Предмет:
teacher_id subject
1 SQL
1 Python
Преподаватель — Аудитория:
teacher_id classroom
1 101
1 102
Теперь предмет и аудитория хранятся отдельно, убирая многозначную зависимость.
5️⃣ Пятая нормальная форма (5NF) — разделяет таблицы на более малые таблицы для устранения избыточности данных. Разбиение идёт до тех пор, пока нельзя будет воссоздать оригинальную таблицу путём объединения малых таблиц.
Требование:
1. Таблица уже в 4NF.
2. Нет соединительных (join) зависимостей — данные не должны разлагаться на более мелкие части без потери информации.
❌ Плохо (не 5NF):
project_id employee_id role
1 100 Разработчик
1 101 Тестировщик
2 100 Разработчик
2 102 Аналитик
Каждый проект связан с сотрудником и его ролью, но возможны дублирования.
✔️ Хорошо (5NF):
Разделяем на три таблицы
Проекты:
project_id
1
2
Сотрудники:
employee_id
100
101
102
Связь проектов и сотрудников через роли в новой стаблице:
project_id employee_id role
1 100 Разработчик
1 101 Тестировщик
2 100 Разработчик
2 102 Аналитик
Теперь данные связаны через таблицы без лишнего дублирования.
6️⃣ Шестая нормальная форма (6NF) — Каждое ограничение в связях между таблицами должно зависеть только от ключей и доменов, т.е допустимых значений столбцов. 6NF предотвращает недопустимые данные, устанавливая ограничения на уровне отношений, а не отдельных таблиц или столбцов.
Требование:
1. Таблица уже в 5NF.
2. Разделение на атомарные отношения (каждое изменение данных должно касаться только одной сущности).
Важно: 6NF встречается редко и полезна в хранилищах данных и системах, требующих историчности данных. По своему опыту скажу, что она скорее теоретическая и направлена на устранение всех возможных избыточностей.
Пример:
Допустим, нам нужно хранить историю изменения зарплаты сотрудников.
❌ Плохо (не 6NF):
employee_id salary dep date
1 5000 IT 2024-01-01
1 5500 IT 2024-03-01
1 5500 HR 2024-05-01
Изменение отдела ведёт к дублированию зарплаты, что может привести к несогласованности данных.
✔️Хорошо (6NF):
Разделяем данные на независимые отношения:
История зарплаты
employee_id salary date
1 5000 2024-01-01
1 5500 2024-03-01
История департаментов
employee_id dep date
1 IT 2024-01-01
1 HR 2024-05-01
Теперь изменения хранятся отдельно и позволяют вести историю без дублирования.
💡Вывод
Продвинутые нормальные формы помогают устранить избыточные зависимости и дублирование, улучшая целостность данных.
4NF – исключает многозначные зависимости.
5NF – убирает дубли через разбиение отношений.
6NF – делает данные полностью атомарными, что полезно для историчности.
#Реляционные_базы_данных #Оптимизация_SQL #Нормализация
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7💯4👾4
🛠 Базовые SQL-команды для уровня Junior
Джуниор в SQL – это начинающий специалист, который работает с базами данных и владеет основами языка SQL. Обычно он занимает позицию Junior Database Developer, Junior Data Analyst, Junior SQL Developer или Junior DBA (Database Administrator). Также знание SQL крайне актуально для системных аналитиков.
Если ты только начинаешь свой путь в SQL, вот основные команды, которые нужно знать!
1️⃣ SELECT – выбор данных. Гайд тут
Извлекает данные из таблицы.
2️⃣ INSERT – добавление данных. Подробнее тут
Добавляет новые строки в таблицу.
3️⃣ UPDATE – обновление данных. Подробнее тут
Изменяет существующие данные.
4️⃣ DELETE – удаление данных. За подробностями сюда
Удаляет строки из таблицы.
5️⃣ WHERE – фильтрация данных. Подробнее тут
Используется для выборки данных по условиям.
6️⃣ ORDER BY – сортировка данных
Сортирует результаты запроса.
7️⃣ GROUP BY – группировка данных. Разбирали тут
Объединяет строки с одинаковыми значениями в одну группу.
8️⃣ JOIN – объединение таблиц. Объяснял в этом посте
Позволяет соединять данные из нескольких таблиц.
Освоив эти команды, ты сможешь работать с БД на базовом уровне. Таже рекомендую изучить следующие материалы размещенные на канале внешний ключ, первичный ключ, основы реляционной модели данных тут, типы данных.
#Карьера_SQL, #Основы_SQL
📱 Подписаться на канал | Курс автора по SQL DDL
Джуниор в SQL – это начинающий специалист, который работает с базами данных и владеет основами языка SQL. Обычно он занимает позицию Junior Database Developer, Junior Data Analyst, Junior SQL Developer или Junior DBA (Database Administrator). Также знание SQL крайне актуально для системных аналитиков.
Если ты только начинаешь свой путь в SQL, вот основные команды, которые нужно знать!
1️⃣ SELECT – выбор данных. Гайд тут
Извлекает данные из таблицы.
SELECT name, age FROM users;
-- Выбирает столбцы name и age из таблицы users
2️⃣ INSERT – добавление данных. Подробнее тут
Добавляет новые строки в таблицу.
INSERT INTO users (name, age) VALUES ('Алексей', 25);
-- Вставляет строку с именем "Алексей" и возрастом 25 в таблицу users3️⃣ UPDATE – обновление данных. Подробнее тут
Изменяет существующие данные.
UPDATE users SET age = 26 WHERE name = 'Алексей';
-- Обновляет возраст пользователя "Алексей" на 26
4️⃣ DELETE – удаление данных. За подробностями сюда
Удаляет строки из таблицы.
DELETE FROM users WHERE age < 18;
-- Удаляет всех пользователей младше 18 лет
5️⃣ WHERE – фильтрация данных. Подробнее тут
Используется для выборки данных по условиям.
SELECT * FROM users WHERE age > 20;
-- Выбирает всех пользователей старше 20 лет
6️⃣ ORDER BY – сортировка данных
Сортирует результаты запроса.
SELECT * FROM users ORDER BY age DESC;
-- Выбирает всех пользователей и сортирует их по возрасту по убыванию
7️⃣ GROUP BY – группировка данных. Разбирали тут
Объединяет строки с одинаковыми значениями в одну группу.
SELECT age, COUNT(*) FROM users GROUP BY age;
-- Считает, сколько пользователей каждого возраста
8️⃣ JOIN – объединение таблиц. Объяснял в этом посте
Позволяет соединять данные из нескольких таблиц.
SELECT users.name, orders.total
FROM users
JOIN orders ON users.id = orders.user_id;
-- Выбирает имена пользователей и суммы их заказов
Освоив эти команды, ты сможешь работать с БД на базовом уровне. Таже рекомендую изучить следующие материалы размещенные на канале внешний ключ, первичный ключ, основы реляционной модели данных тут, типы данных.
#Карьера_SQL, #Основы_SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
👾8🔥6🤯2
📊 ORDER BY — как управлять порядком строк в результатах запроса?
Когда ты выполняешь SELECT, порядок строк не гарантирован. База данных возвращает строки в произвольном порядке, зависящем от её внутренней реализации. Если тебе нужен определённый порядок — используется ORDER BY.
Что такое ORDER BY?
ORDER BY — это инструкция, которая упорядочивает строки результата по значениям одного или нескольких столбцов.
Без него результаты могут быть хаотичными — особенно в больших таблицах.
Ключевые особенности:
1️⃣ Порядок по умолчанию — ASC (по возрастанию)
От меньшего к большему: 0 → 1 → 2, A → B → C
2️⃣ DESC — обратный порядок (по убыванию)
От большего к меньшему: Z → Y → X, 1000 → 100 → 10
3️⃣ Сортировка по нескольким столбцам
Если значения в первом столбце равны — используется второй, и так далее.
4️⃣ Можно сортировать по выражениям, функциям и псевдонимам
5️⃣ Можно использовать номер столбца в списке SELECT
Хотя это не рекомендуется для читаемости, но часто встречается в старом коде.
Синтаксис:
Примеры:
Важно:
1. ORDER BY всегда идёт в конце запроса, перед LIMIT, OFFSET, FETCH.
2. Он не изменяет порядок в самой таблице — только в результате запроса.
3. Если ты не укажешь ORDER BY, то повторные запросы могут возвращать строки в разном порядке.
Зачем нужен ORDER BY на практике?
✔️ Построение отчетов (например, по дате)
✔️ Вывод самых новых или самых старых записей
✔️ Получение топ-N результатов (вместе с LIMIT)
✔️ Для пользователей — упорядоченный, понятный вывод
✔️ Для анализа и сравнения значений
#Операторы_и_работа_с_данными #ORDER_BY
📱 Подписаться на канал | Курс автора по SQL DDL
Когда ты выполняешь SELECT, порядок строк не гарантирован. База данных возвращает строки в произвольном порядке, зависящем от её внутренней реализации. Если тебе нужен определённый порядок — используется ORDER BY.
Что такое ORDER BY?
ORDER BY — это инструкция, которая упорядочивает строки результата по значениям одного или нескольких столбцов.
Без него результаты могут быть хаотичными — особенно в больших таблицах.
Ключевые особенности:
1️⃣ Порядок по умолчанию — ASC (по возрастанию)
От меньшего к большему: 0 → 1 → 2, A → B → C
2️⃣ DESC — обратный порядок (по убыванию)
От большего к меньшему: Z → Y → X, 1000 → 100 → 10
3️⃣ Сортировка по нескольким столбцам
Если значения в первом столбце равны — используется второй, и так далее.
4️⃣ Можно сортировать по выражениям, функциям и псевдонимам
5️⃣ Можно использовать номер столбца в списке SELECT
Хотя это не рекомендуется для читаемости, но часто встречается в старом коде.
Синтаксис:
SELECT столбец1, столбец2, ...
FROM таблица
ORDER BY столбец1 [ASC | DESC], столбец2 [ASC | DESC], ...;
Примеры:
-- 1. По возрасту по возрастанию
SELECT name, age FROM users ORDER BY age;
-- 2. По возрасту по убыванию
SELECT name, age FROM users ORDER BY age DESC;
-- 3. По городу, затем по возрасту
SELECT name, city, age FROM users ORDER BY city ASC, age DESC;
-- 4. По длине имени
SELECT name FROM users ORDER BY LENGTH(name);
Важно:
1. ORDER BY всегда идёт в конце запроса, перед LIMIT, OFFSET, FETCH.
2. Он не изменяет порядок в самой таблице — только в результате запроса.
3. Если ты не укажешь ORDER BY, то повторные запросы могут возвращать строки в разном порядке.
Зачем нужен ORDER BY на практике?
✔️ Построение отчетов (например, по дате)
✔️ Вывод самых новых или самых старых записей
✔️ Получение топ-N результатов (вместе с LIMIT)
✔️ Для пользователей — упорядоченный, понятный вывод
✔️ Для анализа и сравнения значений
#Операторы_и_работа_с_данными #ORDER_BY
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👾4💯3
📋 Тест: сортировка данных по нескольким столбцам
Условие:
У вас есть таблица products, которая хранит информацию о товарах в магазине. Вам нужно отсортировать товары сначала по цене в порядке убывания, а затем по названию в алфавитном порядке.
Таблица products:
Теория по ORDER BY в этом посте
#тест
Условие:
У вас есть таблица products, которая хранит информацию о товарах в магазине. Вам нужно отсортировать товары сначала по цене в порядке убывания, а затем по названию в алфавитном порядке.
Таблица products:
id name price
1 Apple 30
2 Banana 20
3 Orange 60
4 Cherry 80
5 Grape 40
Теория по ORDER BY в этом посте
#тест
👾5🔥3🤔2
Выберите вариант ответа на тестовое задание
Anonymous Quiz
86%
ORDER BY price DESC, name ASC
9%
ORDER BY price ASC, name ASC
5%
ORDER BY name ASC, price DESC
🔥7👾4
🧭 Порядок выполнения SQL-запроса: не такой, как кажется на первый взгляд!
Многие уверены, что SQL исполняется сверху вниз, потому что мы так его пишем: SELECT, потом FROM, потом WHERE и так далее.
Но СУБД (система управления базами данных) читает и исполняет его иначе. Понимание этого является ключом к уверенной работе с SQL и написанию эффективных запросов. К слову этот вопрос является достаточно распространенным каверзным вопросом на собесах.
Реальный порядок выполнения SQL-запроса:
1️⃣ FROM – сначала выбирается таблица (или несколько, если есть JOIN).
На этом этапе данные подтягиваются из таблиц, применяются условия соединения (ON), создаются временные таблицы для дальнейших шагов.
2️⃣ WHERE – фильтруются строки на уровне «сырых» данных.
Удаляются строки, которые не соответствуют критериям. Этот шаг нельзя использовать с агрегатными функциями (вроде AVG, SUM) — они ещё не посчитаны.
3️⃣ GROUP BY – группировка строк по одному или нескольким столбцам.
На этом шаге создаются группы для последующего анализа: например, по отделам, категориям, датам.
4️⃣ HAVING – фильтрация уже сгруппированных данных.
Применяется после GROUP BY, работает с агрегатами. Например: показать только те отделы, где средняя зарплата выше определённого порога.
5️⃣ SELECT – выбираются нужные столбцы, считаются выражения и функции.
Только теперь в дело вступают агрегаты (AVG, COUNT, MAX) и алиасы (AS name). Здесь формируется окончательный «вид» результата.
6️⃣ DISTINCT (если есть) – удаляются дубликаты.
Работает после SELECT. Используется для уникальных значений, но может быть затратен по ресурсам.
7️⃣ ORDER BY – сортировка итогового набора данных.
Можно сортировать по столбцу, выражению или порядковому номеру из SELECT.
8️⃣ LIMIT / OFFSET / FETCH – ограничение количества строк.
Используется в пагинации, топ-результатах и тестировании.
Пример запроса:
Что делает запрос по шагам (порядок обработки СУБД):
1️⃣ FROM employees — загружает всех сотрудников
2️⃣ WHERE status = 'active' — оставляет только активных
3️⃣ GROUP BY department — группирует по департаментам
4️⃣ HAVING AVG(salary) > 5000 — отбирает департаменты с хорошей средней
5️⃣ SELECT department, AVG(salary) — выбирает поля
6️⃣ ORDER BY AVG(salary) DESC — сортирует по средней зарплате
7️⃣ LIMIT 3 — берёт только 3 топовых департамента
Совет:
Если запрос работает не так, как ты ожидал — проверь его на соответствие реальному порядку выполнения. Это поможет найти ошибки и понять логику SQL на глубоком уровне.
#Реляционные_базы_данных #СУБД #Оптимизация_SQL
📱 Подписаться на канал | Курс автора по SQL DDL
Многие уверены, что SQL исполняется сверху вниз, потому что мы так его пишем: SELECT, потом FROM, потом WHERE и так далее.
Но СУБД (система управления базами данных) читает и исполняет его иначе. Понимание этого является ключом к уверенной работе с SQL и написанию эффективных запросов. К слову этот вопрос является достаточно распространенным каверзным вопросом на собесах.
Реальный порядок выполнения SQL-запроса:
1️⃣ FROM – сначала выбирается таблица (или несколько, если есть JOIN).
На этом этапе данные подтягиваются из таблиц, применяются условия соединения (ON), создаются временные таблицы для дальнейших шагов.
2️⃣ WHERE – фильтруются строки на уровне «сырых» данных.
Удаляются строки, которые не соответствуют критериям. Этот шаг нельзя использовать с агрегатными функциями (вроде AVG, SUM) — они ещё не посчитаны.
3️⃣ GROUP BY – группировка строк по одному или нескольким столбцам.
На этом шаге создаются группы для последующего анализа: например, по отделам, категориям, датам.
4️⃣ HAVING – фильтрация уже сгруппированных данных.
Применяется после GROUP BY, работает с агрегатами. Например: показать только те отделы, где средняя зарплата выше определённого порога.
5️⃣ SELECT – выбираются нужные столбцы, считаются выражения и функции.
Только теперь в дело вступают агрегаты (AVG, COUNT, MAX) и алиасы (AS name). Здесь формируется окончательный «вид» результата.
6️⃣ DISTINCT (если есть) – удаляются дубликаты.
Работает после SELECT. Используется для уникальных значений, но может быть затратен по ресурсам.
7️⃣ ORDER BY – сортировка итогового набора данных.
Можно сортировать по столбцу, выражению или порядковому номеру из SELECT.
8️⃣ LIMIT / OFFSET / FETCH – ограничение количества строк.
Используется в пагинации, топ-результатах и тестировании.
Пример запроса:
SELECT department, AVG(salary)
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING AVG(salary) > 5000
ORDER BY AVG(salary) DESC
LIMIT 3;
Что делает запрос по шагам (порядок обработки СУБД):
1️⃣ FROM employees — загружает всех сотрудников
2️⃣ WHERE status = 'active' — оставляет только активных
3️⃣ GROUP BY department — группирует по департаментам
4️⃣ HAVING AVG(salary) > 5000 — отбирает департаменты с хорошей средней
5️⃣ SELECT department, AVG(salary) — выбирает поля
6️⃣ ORDER BY AVG(salary) DESC — сортирует по средней зарплате
7️⃣ LIMIT 3 — берёт только 3 топовых департамента
Совет:
Если запрос работает не так, как ты ожидал — проверь его на соответствие реальному порядку выполнения. Это поможет найти ошибки и понять логику SQL на глубоком уровне.
#Реляционные_базы_данных #СУБД #Оптимизация_SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾4💯3
🏷 Псевдонимы в SQL: зачем нужны AS и как правильно их использовать?
В SQL псевдонимы (alias) — это временные имена, которые можно присвоит столбцам или таблицам прямо в запросе. Они не меняют структуру базы данных, но делают запросы понятнее, короче и логичнее.
🔧 Синтаксис:
Слово AS можно опустить — но явное лучше неявного.
Пример 1: псевдоним для столбца
adjusted_salary — это новое имя для результата выражения salary * 1.15.
Пример 2: псевдонимы в соединениях таблиц
Удобно, когда имена таблиц длинные, или когда в запросе участвуют несколько таблиц с одинаковыми именами столбцов.
Что происходит в этом запросе?
1. employees AS e — Мы даём псевдоним e таблице employees. Теперь к её столбцам можно обращаться коротко: e. name, e. dept_id.
2. departments AS d — Аналогично, таблице departments присваиваем алиас d.
3. e. name и d. name — Здесь мы явно указываем, откуда брать каждый name, чтобы избежать путаницы.
4. d. name AS department — Мы даём столбцу более говорящий псевдоним, в результате запроса он будет отображаться как department, а не просто name.
Зачем нужны псевдонимы?
✔️ Читабельность: особенно полезно в сложных выражениях и подзапросах.
✔️ Разрешение конфликтов: если в нескольких таблицах одинаковые названия столбцов.
✔️ Переименование данных в отчётах: чтобы результат выглядел понятнее пользователю.
⚠️ Важно помнить:
Псевдонимы столбцов нельзя использовать в WHERE, потому что WHERE выполняется до SELECT.
Зато можно использовать в ORDER BY и HAVING. Пост про очередность выполнения тут
Пример из практики: расчёт налога и итоговой зарплаты
Задача: рассчитать 13% налог с зарплаты и итоговую сумму к выплате, вывести имя сотрудника, оклад, налог и сумму "на руки".
📎 Что происходит:
employee_name — читаемое имя вместо name
base_salary — для акцента на том, что это до вычета
tax_amount — отдельный расчёт налога
net_salary — итоговая сумма после удержания налога
В данном случае псевдоним создаёт новые столбцы в результирующей выгрузке запроса — но не в самой таблице в базе данных. Если мы будем формировать отчет на основе этих данных, то разобраться в нем становится намного проще.
📘 Заключение:
Псевдонимы — это не просто «красивости», а важный инструмент в арсенале каждого, кто работает с SQL. Они делают код читаемым, поддерживаемым и профессиональным.
#Операторы_и_работа_с_данными #Alias #Оптимизация_SQL
📱 Подписаться на канал | Курс автора по SQL DDL
В SQL псевдонимы (alias) — это временные имена, которые можно присвоит столбцам или таблицам прямо в запросе. Они не меняют структуру базы данных, но делают запросы понятнее, короче и логичнее.
🔧 Синтаксис:
SELECT выражение AS псевдоним
FROM таблица AS псевдоним;
Слово AS можно опустить — но явное лучше неявного.
Пример 1: псевдоним для столбца
SELECT name, salary * 1.15 AS adjusted_salary
FROM employees;
adjusted_salary — это новое имя для результата выражения salary * 1.15.
Пример 2: псевдонимы в соединениях таблиц
SELECT e.name, d.name AS department
FROM employees AS e
JOIN departments AS d ON e.dept_id = d.id;
Удобно, когда имена таблиц длинные, или когда в запросе участвуют несколько таблиц с одинаковыми именами столбцов.
Что происходит в этом запросе?
1. employees AS e — Мы даём псевдоним e таблице employees. Теперь к её столбцам можно обращаться коротко: e. name, e. dept_id.
2. departments AS d — Аналогично, таблице departments присваиваем алиас d.
3. e. name и d. name — Здесь мы явно указываем, откуда брать каждый name, чтобы избежать путаницы.
4. d. name AS department — Мы даём столбцу более говорящий псевдоним, в результате запроса он будет отображаться как department, а не просто name.
Зачем нужны псевдонимы?
✔️ Читабельность: особенно полезно в сложных выражениях и подзапросах.
✔️ Разрешение конфликтов: если в нескольких таблицах одинаковые названия столбцов.
✔️ Переименование данных в отчётах: чтобы результат выглядел понятнее пользователю.
⚠️ Важно помнить:
Псевдонимы столбцов нельзя использовать в WHERE, потому что WHERE выполняется до SELECT.
Зато можно использовать в ORDER BY и HAVING. Пост про очередность выполнения тут
Пример из практики: расчёт налога и итоговой зарплаты
Задача: рассчитать 13% налог с зарплаты и итоговую сумму к выплате, вывести имя сотрудника, оклад, налог и сумму "на руки".
SELECT
name AS employee_name,
salary AS base_salary,
salary * 0.13 AS tax_amount,
salary * 0.87 AS net_salary
FROM employees;
📎 Что происходит:
employee_name — читаемое имя вместо name
base_salary — для акцента на том, что это до вычета
tax_amount — отдельный расчёт налога
net_salary — итоговая сумма после удержания налога
В данном случае псевдоним создаёт новые столбцы в результирующей выгрузке запроса — но не в самой таблице в базе данных. Если мы будем формировать отчет на основе этих данных, то разобраться в нем становится намного проще.
📘 Заключение:
Псевдонимы — это не просто «красивости», а важный инструмент в арсенале каждого, кто работает с SQL. Они делают код читаемым, поддерживаемым и профессиональным.
#Операторы_и_работа_с_данными #Alias #Оптимизация_SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
👾9🔥4💯2
🔁 Что такое транзакция?
Транзакция — это логически связанная группа SQL-операций, которые выполняются как единое целое. Она либо выполняется полностью, либо откатывается полностью, если возникла ошибка.
Если посмотреть с точки зрения машинной философии механизм транзакции можно выразить принципом «всё или ничего»
Ключевые команды:
1. BEGIN / START TRANSACTION – начало транзакции
2. COMMIT – подтверждение изменений
3. ROLLBACK – откат всех изменений с начала транзакции
💡 Почему это важно?
Представь, что ты переводишь деньги между счетами:
Если после первого запроса произойдёт сбой, то деньги «пропадут».
А если всё это завернуть в транзакцию — либо оба запроса сработают, либо ни один:
Если что-то пойдёт не так, можно сделать откат:
Полезно знать:
Транзакции подчиняются принципам ACID:
1. Atomicity — атомарность
2. Consistency — согласованность
3. Isolation — изолированность
4. Durability — надёжность
Заключение
Транзакции — это не просто дополнительная опция. Это механизм, который:
1. Защищает данные от потерь и ошибок;
2. Позволяет писать надёжные и предсказуемые бизнес-логики;
3. Обеспечивает правильность даже в условиях высокой нагрузки.
Делись с командой — это основа безопасной работы с данными.
#Операторы_и_работа_с_данными #Транзакция #Оптимизация_SQL
📱 Подписаться на канал | Курс автора по SQL DDL
Транзакция — это логически связанная группа SQL-операций, которые выполняются как единое целое. Она либо выполняется полностью, либо откатывается полностью, если возникла ошибка.
Если посмотреть с точки зрения машинной философии механизм транзакции можно выразить принципом «всё или ничего»
Ключевые команды:
1. BEGIN / START TRANSACTION – начало транзакции
2. COMMIT – подтверждение изменений
3. ROLLBACK – откат всех изменений с начала транзакции
💡 Почему это важно?
Представь, что ты переводишь деньги между счетами:
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
Если после первого запроса произойдёт сбой, то деньги «пропадут».
А если всё это завернуть в транзакцию — либо оба запроса сработают, либо ни один:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
Если что-то пойдёт не так, можно сделать откат:
ROLLBACK;
Полезно знать:
Транзакции подчиняются принципам ACID:
1. Atomicity — атомарность
2. Consistency — согласованность
3. Isolation — изолированность
4. Durability — надёжность
Заключение
Транзакции — это не просто дополнительная опция. Это механизм, который:
1. Защищает данные от потерь и ошибок;
2. Позволяет писать надёжные и предсказуемые бизнес-логики;
3. Обеспечивает правильность даже в условиях высокой нагрузки.
Делись с командой — это основа безопасной работы с данными.
#Операторы_и_работа_с_данными #Транзакция #Оптимизация_SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👾5
🔔 Триггеры в SQL: автоматические действия в базе данных
Что такое триггер?
Триггер (trigger) — это специальная программа внутри СУБД, которая автоматически выполняет определённый SQL-код при наступлении события в таблице. Иными словами, триггер — это реакция базы данных на изменение данных.
Какие события могут активировать триггер?
Триггеры можно настроить на 3 типа событий:
1. INSERT — Добавление новой строки
2. UPDATE — Изменение существующей строки
3. DELETE — Удаление строки
Когда срабатывает триггер?
Есть два режима срабатывания:
1. BEFORE — До того, как операция будет завершена
2. AFTER — После выполнения операции
Это позволяет:
С BEFORE — предотвратить нежелательные действия (например, отклонить запись с ошибкой).
С AFTER — реагировать на уже выполненные изменения (например, логировать, уведомлять, синхронизировать).
Зачем нужны триггеры?
Примеры использования:
1. Автоматический лог изменений: записывать, кто и когда внёс изменения.
2. Синхронизация таблиц: при удалении строки из одной таблицы, удалить её из другой.
3. Уведомления: запускать действия при изменении статуса заказа.
4. Бизнес-правила: блокировать операции, нарушающие правила компании.
🛠 Синтаксис (на примере MySQL):
* - Внутри BEGIN ... END пишем обычный SQL-код.
Пример 1: логируем добавление сотрудника
Допустим, у нас есть таблица employees и таблица logs для записей о событиях.
🔍 Объяснение:
AFTER INSERT — триггер сработает после добавления нового сотрудника.
NEW. name — обращение к значению поля name в новой строке (та, что только что вставлена).
Вставляется строка в таблицу logs.
Пример 2: предотвратить удаление важной записи
🔍 Объяснение:
BEFORE DELETE — триггер срабатывает до удаления.
OLD. role — значение удаляемой строки.
Если роль admin, выбрасывается ошибка, и удаление не происходит.
Разница между NEW и OLD
В INSERT только NEW — новая строка
В DELETE только OLD — удаляемая строка
В UPDATE оба: OLD — старая, NEW — новая
⚠️ Важные замечания
1. Один триггер = одно событие + одно время (BEFORE/AFTER).
2. Если нужно реагировать на разные события, создавайте несколько триггеров.
3. Не стоит делать сложную логику внутри триггера — это замедлит работу.
4. Циклические триггеры (когда один вызывает другой) могут привести к ошибкам или зависанию — избегайте этого.
📚 Резюме
CREATE TRIGGER — создание триггера
BEFORE / AFTER — время срабатывания
INSERT, UPDATE, DELETE — тип события
NEW, OLD — доступ к значениям до/после
FOR EACH ROW — выполняется для каждой строки
📌 Сохрани этот пост как шпаргалку!
🔁 Делись с коллегами — триггеры полезны, но ими часто пренебрегают.
#Операторы_и_работа_с_данными #Trigger
📱 Подписаться на канал | Курс автора по SQL DDL
Что такое триггер?
Триггер (trigger) — это специальная программа внутри СУБД, которая автоматически выполняет определённый SQL-код при наступлении события в таблице. Иными словами, триггер — это реакция базы данных на изменение данных.
Какие события могут активировать триггер?
Триггеры можно настроить на 3 типа событий:
1. INSERT — Добавление новой строки
2. UPDATE — Изменение существующей строки
3. DELETE — Удаление строки
Когда срабатывает триггер?
Есть два режима срабатывания:
1. BEFORE — До того, как операция будет завершена
2. AFTER — После выполнения операции
Это позволяет:
С BEFORE — предотвратить нежелательные действия (например, отклонить запись с ошибкой).
С AFTER — реагировать на уже выполненные изменения (например, логировать, уведомлять, синхронизировать).
Зачем нужны триггеры?
Примеры использования:
1. Автоматический лог изменений: записывать, кто и когда внёс изменения.
2. Синхронизация таблиц: при удалении строки из одной таблицы, удалить её из другой.
3. Уведомления: запускать действия при изменении статуса заказа.
4. Бизнес-правила: блокировать операции, нарушающие правила компании.
🛠 Синтаксис (на примере MySQL):
CREATE TRIGGER имя_триггера
[BEFORE | AFTER] [INSERT | UPDATE | DELETE]
ON имя_таблицы
FOR EACH ROW
BEGIN
-- SQL-действия*
END;
FOR EACH ROW означает, что триггер сработает для каждой строки, к которой применимо событие.
* - Внутри BEGIN ... END пишем обычный SQL-код.
Пример 1: логируем добавление сотрудника
Допустим, у нас есть таблица employees и таблица logs для записей о событиях.
CREATE TRIGGER log_employee_insert
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
INSERT INTO logs(message)
VALUES (CONCAT('Добавлен сотрудник: ', NEW.name));
END;
🔍 Объяснение:
AFTER INSERT — триггер сработает после добавления нового сотрудника.
NEW. name — обращение к значению поля name в новой строке (та, что только что вставлена).
Вставляется строка в таблицу logs.
Пример 2: предотвратить удаление важной записи
CREATE TRIGGER protect_admin_delete
BEFORE DELETE ON users
FOR EACH ROW
BEGIN
IF OLD.role = 'admin' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Нельзя удалить администратора!';
END IF;
END;
🔍 Объяснение:
BEFORE DELETE — триггер срабатывает до удаления.
OLD. role — значение удаляемой строки.
Если роль admin, выбрасывается ошибка, и удаление не происходит.
Разница между NEW и OLD
В INSERT только NEW — новая строка
В DELETE только OLD — удаляемая строка
В UPDATE оба: OLD — старая, NEW — новая
⚠️ Важные замечания
1. Один триггер = одно событие + одно время (BEFORE/AFTER).
2. Если нужно реагировать на разные события, создавайте несколько триггеров.
3. Не стоит делать сложную логику внутри триггера — это замедлит работу.
4. Циклические триггеры (когда один вызывает другой) могут привести к ошибкам или зависанию — избегайте этого.
📚 Резюме
CREATE TRIGGER — создание триггера
BEFORE / AFTER — время срабатывания
INSERT, UPDATE, DELETE — тип события
NEW, OLD — доступ к значениям до/после
FOR EACH ROW — выполняется для каждой строки
📌 Сохрани этот пост как шпаргалку!
🔁 Делись с коллегами — триггеры полезны, но ими часто пренебрегают.
#Операторы_и_работа_с_данными #Trigger
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👾6💯3
🧬 INSERT через SELECT: массовый перенос данных
INSERT INTO ... SELECT — это оператор массовой вставки. Вместо ручного ввода значений через VALUES, мы берем данные из существующей таблицы (или нескольких) и вставляем их в другую таблицу.
Это — основа для:
1. Копирования данных между таблицами
2. Архивирования записей
3. Миграции и трансформации данных
5. Наполнения витрин и отчётов
6. Подготовки временных таблиц в ETL-процессах
Синтаксис:
Это не просто копирование — можно фильтровать, преобразовывать и агрегировать данные прямо на лету.
⚙️ Как работает?
1. Сначала выполняется SELECT — он формирует временный набор данных.
2. Затем INSERT INTO вставляет эти данные в указанную таблицу.
3. Всё это работает как единая транзакция.
Важно: порядок и типы колонок должны совпадать или быть совместимыми.
🔒 Строгие правила:
1. Количество колонок в INSERT INTO и SELECT должно совпадать.
2. Типы данных должны быть совместимыми: нельзя вставить TEXT в INT.
3. Если в целевой таблице есть NOT NULL, UNIQUE, FOREIGN KEY или DEFAULT, они тоже применяются.
4. Если есть автоинкремент (AUTO_INCREMENT), значение можно не указывать, оно подставится само.
⚠️ Частые ошибки:
1. Забыли WHERE — и вставили весь набор, включая ненужное.
2. Не проверили SELECT — и получили не те данные.
3. Не учли дубликаты — и получили ошибки или лишние строки.
4. Совпали ID-шники — и нарушили целостность данных.
🧠 SQL-инсайты:
1. Можно использовать JOIN в SELECT — перенос с объединением.
2. Можно использовать CASE, чтобы пересчитывать данные на лету.
3. LIMIT полезен при вставке порциями.
4.Поддерживается во всех основных СУБД (MySQL, PostgreSQL, SQL Server, Oracle).
ПРИМЕР 1: копирование всех данных
Что здесь происходит:
1. SELECT * FROM employees — выбираются все строки и все столбцы из таблицы employees.
2. INSERT INTO employees_backup — полученные строки вставляются в таблицу employees_backup.
❗️ Таблицы employees и employees_backup должны иметь одинаковую структуру — одинаковые столбцы в том же порядке и с совместимыми типами данных.
ПРИМЕР 2: выборочная вставка (фильтрация)
Что происходит:
1. SELECT * FROM orders — берутся все заказы.
2. WHERE order_date < CURDATE() - INTERVAL 1 YEAR — фильтрация: только те заказы, которым больше года.
3. Результат вставляется в orders_archive.
Это пример архивации старых данных — очень частая задача в реальной работе с базами.
ПРИМЕР 3: агрегация и вставка
Что делает запрос:
1. SELECT category, SUM(amount) — для каждой категории считается общая сумма продаж.
2. GROUP BY category — группирует строки по категориям.
3. INSERT INTO sales_summary (...) — вставляет результат в таблицу итогов.
В INSERT INTO перечислены имена столбцов, куда вставляются значения. Это повышает читаемость и защищает от ошибок при изменении структуры таблиц.
ПРИМЕР 4: выборка с JOIN
Что происходит по шагам:
JOIN объединяет таблицы users и subnoscriptions по user_id.
WHERE s.active = 1 — выбирает только активных подписчиков.
SELECT u. id, u. name — выбираем только нужные поля.
INSERT INTO newsletter_subscribers (...) — вставляем их в целевую таблицу.
Это пример массового импорта данных в отдельный список.
💡Вывод
INSERT INTO ... SELECT — это не просто способ скопировать данные, а инструмент для построения гибких потоков данных между таблицами. Это основа работы с отчетами, витринами, архивами и резервным копированием.
🔁 Делись с коллегами — особенно с теми, кто до сих пор вставляет данные вручную через VALUES
#Операторы_и_работа_с_данными
📱 Подписаться на канал | Курс автора по SQL DDL
INSERT INTO ... SELECT — это оператор массовой вставки. Вместо ручного ввода значений через VALUES, мы берем данные из существующей таблицы (или нескольких) и вставляем их в другую таблицу.
Это — основа для:
1. Копирования данных между таблицами
2. Архивирования записей
3. Миграции и трансформации данных
5. Наполнения витрин и отчётов
6. Подготовки временных таблиц в ETL-процессах
Синтаксис:
INSERT INTO target_table (col1, col2)
SELECT col_a, col_b
FROM source_table
WHERE condition;
Это не просто копирование — можно фильтровать, преобразовывать и агрегировать данные прямо на лету.
⚙️ Как работает?
1. Сначала выполняется SELECT — он формирует временный набор данных.
2. Затем INSERT INTO вставляет эти данные в указанную таблицу.
3. Всё это работает как единая транзакция.
Важно: порядок и типы колонок должны совпадать или быть совместимыми.
🔒 Строгие правила:
1. Количество колонок в INSERT INTO и SELECT должно совпадать.
2. Типы данных должны быть совместимыми: нельзя вставить TEXT в INT.
3. Если в целевой таблице есть NOT NULL, UNIQUE, FOREIGN KEY или DEFAULT, они тоже применяются.
4. Если есть автоинкремент (AUTO_INCREMENT), значение можно не указывать, оно подставится само.
⚠️ Частые ошибки:
1. Забыли WHERE — и вставили весь набор, включая ненужное.
2. Не проверили SELECT — и получили не те данные.
3. Не учли дубликаты — и получили ошибки или лишние строки.
4. Совпали ID-шники — и нарушили целостность данных.
🧠 SQL-инсайты:
1. Можно использовать JOIN в SELECT — перенос с объединением.
2. Можно использовать CASE, чтобы пересчитывать данные на лету.
3. LIMIT полезен при вставке порциями.
4.Поддерживается во всех основных СУБД (MySQL, PostgreSQL, SQL Server, Oracle).
ПРИМЕР 1: копирование всех данных
INSERT INTO employees_backup
SELECT * FROM employees;
Что здесь происходит:
1. SELECT * FROM employees — выбираются все строки и все столбцы из таблицы employees.
2. INSERT INTO employees_backup — полученные строки вставляются в таблицу employees_backup.
❗️ Таблицы employees и employees_backup должны иметь одинаковую структуру — одинаковые столбцы в том же порядке и с совместимыми типами данных.
ПРИМЕР 2: выборочная вставка (фильтрация)
INSERT INTO orders_archive
SELECT * FROM orders
WHERE order_date < CURDATE() - INTERVAL 1 YEAR;
Что происходит:
1. SELECT * FROM orders — берутся все заказы.
2. WHERE order_date < CURDATE() - INTERVAL 1 YEAR — фильтрация: только те заказы, которым больше года.
3. Результат вставляется в orders_archive.
Это пример архивации старых данных — очень частая задача в реальной работе с базами.
ПРИМЕР 3: агрегация и вставка
INSERT INTO sales_summary (category, total_sales)
SELECT category, SUM(amount)
FROM sales
GROUP BY category;
Что делает запрос:
1. SELECT category, SUM(amount) — для каждой категории считается общая сумма продаж.
2. GROUP BY category — группирует строки по категориям.
3. INSERT INTO sales_summary (...) — вставляет результат в таблицу итогов.
В INSERT INTO перечислены имена столбцов, куда вставляются значения. Это повышает читаемость и защищает от ошибок при изменении структуры таблиц.
ПРИМЕР 4: выборка с JOIN
INSERT INTO newsletter_subscribers (user_id, user_name)
SELECT u.id, u.name
FROM users AS u
JOIN subnoscriptions AS s ON u.id = s.user_id
WHERE s.active = 1;
Что происходит по шагам:
JOIN объединяет таблицы users и subnoscriptions по user_id.
WHERE s.active = 1 — выбирает только активных подписчиков.
SELECT u. id, u. name — выбираем только нужные поля.
INSERT INTO newsletter_subscribers (...) — вставляем их в целевую таблицу.
Это пример массового импорта данных в отдельный список.
💡Вывод
INSERT INTO ... SELECT — это не просто способ скопировать данные, а инструмент для построения гибких потоков данных между таблицами. Это основа работы с отчетами, витринами, архивами и резервным копированием.
🔁 Делись с коллегами — особенно с теми, кто до сих пор вставляет данные вручную через VALUES
#Операторы_и_работа_с_данными
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👾6
🔗 INNER JOIN в SQL — объединяем таблицы
В реальных базах данных информация часто хранится в нескольких связанных таблицах. Чтобы собрать все нужные данные в один результат — используют соединения (JOIN). Самый базовый и часто используемый тип соединения — INNER JOIN.
Что такое INNER JOIN?
INNER JOIN возвращает только те строки, где есть совпадения в обеих таблицах по заданному условию (обычно по ключам).
То есть: если связь не найдена — строка не попадёт в результат.
Синтаксис:
ПРИМЕР:
Структура и данные исходных таблиц:
Таблица employees:
Таблица departments:
Пример запроса:
Что делает запрос:
1. Обходит сотрудников (employees)
2. Находит отделы (departments) по полю dept_id
3. Возвращает только те строки, где dept_id найден в departments. id
Результат:
Charlie не попал в результат, потому что у него dept_id = NULL, а значит нет совпадения с таблицей departments.
🧠 Когда использовать INNER JOIN?
1. Когда нужно объединить связанные таблицы: сотрудники → отделы, заказы → клиенты, товары → категории и т.д.
2. Когда важны только те данные, у которых есть соответствие в обеих таблицах.
3. В отчетах, аналитике и выборках на основе бизнес-связей.
Вывод:
INNER JOIN — это основной способ объединить данные из разных таблиц, сохраняя логическую связь между ними. Если нет совпадения — строки просто игнорируются. Небольшой обзор на все виды Join тут
#Операторы_и_работа_с_данными #INNER_LOIN
📱 Подписаться на канал | Курс автора по SQL DDL
В реальных базах данных информация часто хранится в нескольких связанных таблицах. Чтобы собрать все нужные данные в один результат — используют соединения (JOIN). Самый базовый и часто используемый тип соединения — INNER JOIN.
Что такое INNER JOIN?
INNER JOIN возвращает только те строки, где есть совпадения в обеих таблицах по заданному условию (обычно по ключам).
То есть: если связь не найдена — строка не попадёт в результат.
Синтаксис:
SELECT t1.column, t2.column
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t1.id = t2.foreign_id;
ПРИМЕР:
Структура и данные исходных таблиц:
Таблица employees:
id name dept_id
1 Alice 10
2 Bob 20
3 Charlie NULL
4 Diana 30
Таблица departments:
id name
10 HR
20 Engineering
30 Marketing
40 Sales
Пример запроса:
SELECT e.name, d.name AS department
FROM employees AS e
INNER JOIN departments AS d
ON e.dept_id = d.id;
Что делает запрос:
1. Обходит сотрудников (employees)
2. Находит отделы (departments) по полю dept_id
3. Возвращает только те строки, где dept_id найден в departments. id
Результат:
name department
Alice HR
Bob Engineering
Diana Marketing
Charlie не попал в результат, потому что у него dept_id = NULL, а значит нет совпадения с таблицей departments.
🧠 Когда использовать INNER JOIN?
1. Когда нужно объединить связанные таблицы: сотрудники → отделы, заказы → клиенты, товары → категории и т.д.
2. Когда важны только те данные, у которых есть соответствие в обеих таблицах.
3. В отчетах, аналитике и выборках на основе бизнес-связей.
Вывод:
INNER JOIN — это основной способ объединить данные из разных таблиц, сохраняя логическую связь между ними. Если нет совпадения — строки просто игнорируются. Небольшой обзор на все виды Join тут
#Операторы_и_работа_с_данными #INNER_LOIN
Please open Telegram to view this post
VIEW IN TELEGRAM
💯7👾6🔥4
Удаление данных в РБД SQL: общая заметка про DML и DLL
Когда речь заходит об удалении данных в реляционной базе, важно понимать: в SQL для этого существуют различные типы команд, которые работают по-разному, некоторые из них обратимые и безопасные, а некоторые подобны экстреминатусу в Warhammer40к — уничтожат всё без остатка.
Уровень DML - можно удалить данные очень безопасно. DML-команды изменяют именно данные, но не трогают структуру таблиц:
Особенности:
1. Можно удалить часть данных с фильтрацией (WHERE).
2. Структура таблицы остаётся без изменений.
3. Можно откатить операцию с помощью транзакции (ROLLBACK). Пост про транзакции и откат изменений тут
4. Может быть медленным на больших объёмах (поскольку строки удаляются одна за одной с фиксацией).
🛠 Уровень DDL
DDL-команды влияют на структуру и метаданные базы данных. Даже если кажется, что они просто удаляют строки они могут серьезно повлиять на целостность данных, поэтому применять их нужно только будучи абсолютно уверенным в своих действиях (и желательно с бэкапом БД в кармане)
1. Очищает таблицу полностью: удаляются все строки без условия, сбрасываются счётчики (AUTO_INCREMENT), освобождаются ресурсы.
2. Быстрее, чем DELETE, так как нет построчной обработки.
3. В большинстве СУБД невозможно откатить TRUNCATE через ROLLBACK.
4. В лог транзакций (transaction log) записывается не каждая удалённая строка, а сам факт очистки.
1. Полностью удаляет таблицу из базы, вместе со всеми данными и схемой столбцов.
2. Требует осторожности: восстановление возможно только из бэкапа.
Кратко:
DELETE — DML, удаляет строки, фильтрация доступна, построчная обработка
TRUNCATE — DDL, очищает всю таблицу, нет фильтрации, откат изменений обычно недоступен
DROP — DDL, удаляет таблицу полностью, восстановление таблицы возможно только при наличии бэкапа
На что обратить внимание:
1. Если нужно удалить часть данных — выбирай DELETE.
2. Если нужно быстро очистить всю таблицу перед новой загрузкой данных TRUNCATE.
3. Если таблица должна быть предана полному забвению — юзай DROP.
#Операторы_и_работа_с_данными #DELETE #TRUNCATE #DROP
📱 Подписаться на канал | Курс автора по SQL DDL
Когда речь заходит об удалении данных в реляционной базе, важно понимать: в SQL для этого существуют различные типы команд, которые работают по-разному, некоторые из них обратимые и безопасные, а некоторые подобны экстреминатусу в Warhammer40к — уничтожат всё без остатка.
Уровень DML - можно удалить данные очень безопасно. DML-команды изменяют именно данные, но не трогают структуру таблиц:
DELETE FROM таблица1
WHERE признак = 'значение';
Особенности:
1. Можно удалить часть данных с фильтрацией (WHERE).
2. Структура таблицы остаётся без изменений.
3. Можно откатить операцию с помощью транзакции (ROLLBACK). Пост про транзакции и откат изменений тут
4. Может быть медленным на больших объёмах (поскольку строки удаляются одна за одной с фиксацией).
🛠 Уровень DDL
DDL-команды влияют на структуру и метаданные базы данных. Даже если кажется, что они просто удаляют строки они могут серьезно повлиять на целостность данных, поэтому применять их нужно только будучи абсолютно уверенным в своих действиях (и желательно с бэкапом БД в кармане)
TRUNCATE таблица1;
1. Очищает таблицу полностью: удаляются все строки без условия, сбрасываются счётчики (AUTO_INCREMENT), освобождаются ресурсы.
2. Быстрее, чем DELETE, так как нет построчной обработки.
3. В большинстве СУБД невозможно откатить TRUNCATE через ROLLBACK.
4. В лог транзакций (transaction log) записывается не каждая удалённая строка, а сам факт очистки.
DROP таблица1;
1. Полностью удаляет таблицу из базы, вместе со всеми данными и схемой столбцов.
2. Требует осторожности: восстановление возможно только из бэкапа.
Кратко:
DELETE — DML, удаляет строки, фильтрация доступна, построчная обработка
TRUNCATE — DDL, очищает всю таблицу, нет фильтрации, откат изменений обычно недоступен
DROP — DDL, удаляет таблицу полностью, восстановление таблицы возможно только при наличии бэкапа
На что обратить внимание:
1. Если нужно удалить часть данных — выбирай DELETE.
2. Если нужно быстро очистить всю таблицу перед новой загрузкой данных TRUNCATE.
3. Если таблица должна быть предана полному забвению — юзай DROP.
#Операторы_и_работа_с_данными #DELETE #TRUNCATE #DROP
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾5🌚3
🧩 Что такое ER-диаграммы и зачем они нужны?
В этом посте немного поработаем, с любимой темой автора — архитектурой. Когда вы проектируете базу данных, важно понять не только, какие таблицы будут, но и что они означают и как связаны. Для этого используют ER-модель (Entity-Relationship Model) — инструмент, созданный Питером Ченом в 1976 году.
Теоретическая база
ER-модель — это абстракция предметной области, которая позволяет выразить:
2. Сущности (Entity) — уникальные объекты (например, Пользователь, Товар, Заказ)
3. Атрибуты (Attributes) — свойства этих объектов (например, имя, цена, дата)
4. Связи (Relationships) — логические ассоциации между сущностями (например, "Пользователь оформляет Заказ")
Пост про реляционную модель
ER-модель помогает перевести бизнес-требования в техническую структуру, которую можно реализовать в СУБД.
Основные понятия подробно:
1. Сущность (Entity). Это классы объектов реального мира, которые мы хотим сохранить в базе. Например, Student, Course, Invoice.
2. Слабая сущность. Не имеет собственного первичного ключа. Например, Payment может зависеть от Invoice.
3. Атрибут (Attribute). Конкретная характеристика сущности. Могут быть: Простыми (name, price), составными (full_name → first_name + last_name), многозначными (телефоны), производными (возраст можно вычислить по дате рождения)
4.Первичный ключ (Primary Key). Уникальный идентификатор сущности — обязателен. Посты про первичный и внешний ключи
5.Связь (Relationship) определяет, как сущности взаимодействуют. Может быть:
— бинарной (между двумя сущностями)
— тернарной (между тремя)
— рекурсивной (сущность связана сама с собой, например, Employee → Manager)
6, Кардинальность. Указывает, сколько экземпляров одной сущности может быть связано с другой. Форматы: 1:1, 1:N, M:N.
7, Обязательность (Optionality). Определяет, обязательно ли участие в связи. Например, заказ может иметь доставку, а может не иметь.
🔗 Типы связей в деталях
1, Один к одному (1:1) — Реализуется через внешний ключ с ограничением уникальности.
Пример: каждый человек имеет один паспорт.
2, Один ко многим (1:N) — Внешний ключ указывается на стороне "многих".
Пример: один клиент может сделать несколько заказов.
3, Многие ко многим (M:N) — Требует связующей таблицы.
Пример: студент может записаться на много курсов, курс — иметь много студентов.
Пример: интернет-магазин:
Фрагмент ER-диаграммы (в текстовом виде):
Сущности:
Customer (атрибуты customer_id, name, email)
Order (атрибуты order_id, order_date, total)
Product (атрибуты product_id, name, price)
Связи:
1. Это связь "один ко многим" (1:N).
2. Один покупатель (Customer) может сделать много заказов, но каждый заказ принадлежит только одному покупателю.
3. На практике в таблице Order будет внешний ключ customer_id. Чтобы реализовать такую связь в базе данных, в таблице заказов (Order) нужно указать, кто из клиентов сделал заказ.
1. Это связь "многие ко многим" (M:N).
2. Один заказ может включать много товаров, и один товар может быть в многих заказах.
3. Для реализации такой связи создаётся промежуточная таблица (не показана здесь, но подразумевается) — например, OrderItem:
Эта таблица реализует связь и дополнительные данные (например, количество).
Советы:
1. Используйте ER-диаграмму до нормализации — это первый логический шаг. Пост про нормализацию данных
2. Хорошие инструменты: dbdiagram.io, draw.io, Lucidchart
3. Храните диаграмму рядом с документацией — она пригодится через год, когда все забудут, зачем нужно некое поле.
ER-модель — это язык проектировщика баз данных.
Научитесь его читать и писать — и ваши БД будут чёткими, масштабируемыми и поддерживаемыми.
#Реляционные_базы_данных #Архитектура_РБД
📱 Подписаться на канал | Курс автора по SQL DDL
В этом посте немного поработаем, с любимой темой автора — архитектурой. Когда вы проектируете базу данных, важно понять не только, какие таблицы будут, но и что они означают и как связаны. Для этого используют ER-модель (Entity-Relationship Model) — инструмент, созданный Питером Ченом в 1976 году.
Теоретическая база
ER-модель — это абстракция предметной области, которая позволяет выразить:
2. Сущности (Entity) — уникальные объекты (например, Пользователь, Товар, Заказ)
3. Атрибуты (Attributes) — свойства этих объектов (например, имя, цена, дата)
4. Связи (Relationships) — логические ассоциации между сущностями (например, "Пользователь оформляет Заказ")
Пост про реляционную модель
ER-модель помогает перевести бизнес-требования в техническую структуру, которую можно реализовать в СУБД.
Основные понятия подробно:
1. Сущность (Entity). Это классы объектов реального мира, которые мы хотим сохранить в базе. Например, Student, Course, Invoice.
2. Слабая сущность. Не имеет собственного первичного ключа. Например, Payment может зависеть от Invoice.
3. Атрибут (Attribute). Конкретная характеристика сущности. Могут быть: Простыми (name, price), составными (full_name → first_name + last_name), многозначными (телефоны), производными (возраст можно вычислить по дате рождения)
4.Первичный ключ (Primary Key). Уникальный идентификатор сущности — обязателен. Посты про первичный и внешний ключи
5.Связь (Relationship) определяет, как сущности взаимодействуют. Может быть:
— бинарной (между двумя сущностями)
— тернарной (между тремя)
— рекурсивной (сущность связана сама с собой, например, Employee → Manager)
6, Кардинальность. Указывает, сколько экземпляров одной сущности может быть связано с другой. Форматы: 1:1, 1:N, M:N.
7, Обязательность (Optionality). Определяет, обязательно ли участие в связи. Например, заказ может иметь доставку, а может не иметь.
🔗 Типы связей в деталях
1, Один к одному (1:1) — Реализуется через внешний ключ с ограничением уникальности.
Пример: каждый человек имеет один паспорт.
2, Один ко многим (1:N) — Внешний ключ указывается на стороне "многих".
Пример: один клиент может сделать несколько заказов.
3, Многие ко многим (M:N) — Требует связующей таблицы.
Пример: студент может записаться на много курсов, курс — иметь много студентов.
Пример: интернет-магазин:
Фрагмент ER-диаграммы (в текстовом виде):
Customer ─< Order >─ Product
| | |
id order_id id
name order_date name
email total price
Сущности:
Customer (атрибуты customer_id, name, email)
Order (атрибуты order_id, order_date, total)
Product (атрибуты product_id, name, price)
Связи:
Customer ─────< Order
1. Это связь "один ко многим" (1:N).
2. Один покупатель (Customer) может сделать много заказов, но каждый заказ принадлежит только одному покупателю.
3. На практике в таблице Order будет внешний ключ customer_id. Чтобы реализовать такую связь в базе данных, в таблице заказов (Order) нужно указать, кто из клиентов сделал заказ.
Order >───── Product
1. Это связь "многие ко многим" (M:N).
2. Один заказ может включать много товаров, и один товар может быть в многих заказах.
3. Для реализации такой связи создаётся промежуточная таблица (не показана здесь, но подразумевается) — например, OrderItem:
OrderItem (
order_id INT, -- внешний ключ к Order
product_id INT, -- внешний ключ к Product
quantity INT -- количество единиц товара
)
Эта таблица реализует связь и дополнительные данные (например, количество).
Советы:
1. Используйте ER-диаграмму до нормализации — это первый логический шаг. Пост про нормализацию данных
2. Хорошие инструменты: dbdiagram.io, draw.io, Lucidchart
3. Храните диаграмму рядом с документацией — она пригодится через год, когда все забудут, зачем нужно некое поле.
ER-модель — это язык проектировщика баз данных.
Научитесь его читать и писать — и ваши БД будут чёткими, масштабируемыми и поддерживаемыми.
#Реляционные_базы_данных #Архитектура_РБД
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👾8🤔4