Пишу пост про SQLi*, до конца недели опубликую. В июле, скорее всего буду много говорить о безопасности БД, методах их защиты, плюс затронем выдачу и управление правами пользователей в СУБД и бэкапы.
*⚠️ SQL-инъекция (SQL injection)— это атака, при которой злоумышленник внедряет вредоносный SQL-код через поля ввода, например, на сайте (логин, пароль, поисковая строка), чтобы получить несанкционированный доступ к базе данных.
*
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🌚7 5
This media is not supported in your browser
VIEW IN TELEGRAM
Когда удалил не ту таблицу. Ну, главное, чтобы не на проде 😂
🤣16🔥5😱3🌚2
Привет, вписался в конкурс каналов с качественным авторским контентом. Потом будут голосования за лучшие посты по номинациям среди каналов и все такое — здесь @tg_contest_main. Так что, не удивляйтесь, иногда буду просить вас голосовать))
Ну а вобще, я считаю, круто, что мой канал начинает участвовать в таких штуках, для меня это своеобразный признак оценки моих стараний (как и ваши реакции)😁
Ну а вобще, я считаю, круто, что мой канал начинает участвовать в таких штуках, для меня это своеобразный признак оценки моих стараний (как и ваши реакции)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15🌚3💯3
Недавно писал важный скрипт на работе, где необходимо было считать дельты внутри колонок (сегодня минус вчера). Подумал, что это очень полезное знание и решил передать его вам, моим подписчикам. Собственно вычисление между текущим и предыдущим значением внутри колонки мы и рассмотрим.
SQL-инструмент для расчёта такой дельты — оконная функция LAG()
LAG(столбец, смещение, значение_по_умолчанию)
OVER (PARTITION BY ... ORDER BY ...)
Допустим, у нас есть таблица sales:
sale_date amount
2024-06-01 1000
2024-06-02 1200
2024-06-03 800
Запрос:
select
sale_date,
amount,
amount - LAG(amount) OVER (ORDER BY sale_date) AS delta
FROM sales;
Результат:
sale_date amount delta
2024-06-01 1000 NULL
2024-06-02 1200 200
2024-06-03 800 -400
Что происходит в запросе?
Если у нас несколько магазинов в таблице store_sales:
store_id sale_date amount
1 2024-06-01 1000
1 2024-06-02 1200
2 2024-06-01 700
2 2024-06-02 900
Запрос:
select
store_id,
sale_date,
amount,
amount - LAG(amount) OVER (PARTITION BY store_id ORDER BY sale_date) AS delta
FROM store_sales;
Что получится в результате:
store_id sale_date amount delta
1 2024-06-01 1000 NULL
1 2024-06-02 1200 200
2 2024-06-01 700 NULL
2 2024-06-02 900 200
Доп.ситуация:
Если значения amount могут быть NULL, то delta будет NULL даже при корректном LAG(). Можно использовать COALESCE():
amount - COALESCE(LAG(amount) OVER (...), 0) AS delta
#LAG #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18 7👾5
Привет, немного порассуждал над собесами и подготовкой к ним, совместно с @bashnya_education
🔥7
Forwarded from БАШНЯ
РАЗБОР РУБРИКИ НОРМ ИЛИ СТРЕМ ❗️
Владимир Лунев - наш ментор подготовил разбор, где детально рассмотрел каждый наш вопрос🔥
Не забывайте, что уже сейчас можно записаться на занятие с ментором через нашего менеджера - @bashnya_edu🤯
Более подробно про менторство можно узнать в нашем миниаппе💪
#mini_app
Владимир Лунев - наш ментор подготовил разбор, где детально рассмотрел каждый наш вопрос
Не забывайте, что уже сейчас можно записаться на занятие с ментором через нашего менеджера - @bashnya_edu
Более подробно про менторство можно узнать в нашем миниаппе
#mini_app
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17💯7👾5🤣1
Привет, обещал рассказать про SQL-инъекции. Начнем с теории, а потом расскажу пару интересных кейсов, как от этого пострадали крупные компании.
SQL-инъекция — это уязвимость, при которой злоумышленник может внедрить произвольный SQL-код в запрос и изменить его поведение. Обычно возникает, когда значения из внешнего ввода (пользователя) напрямую вставляются в SQL-запрос без очистки и параметризации.
Представим, что на сайте есть форма входа, и backend формирует такой запрос на основе ввода пользователя:
SELECT * FROM users
WHERE username = 'admin' AND password = '1234';
Но если пользователь введёт в поле password значение:
' OR '1'='1
Запрос превратится в нечто вроде:
SELECT * FROM users
WHERE username = 'admin' AND password = '' OR '1'='1';
А это всегда истина. В итоге, пользователь войдёт без знания пароля.
Урон: более 130 миллионов украденных номеров кредитных карт.
Хакеры использовали SQL-инъекцию на публично доступном веб-сервере, чтобы получить доступ к внутренней сети компании. Далее они установили кейлоггер, чтобы собирать данные с систем обработки платежей.
Последствия:
Урон: более 1 миллиона аккаунтов пользователей, включая пароли, e-mail и адреса.
Группа LulzSec заявила, что использовала простую SQL-инъекцию на одном из сайтов Sony, не требующую особых технических знаний. База данных была не зашифрована.
Последствия:
Урон: утечка данных более 150 тыс. клиентов, включая банковские данные и номера карт.
Хакер использовал простейшую SQL-инъекцию в форме запроса на сайте, где не была проведена должная проверка входных данных.
Последствия:
Урон: утечка информации о безопасности выборов, продажа на чёрном рынке.
Что произошло:
SQL-инъекция позволила злоумышленникам получить доступ к серверу агентства. Они смогли создать привилегированную учётную запись администратора и продали доступ к базе данных на хакерских форумах.
Последствия:
🔐 SQL-инъекция — это не баг кода, а баг архитектуры. Её можно полностью избежать, если изначально строить систему основанной на принципах безопасности данных.
Что объединяет все эти случаи?
🔒Короткую методичку по защите от этого типа атак можно тезисно охарактеризовать так (подробно расписывать не буду, так как поста не хватит, если интересно почитать подробнее о способах защиты, пишите в коменты, сделаю отдельный пост):
#SQL_Injection #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👾6🤔3😱2 1
И смешно и грустно. Но по моему опыту ИИ неплохие результаты показывает, ибо многие аналитики предочитают не думать об оптимизации запросов, ибо целью является, просто получение нужных данных через страдания CPU и прочих механизмов сервера 🖥
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣10👾4🔥2🤔1
Привет, сегодня факультативный пост без разборов кода. Все слышали про SQL, многие с ним работали и работают, но давайте разберем откуда он вобще взялся и почему стал так популярен. Это язык, который пережил несколько поворотных технологических эпох в мире ИТ и до сих пор является самым актуальным и популярным инструментом управления данными.
🛠 Рождение: 1970-е
В реальности — получилось не совсем так.
🛠 Стандартизация и рост
🧊 Реальный мир
🧊 SQL сегодня
Сегодня есть ряд глобальных проблем, среди них:
Некоторые плюсы:
Вобщем, SQL, еще долго будет с нами, полноценного альтернативного решения, еще не изобрели, так что учим)
#История_SQL #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
💯9👾6 4🔥2
При проектировании таблиц в реляционных базах данных важно выбрать тип данных для первичного ключа. От него зависят скорость запросов, обеспечение уникальности, масштабируемость и даже архитектура системы. Даже если вы не проектируете БД, понимание ключей поможет в работе с данными.
В этом посте рассмотрим три популярных способа генерации первичных ключей: INT, BIGINT и UUID.
🛠 INT — автоинкрементный числовой ключ.
Используется по умолчанию в большинстве проектов. Он требует минимум места, обеспечивает быструю сортировку и фильтрацию по индексу, хорошо читается в логах, легко реализуется средствами СУБД. Но у INT есть потолок (2.1 млрд значений) и ограниченная масштабируемость: при распределении на несколько серверов ID могут пересекаться. А ещё ID легко угадываются, что делает структуру базы предсказуемой.
🛠 BIGINT — INT с запасом на вырост.
То же самое, только 64 бита. Решает проблему переполнения — хватит на миллиарды строк. Сохраняет читаемость, скорость и простоту реализации. Поддерживается всеми современными СУБД. Но индекс и таблицы с такими ключами весят больше. А генерация ID всё ещё централизованная, что не даёт гибкости.
🛠 UUID (Universally Unique Identifier).
UUID создаётся независимо, без единого центра, что делает его идеальным для микросервисов, Kafka, offline-режимов и распределённых архитектур. Его сложно предсказать — это повышает безопасность. UUID легко интегрируется в API и события. Но UUID весит больше (16 байт), хуже индексируется, не читается глазами, не сортируется. Это может замедлять JOIN и вставки. Если важна хоть какая-то упорядоченность, используйте UUID v1 или v7 — они содержат метку времени.
🧊 Объемы генерации ключей в экземпляре таблицы.
Вы можете создать не более примерно 2 миллиардов уникальных записей с автоинкрементом INT. Если же использовать BIGINT, то его диапазон гораздо шире — он позволяет задать свыше 9 квинтиллионов уникальных значений, что на практике практически никогда не достигается.
С UUID ситуация другая: это 128-битное значение, которое генерируется случайным или псевдослучайным образом. Количество возможных значений настолько велико (2^128), что даже при создании миллиардов UUID-ключей в секунду вероятность столкнуться с дублем за всю историю человечества минимальна. Однако при этом UUID занимает больше места, как на диске, так и в оперативной памяти, и может замедлять индексацию.
Что выбрать?
#UUID #INT #BIGINT
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15💯4👾3 2🤣1
CTE (Common Table Expression) — это временный результирующий набор данных, определённый в WITH-блоке и используемый внутри основного SQL-запроса. Он существует только в рамках одного запроса и не сохраняется в базе.
По сути, это "виртуальная подтаблица", которую можно использовать как обычную таблицу, но без создания объекта в БД.
Зачем нужен CTE?
WITH имя_cte (опциональные_поля) AS (
SQL-запрос
)
SELECT ...
FROM имя_cte
...
WITH объявляет формирование CTE. Можно создавать несколько CTE за один раз, разделяя их запятыми:
WITH cte1 AS (...),
cte2 AS (...)
SELECT ...
FROM cte1
JOIN cte2 ...
Найти всех пользователей, которые заходили в систему за последние 30 дней, и посчитать, сколько заказов сделал каждый из них.
Атрибуты:
id name last_login
101 Иван 2025-07-20
105 Ольга 2025-07-15
109 Петр 2025-06-10
Атрибуты:
id user_id created_at
201 101 2025-07-21
203 101 2025-07-20
206 101 2025-07-22
202 105 2025-07-19
204 105 2025-07-22
205 105 2025-07-23
207 105 2025-07-24
208 105 2025-07-25
209 105 2025-07-26
210 105 2025-07-27
WITH active_users AS (
SELECT id AS user_id
FROM users
WHERE last_login > CURRENT_DATE - INTERVAL '30 days'
)
SELECT
u.user_id,
COUNT(o.id) AS orders_count
FROM active_users u
JOIN orders o ON o.user_id = u.user_id
GROUP BY u.user_id;
WITH active_users AS (...)
Создаём временный набор данных с именем active_users, в который попадут только те пользователи, чей last_login был в последние 30 дней.
CURRENT_DATE - INTERVAL '30 days'
Это дата 30 дней назад от текущей.
user_id
101
105
109
SELECT
u.user_id,
COUNT(o.id) AS orders_count
FROM active_users u
JOIN orders o ON o.user_id = u.user_id
GROUP BY u.user_id;
user_id orders_count
101 3
105 7
Пользователь 109, у которого нет заказов, не попадёт в результат — INNER JOIN исключает строки без соответствующих заказов. Чтобы включить таких пользователей и показать orders_count = 0, используйте LEFT JOIN
Когда точно стоит использовать CTE:
#CTE #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20 6🤯5💯1👾1
🧊 Айсберг SQL
Однажды, наткнулся на забавный мем, который с каждым уровнем становится все сложнее и страшнее, посмеялся и забыл. А недавно нашёл статью на Хабр и оказалось, что у мема есть реальное практическое применение, ведь он, по сути, этап за этапом разбирает взаимодействие через SQL с СУБД PostgreSQL, а автор мема SQL-разработчик Джордан Льюис.
Так что можно использовать мем, чтобы выстроить свой путь изучения SQL, как методичку))
На этой неделе, кстати, опубликую пост, как быстро погрузиться в SQL, если вы новичок, и за пару недель (или меньше) достичь гордого уровня junior, минимально необходимого для прохождения собеседований.
Однажды, наткнулся на забавный мем, который с каждым уровнем становится все сложнее и страшнее, посмеялся и забыл. А недавно нашёл статью на Хабр и оказалось, что у мема есть реальное практическое применение, ведь он, по сути, этап за этапом разбирает взаимодействие через SQL с СУБД PostgreSQL, а автор мема SQL-разработчик Джордан Льюис.
Так что можно использовать мем, чтобы выстроить свой путь изучения SQL, как методичку))
На этой неделе, кстати, опубликую пост, как быстро погрузиться в SQL, если вы новичок, и за пару недель (или меньше) достичь гордого уровня junior, минимально необходимого для прохождения собеседований.
🔥28👾4🌚3 1
Набросал своеобразную карту навыков и знаний необходимых для базового, но уверенного понимания работы с реляционными БД. У поста будет еще вторая часть, больше про сами собесы и задачки на них. А пока основы:
Начинать нужно с основ. Вы должны понимать, как извлекать данные из таблиц и как управлять результатом запроса. Разберитесь с базовыми конструкциями:
Уже на этом этапе вы сможете решать до 40% практических задач, особенно из области аналитики или SQL-тестов на позицию junior.
В большинстве реальных задач данные разбросаны по нескольким таблицам. Чтобы собрать полную картину, нужно уметь соединять таблицы между собой. Разберитесь с основными типами соединений:
Понимание JOIN — обязательный навык. Ошибки в соединениях часто приводят к неверным результатам и срезают кандидатов на собеседованиях.
Вам нужно научиться считать и группировать данные, это важно для аналитики через SQL. Изучите:
На этой базе строится вся аналитика: подсчёты по клиентам, категориям, регионам и т.д.
Многие задачи связаны с анализом по дням, неделям, месяцам. Изучите:
Это часто встречается в SQL-задачах.
Часто задачи требуют промежуточных расчётов или сложной логики. Тут пригодятся:
Вложенные конструкции активно используются в продвинутой аналитике, автоматизированных отчётах и сложных тестовых заданиях.
Что из ресурсов могу посоветовать:
Это то, что помогает не просто писать код, а реально понимать, как устроен SQL и базы данных.
Для уверенного уровня Junior важно:
Продолжение следует
#Junior #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24👾11 8💯2🌚1
Работа с датами и временем — это неотъемлемая часть большинства SQL-запросов. Независимо от того, анализируете ли вы продажи по месяцам, фильтруете данные за определённый период или рассчитываете сроки выполнения задач — понимание работы с датами просто необходимо. Перед тем как начинать работать с датами, важно понять, как именно они хранятся в различных СУБД (определите вашу и погуглите какой синтаксис она приветствует), это поможет избежать множества ошибок и неожиданностей.
Дальше распишу функционал внутри кода, для наглядности.
Эти функции используются постоянно — для фильтрации свежих данных, создания временных меток, сравнения с прошлыми значениями.
-- Получаем только текущую дату (без времени)
-- Результат будет примерно таким: 2024-03-15
SELECT CURRENT_DATE;
-- Альтернатива:
SELECT CURDATE(); -- То же самое в MySQL
-- Получаем текущую дату и время
-- Результат будет примерно таким: 2024-03-15 16:45:30
SELECT NOW();
-- Альтернативы:
SELECT CURRENT_TIMESTAMP; -- То же самое, что и NOW()
SELECT LOCALTIME(); -- В некоторых СУБД
SELECT LOCALTIMESTAMP(); -- В некоторых СУБД
-- Получаем только текущее время (без даты)
-- Результат будет примерно таким: 16:45:30
SELECT CURRENT_TIME;
-- Альтернатива:
SELECT CURTIME(); -- То же самое в MySQL
Часто нужно получить отдельные части даты — год, месяц, день и т.д. Для этого используются функции извлечения.
-- Представим, что у нас есть таблица orders с полем created_at
-- Значение created_at: '2024-03-15 14:30:25'
SELECT
created_at, -- Исходное значение: 2024-03-15 14:30:25
-- Извлекаем год из даты
-- Результат: 2024
EXTRACT(YEAR FROM created_at) AS order_year,
-- Извлекаем месяц из даты
-- Результат: 3 (март)
EXTRACT(MONTH FROM created_at) AS order_month,
-- Извлекаем день месяца
-- Результат: 15
EXTRACT(DAY FROM created_at) AS order_day,
-- Извлекаем день недели (0 = воскресенье, 1 = понедельник, ...)
-- Результат: 6 (суббота)
EXTRACT(DOW FROM created_at) AS day_of_week,
-- Извлекаем день года (1-365/366)
-- Результат: 75 (15 марта — 75-й день года)
EXTRACT(DOY FROM created_at) AS day_of_year,
-- Извлекаем час
-- Результат: 14
EXTRACT(HOUR FROM created_at) AS order_hour,
-- Извлекаем минуты
-- Результат: 30
EXTRACT(MINUTE FROM created_at) AS order_minute,
-- Извлекаем секунды
-- Результат: 25
EXTRACT(SECOND FROM created_at) AS order_second,
-- Извлекаем квартал года (1-4)
-- Результат: 1 (первый квартал)
EXTRACT(QUARTER FROM created_at) AS quarter,
-- Извлекаем номер недели года (1-53)
-- Результат: 11
EXTRACT(WEEK FROM created_at) AS week_number
FROM orders
WHERE id = 123; -- Для примера берём конкретную запись
Завтра выложу вторую часть поста, где покажу работу с интервалами, вычисление дельт между датами и варианты форматирования дат.
#SQL #Даты
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23 8👾4💯1