Глава 7. Генерация, обработка и преобразование данных
SQL Lab in JupyterLab
from sqlalchemy import create_engine
from sqlalchemy.engine import URL
connection_url = URL.create(
drivername="mysql+pymysql",
host="localhost",
port=3306,
database="sakila",
username="root",
password="********",
)
engine = create_engine(connection_url)
%load_ext sql
%config SqlMagic.displaylimit = 20
%config SqlMagic.displaycon = False
# %config SqlMagic.feedback = False
%sql engine
print("SQLAlchemy - подключение создано")
print("JupySQL - успешно подключен через SQLAlchemy Engine!")SQLAlchemy - подключение создано
JupySQL - успешно подключен через SQLAlchemy Engine!
Работа со строковыми данными¶
При работе со строковыми данными используется один из символьных типов данных: char, varchar, text (tinytext, text, mediumtext, longtext).
%%sql
CREATE TABLE string_tbl
(char_fld CHAR(30),
vchar_fld VARCHAR(30),
text_fld TEXT
);Генерация строк¶
Самый простой способ заполнить символьный столбец – заключить строку в кавычки.
%%sql
INSERT INTO string_tbl (char_fld, vchar_fld, text_fld)
VALUES ('This is char data',
'This is varchar data',
'This is text data');%%sql
SELECT * FROM string_tbl;Попытаемся заменить столбец vchar_fld строкой в 38 символов:
%%sql
UPDATE string_tbl
SET vchar_fld = 'This is a piece of extremely long data';RuntimeError: (pymysql.err.DataError) (1406, "Data too long for column 'vchar_fld' at row 1")
[SQL: UPDATE string_tbl
SET vchar_fld = 'This is a piece of extremely long data';]
(Background on this error at: https://sqlalche.me/e/20/9h9h)
Получили исключение; данные остались не тронутыми:
%%sql
SELECT * FROM string_tbl;Проверим в каком режиме работаем:
%%sql
SELECT @@session.sql_mode;Если предпочтем механизм усечения строк вместо генерации исключений нужно выбрать режим ANSI:
%%sql
SET sql_mode = 'ansi';%%sql
SELECT @@session.sql_mode;Вызвав инструкцию UPDATE повторно, обнаружим что сервер выполнит ее без ошибок и обновит столбец:
%%sql
UPDATE string_tbl
SET vchar_fld = 'This is a piece of extremely long data';%%sql
SHOW WARNINGS;Выполнив выборку столбца vchar_fld, увидим что строка действительно была усечена:
%%sql
SELECT vchar_fld
FROM string_tbl;Чтобы вернуть настройки обратно в безопасное состояние с включенным строгим контролем данных, сбрасываем их в значение по умолчанию:
%%sql
SET sql_mode = DEFAULT;%%sql
SELECT @@session.sql_mode;Включение одинарных кавычек¶
Поскольку строки указываются одинарными кавычками, следует обратить особое внимание на строки, содержащие внутри одинарные кавычки или апострофы.
%%sql
UPDATE string_tbl
SET text_fld = 'This string dosn't work';RuntimeError: If using snippets, you may pass the --with argument explicitly.
For more details please refer: https://jupysql.ploomber.io/en/latest/compose.html#with-argument
Original error message from DB driver:
(pymysql.err.ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 't work'' at line 2")
[SQL: UPDATE string_tbl
SET text_fld = 'This string dosn't work';]
(Background on this error at: https://sqlalche.me/e/20/f405)
Чтобы серевер игнорировал апостроф, необходимо добавить перед ним управляющий символ ' или символ обратной косой черты \
%%sql
UPDATE string_tbl
SET text_fld = 'This string didn''t work, but it does now';%%sql
UPDATE string_tbl
SET text_fld = 'This string didn\'t work, but it does now';%%sql
SELECT text_fld
FROM string_tbl;Однако, если извлекаете строку для добавления в файл (который будет читать другая программа), то может потребоваться включение управляющего символа как части извлеченной строки.
%%sql
SELECT QUOTE(text_fld)
FROM string_tbl;При получении данных для экспорта целесообразно использовать функцию quote() для всех символьных столбцов не генерируемых системой – которые пользователи заполняют вручную на обычном языке (комментарии, описания, адреса, отзывы). В них может встретиться любой неожиданный символ.
Включение специальных символов¶
Если приложение является многонациональным, в нем, вероятно, будут встречаться строки, содержащие символы, которых нет на клавиатуре и может потребоваться включить такие символы, например, с диакритическими знаками é или ö.
%%sql
SELECT 'abcdefg', CHAR(97, 98, 99, 100, 101, 102, 103);%%sql
SELECT 'abcdefg', CHAR(97, 98, 99, 100, 101, 102, 103 USING utf8mb4);%%sql
SELECT CONVERT(
CHAR(128, 129, 130, 131, 132, 133, 134, 135, 136, 137 USING binary)
USING cp850
) decoded_result;CHAR(... USING binary)заставляет MySQL сгенерировать чистые, неиспорченные байтыCONVERT(... USING cp850)принудительно расшифровывает их по старой западной DOS-таблице автора книги, превращая в правильные буквы Çüéâäàåçêë.Драйвер Python видит этот готовый текст и выводит его в Jupyter идеально чисто, без маркера
bи без кракозябр.
%%sql
SELECT CONVERT(
CHAR(138, 139, 140, 141, 142, 143, 144, 145, 146, 147 USING binary)
USING cp850
) decoded_result;%%sql
SELECT CONVERT(
CHAR(148, 149, 150, 151, 152, 153, 154, 155, 156, 157 USING binary)
USING cp850
) decoded_result;%%sql
SELECT CONVERT(
CHAR(158, 159, 160, 161, 162, 163, 164, 165 USING binary)
USING cp850
) decoded_result;Используем функцию concat() для соединения отдельных строк, одни из которых просто введем с клавиатуры, а другие сгенерируем с помощью char():
%%sql
SELECT CONCAT(
'danke sch',
CONVERT(CHAR(148 USING binary) USING cp850),
'n'
) result;%%sql
SELECT ASCII('ö');%%sql
SELECT ASCII(CONVERT('ö' USING cp850)) AS book_result;Используя функции char(), ascii() и concat() можно справиться с любой латиницей, даже если под рукой клавиатура без диакритических знаков и специальных символов.
Манипуляции строками¶
Каждый сервер данных включает множество встроенных функций для манипуляции строками.
Прежде чем продолжить, сбросим и обновим данные в string_tbl:
%%sql
DELETE FROM string_tbl;%%sql
INSERT INTO string_tbl (char_fld, vchar_fld, text_fld)
VALUES ('This string is 28 characters',
'This string is 28 characters',
'This string is 28 characters');%%sql
SELECT * FROM string_tbl;Строковые функции, возвращающие числовые значения¶
%%sql
SELECT LENGTH(char_fld) char_length,
LENGTH(vchar_fld) varchar_length,
LENGTH(text_fld) text_length
FROM string_tbl;Увидим одни и те же результаты для всех строковых функций независимо от типа стобца, в котором хранятся строки.
%%sql
SELECT POSITION('characters' IN vchar_fld)
FROM string_tbl;Если подстрока не может быть найдена, функция position () возвращает значение 0.
Нестандартная функция locate() подобна функции position() но допускает необязательный третий параметр, используемый для указания начальной позиции поиска:
%%sql
SELECT LOCATE('is', vchar_fld, 5)
FROM string_tbl;%%sql
DELETE FROM string_tbl;Сначала посмотрим порядок сортировки пяти строк используя запрос, а затем как строки сравниваются одна с другой, используя strcmp().
%%sql
INSERT INTO string_tbl (vchar_fld)
VALUES ('abcd'),
('xyz'),
('QRSTUV'),
('qrstuv'),
('12345');%%sql
SELECT vchar_fld
FROM string_tbl
ORDER BY vchar_fld;%%sql
SELECT STRCMP('12345', '12345') 12345_12345,
STRCMP('abcd', 'xyz') abcd_xyz,
STRCMP('abcd', 'QRSTUV') abcd_QRSTUV,
STRCMP('qrstuv', 'QRSTUV') qrstuv_QRSTUV,
STRCMP('12345', 'xyz') 12345_xyz,
STRCMP('xyz', 'qrstuv') xyz_qrstuv;Наряду с функцией strcmp() MySQL позволят использовать для сравнения строк в предложении select операторы like и regexp.
Такие сравнения будут давать значения 1 (истина) или 0 (ложь).
%%sql
SELECT name, name LIKE '%y' ends_in_y
FROM category;%%sql
SELECT name, name REGEXP 'y$' ends_in_y
FROM category;Строковые функции, возвращающие строки¶
В некоторых случаях требуется изменять существующие строки, извлекая часть строки или добавляя к ней дополнительный текст.
%%sql
DELETE FROM string_tbl;%%sql
INSERT INTO string_tbl (text_fld)
VALUES ('This string was 29 characters');В том числе когда нужно добавить к хранимой строке дополнительные символы:
%%sql
UPDATE string_tbl
SET text_fld = CONCAT(text_fld, ' but now it is longer');%%sql
SELECT text_fld
FROM string_tbl;Еще одно распространенное использование функции concat() – построение строки из отдельных фрагментов данных.
import pandas as pd
pd.set_option('display.max_colwidth', None)
print(f'Pandas ver. {pd.__version__}')
print('Ограничение на макс. ширину столбцов в 50 символов отключено.')Pandas ver. 3.0.5
Ограничение на макс. ширину столбцов в 50 символов отключено.
%config SqlMagic.autopandas = True%%sql
SELECT CONCAT(first_name, ' ', last_name,
' has been a customer since ',
date(create_date)) cust_narrative
FROM customer;Функция concat() может обрабатывать любое выражение, возвращающее строку, и даже преобразовывать числа и даты в строковый формат, о чем свидетельствует столбец даты (create_date), использованный в качестве аргумента.
%config SqlMagic.autopandas = FalseХотя функция concat() полезна для добавления символов в начало или конец строки, может потребоваться добавить или заменить символы в середине строки.
%%sql
SELECT INSERT('goodbye world', 9, 0, 'cruel ') string;Если третий аргумент больше нуля, то он указывает количество символов, которые заменяются вставляемой строкой:
%%sql
SELECT INSERT('goodbye world', 1, 7, 'hello') string;%%sql
SELECT REPLACE('goodbye world goodbye', 'goodbye', 'hello') string;Помимо вставки символов в строку, может потребоваться извлечение подстроки из строки.
%%sql
SELECT SUBSTRING('goodbye cruel world', 9, 5);Работа с числовыми данными¶
В отличие от строковых и временных данных, генерация числовых данных довольно проста. Можете ввести число, получить его из другого столбца или сгенерировать его путем вычислений. При выполнении вычислений доступны все обычные арифметические операторы, а для изменения приоритетов вычислений можно использовать скобки.
%%sql
SELECT (37 * 59) / (78 - (8 * 6));Основная проблема при хранении числовых данных заключается в том, что числа могут быть округлены, если они больше размера, указанного для числового столбца. Например, число 9,96 будет округлено до 10,0 если оно сохранено в столбце определенном как float(3,1).
Выполнение математических функций¶
Числовые функции от одного аргумента
| Имя функции | Описание |
| ----------- | -------------------------------- |
| acos(х) | Вычисляет арккосинус х |
| asin(х) | Вычисляет арксинус х |
| atan(х) | Вычисляет арктангенс х |
| cos(х) | Вычисляет косинус х |
| cot(х) | Вычисляет котангенс х |
| ехр(х) | Вычисляет экспоненту х |
| ln(x) | Вычисляет натуральный логарифм х |
| sin(х) | Вычисляет синус х |
| sqrt(х) | Вычисляет квадратный корень х |
| tan(х) | Вычисляет тангенс х |%%sql
SELECT MOD(10, 4);%%sql
SELECT MOD(22.75, 5);%%sql
SELECT POW(2, 8);%%sql
SELECT POW(2, 10) kilobyte, POW(2, 20) megabyte,
POW(2, 30) gigabyte, POW(2, 40) terabyte;Управление точностью чисел¶
При работе с числами с плавающей точкой не всегда требуется работа или отображение числа с полной точностью. Например, можно хранить данежные данные транзакции с точностью до шести знаков после запятой, но для их отображения понадобится округление до ближайшей сотой.
%%sql
SELECT CEIL(72.445), FLOOR(72.445);%%sql
SELECT CEIL(72.000000001), FLOOR(72.999999999);%%sql
SELECT ROUND(72.49999), ROUND(72.5), ROUND(72.50001);В большинстве случаев требуется сохранить хотя бы некоторую часть десятичных знаков после запятой, а не округлять значение до целого числа.
Для этого функция round() допускает необязательный второй аргумент, который указывает какое количество цифр справа от запятой следует оставить при округлении.
%%sql
SELECT ROUND(72.0909, 1), ROUND(72.0909, 2), ROUND(72.0909, 3);%%sql
SELECT TRUNCATE(72.000000001, 0), TRUNCATE(72.999999999, 0);%%sql
SELECT TRUNCATE(72.0909, 1), TRUNCATE(72.0909, 2), TRUNCATE(72.0909, 3);%%sql
SELECT ROUND(17, -1), TRUNCATE(17, -1);Работа со знаковыми данными¶
Если работаете с числовыми столбцами, в которых допускаются отрицательные значения, могут быть полезны некоторые специализированные числовые функции.
Допустим вас просят создать отчет, показывающий текущее состояние набора банковских счетов, используя данные из некой таблицы account:
| account_id | acct_type | balance |
| ---------- | ------------ | ------- |
| 123 | MONEY MARKET | 785.22 |
| 456 | SAVINGS | 0.00 |
| 789 | CHECKING | -324.22 |Представленный далее запрос возвращает три столбца, полезных при создании отчета:
SELECT account_id, SIGN(balance), ABS(balance)
FROM account;| account_id | SIGN(balance) | ABS(balance) |
| ---------- | ------------- | ------------ |
| 123 | 1 | 785.22 |
| 456 | 0 | 0.00 |
| 789 | -1 | 324.22 |Во втором столбце функция sign() возвращает значение -1, если баланс счета отрицательный, 0 если баланс нулевой и 1 если баланс положительный. Третий столбец получает абсолютное значение баланса счета с помощью функции abs().
Работа с временными данными¶
Из трех типов данных, обсуждаемых в этой главе (символьные, числовые и временные), когда дело доходит до создания и обработки данных, временные данные являются наиболее сложными.
Некоторая сложность вызвана множеством способов, которыми можно описать единственную дату и время. Большая часть сложности связана с системой отсчета.
Часовые пояса¶
MySQL хранит два разных часовых пояса: глобальный часовой пояс и часовой пояс сеанса, которые могут быть разными для каждого пользователя вошедшего в базу данных.
%%sql
SELECT @@global.time_zone, @@session.time_zone;Значение system говорит о том, что сервер использует настройку часового пояса, в котором находится база данных.
Если вы сидите за компьютером в Санкт-Петербурге (Россия) и открываете сеанс по сети на сервере MySQL расположенном в Нью-Йорке, то можете изменить настройку часового пояса для своего сеанса с помощью команды:
%%sql
SET time_zone = 'Europe/Moscow';RuntimeError: (pymysql.err.OperationalError) (1298, "Unknown or incorrect time zone: 'Europe/Moscow'")
[SQL: SET time_zone = 'Europe/Moscow';]
(Background on this error at: https://sqlalche.me/e/20/e3q8)
%%sql
SET time_zone = '+03:00';%%sql
SELECT @@global.time_zone, @@session.time_zone;Чтобы сеанс снова синхронизировался с системным временем самого сервера (а в качестве сервера мы используем наш собственный локальный компьютер):
%%sql
SET time_zone = 'SYSTEM';%%sql
SELECT @@global.time_zone, @@session.time_zone;Генерация временных данных¶
Генерировать временные данные можно любым из способов:
копирование данных из существующего столбца
date,datetimeилиtime;выполнение встроенной функции, которая возвращает
date,datetimeилиtime;построение строкового представления временных данных для вычисления сервером.
Чтобы использовать последний метод, необходимо знать о различных компонентах, используемых при формировании дат.
Строковые представления временных данных¶
Пример инструкции, используемой для изменения даты возврата взятого напрокат фильма:
UPDATE rental
SET return_date = '2019-09-17 15:30:00'
WHERE rental_id = 99999;Сервер определяет, что строка, указанная в предложении set должна быть значением datetime так как строка используется для заполнения столбца datetime. Поэтому сервер попытается преобразовать строку, разделяя ее на шесть компонентов (год, месяц, день, час, минута, секунда), включаемых в формат datetime по умолчанию.
Преобразование строки в дату¶
Если сервер не ожидает значения datetime или если вы хотите представить datetime в формате, отличном от формата по умолчанию, нужно указать серверу на необходимость преобразования строки в дату и время.
Пример простого запроса, который возвращает значение datetime c помощью функции cast():
%%sql
SELECT CAST('2019-09-17 15:30:00' AS DATETIME);Та же логика применяется и к типам date и time:
%%sql
SELECT CAST('2019-09-17' AS DATE) date_field,
CAST('108:17:57' AS TIME) time_field;%%sql
SELECT CAST(CAST('108:17:57' AS TIME) AS CHAR) AS time_field;%%sql
SELECT * FROM rental
WHERE rental_date < CAST('2005-05-25' AS DATE);Когда строки преобразуются во временные значения (явно или неявно) вы должны предоставить все компоненты даты в необходимом порядке.
Функции генерации дат¶
Если нужно сгенерировать временные данные из строки, а строка находится в неверном виде для использования функции cast(), можно использовать встроенную функцию, которая принимает вместе со строкой даты строку формата.
Пусть, например, вы извлекаете из файла строку ‘September 17, 2019’ и вам нужно использовать ее для обновления столбца date. Поскольку строка не соответствует требуемому формату YYYY-MM-DD, можем использовать str_to_date() вместо того, чтобы переформатировать строку для использования функции cast():
UPDATE rental
SET return_date = STR_TO_DATE('September 17, 2019', '%M', '%d', '%Y')
WHERE rental_id = 99999;Второй аргумент в вызове str_to_date() определяет формат строки даты. В данном случае строка содержит название месяца %M, числовое значение дня %d и четырехзначное числовое знаение года %Y.
Функция str_to_date() возвращает значение datetime, date или time в зависимости от содержимого строки формата. Например, если строка формата включает только %H, %i и %s, будет возвращено значение time.
Если пытаетесь сгенерировать текущую дату/время, то не нужно создавать строку, потому что имеются встроенные функции, которые обращаются к системным часам и возвращают текущую дату и/или время в виде строки:
%%sql
SELECT CURRENT_DATE(), CURRENT_TIME(), CURRENT_TIMESTAMP();Значения, возвращаемые этими функциями, имеют формат по умолчанию для возвращаемого временного типа.
Манипуляции временными данными¶
В этом разделе исследуются встроенные функции, которые принимают аргументы даты и возвращают даты, строки или числа.
Функции, возвращающие даты¶
Многие встроенные временные функции принимают в качестве аргумента одну дату и возвращают другую.
Пример, как добавить к текущей дате пять дней:
%%sql
SELECT DATE_ADD(CURRENT_DATE(), INTERVAL 5 DAY);%%sql
SELECT DATE_ADD(CURRENT_DATE(), INTERVAL -364 DAY);Второй аргумент состоит из трех элементов: ключевого слова interval, желаемого количества и типа интервала.
Например, вам сказали, что фильм вернули на 3 часа 27 минут 11 секунд позже, чем было указано изначально. Чтобы исправить:
UPDATE rental
SET return_date = DATE_ADD(return_date, INTERVAL '3:27:11' HOUR_SECOND)
WHERE rental_id = 99999;Или, например, в отделе кадров выяснил, что сотрудник с id 4789 в базе данных старше на 9 лет и 11 месяцев, чем на самом деле:
UPDATE employee
SET birth_date = DATE_ADD(birth_date, INTERVAL '9-11' YEAR_MONTH)
WHERE emp_id = 4789;Например, клиент банка входит 17 сентября 2019 года в систему онлайн-банкинга и планирует перевод на конец месяца:
%%sql
SELECT LAST_DAY('2019-09-17');Независимо от того, указываете ли вы значение date или datetime, функция last_day() всегда возвращает date.
Функции, возвращающие строки¶
Большинство временных функций, возвращающих строковые значения, используются для извлечения части даты или времени.
%%sql
SELECT DAYNAME('2019-09-18');В MySQL много функций для извлечения информации из значений даты, но автор рекомендует вместо них использовать функцию extract(), так как проще запомнить несколько вариантов одной функции, чем десяток различных функций.
Например, чтобы извлечь из значения datetime только часть года:
%%sql
SELECT EXTRACT(YEAR FROM '2019-09-18 22:19:05');Функции, возвращающие числовые значения¶
Еще одна распространенная задача при работе с датами – определение количества интервалов (дней, недель, лет) между двумя датами.
%%sql
SELECT DATEDIFF('2019-09-03', '2019-06-21');Функция datediff() игнорирует время дня в своих аргументах:
%%sql
SELECT DATEDIFF('2019-09-03 23:59:59', '2019-06-21 00:00:01');Если поменять аргументы местами и сначала указать более раннюю дату, datediff() вернет отрицательное значение:
%%sql
SELECT DATEDIFF('2019-06-21', '2019-09-03');Количество недель или лет можем высчитать простым делением на 7 дней в неделю или 365 дней в году:
%%sql
SELECT DATEDIFF('2026-08-26', '2025-08-27') / 365;Если нужна разница не в днях, а в других единицах, вместо datediff() используют функцию timestampdiff(). Она умеет считать и недели, и года, и месяцы.
%%sql
SELECT
TIMESTAMPDIFF(DAY, '2025-08-27', '2026-08-26') AS days_diff,
TIMESTAMPDIFF(MONTH, '2025-08-27', '2026-08-26') AS months_diff,
TIMESTAMPDIFF(YEAR, '2025-08-27', '2026-08-26') AS years_diff
;Функции преобразования¶
Ранее было показано как использовать функцию cast() для преобразования строки в значение datetime.
Чтобы использовать cast(), вы предоставляете значение или выражение, ключевое слово as и тип, в который хотите преобразовать это значение.
Вот пример преобразования строки в целое число:
%%sql
SELECT CAST('1456328' AS SIGNED INTEGER);При преобразовании строки в число функция cast() пытается преобразовать всю строку слева направо. Если в строке обнаруживается знак, которого не может быть в числе, преобразование останавливается без сообщения об ошибке:
%%sql
SELECT CAST('999ABC111' AS UNSIGNED INTEGER);Преобразуются первые три цифры строки, а остальные отбрасываются. При этом сервер MySQL CLI выдает предупреждение, чтобы вы знали, что не вся строка была преобразована:
+---------------------------------------+
| CAST('999ABC111' AS UNSIGNED INTEGER) |
+---------------------------------------+
| 999 |
+---------------------------------------+
1 row in set, 1 warning (0.00 sec)К сожалению не нашел способ как реализовать появление предупреждения 1 warning в Jupyter.
%%sql
SHOW WARNINGS;Если вы конвертируете строку в значение date, datetime или time, следует придерживаться форматов по умолчанию для каждого типа, поскольку предоставить функции cast() строку формата нельзя. cast() умеет переводить строку в дату только в том случае, если строка уже записана в эталонном формате ISO.
Если ваша строка даты представлена не в формате по умолчанию (т.е. YYYY-MM-DD HH:MI:SS для типа datetime), то нужно использовать другую рассмотренную ранее функцию str_to_date()
Упражнения¶
Упражнение 7.1¶
Напишите запрос, который возвращает символы строки ‘Please find the substring in this string’ с 17-го по 25-й.
%%sql
SELECT SUBSTRING('Please find the substring in this string', 17, 9);Упражнение 7.2¶
Напишите запрос, который возвращает абсолютное значение и знак (-1, 0 или 1) числа -25,76823. Верните также число, округленное до ближайших двух знаков после запятой.
%%sql
SELECT ABS(-25.76823), SIGN(-25.76823), ROUND(-25.76823, 2);Упражнение 7.3¶
Напишите запрос, возвращающий для текущей даты только часть, соответствующую месяцу.
%%sql
SELECT EXTRACT(MONTH FROM CURRENT_DATE());Задача решена, но стало интересно:
как получить название месяца, причем на русском языке?
%%sql
SELECT
MONTHNAME(CURRENT_DATE()) current_month_name;Если в будущем потребуется вывести не просто имя месяца, а, например, сокращенное название (Aug) или совместить его с годом (August 2026), лучшим выбором станет date_format().
%%sql
SELECT
DATE_FORMAT(CURRENT_DATE(), '%M') AS month_name_universal,
DATE_FORMAT(CURRENT_DATE(), '%b') AS month_name_short,
DATE_FORMAT(CURRENT_DATE(), '%d.%m.%Y') AS russian_date_format
;%%sql
-- 1. Переключаем локаль сессии на русскую (для текущего запроса)
SET lc_time_names = 'ru_RU';
-- 2. Выполняем целевой запрос
SELECT
DATE_FORMAT(CURRENT_DATE(), '%W, %d %M') AS formatted_date,
DATE_FORMAT(NOW(), '%W, %d %M %Y года, %H:%i') AS full_human_datetime
;%%sql
-- 3. Возвращаем локаль сессии в стандартный режим
SET lc_time_names = 'en_US';
-- 4. Проверяем возврат дефолтных настроек
SELECT
DATE_FORMAT(CURRENT_DATE(), '%W, %d %M') AS formatted_date;