📦 Репозиторий занятия 80

Урок 80. MySQL и Python

Как работать с репозиторием

Каждая карточка говорит, о чём файл, что он выводит и что в нём искать. Код виден прямо здесь: его можно скопировать одной кнопкой, скачать файл или открыть его целиком.

Маршрут изучения

  1. Прочитайте описание: по нему уже понятно, о чём файл и что он выведет.
  2. Предскажите вывод: сравните своё предположение со строкой «Что выводит».
  3. Запустите: скачайте файл или скопируйте код кнопкой и выполните его у себя.
  4. Измените: поменяйте одно условие или значение и объясните новый результат.

Файлы: рекомендуемый порядок

1
SQLSQL-сценарий62 строк

SELECT ... FROM ... WHERE: операторы условий и приоритет операций

01__SELECT_FROM_WHERE/theory_01__SELECT.sql

Один большой блок-комментарий — справочник по синтаксису SELECT/FROM/WHERE и всем операторам условия: сравнения, BETWEEN/NOT BETWEEN, IN/NOT IN, IS NULL/IS NOT NULL, LIKE с масками % и _ (включая BINARY для регистрозависимого поиска) и логические AND/OR/NOT со скобками. Завершается отдельной таблицей приоритета операций от NOT (высший) до XOR (низший) — без неё сложные условия с AND/OR читаются неоднозначно.

  • Базовый синтаксис SELECT ... FROM ... WHERE ...;
  • Операторы сравнения: =, <, >, <>(!=), <=, >=
  • BETWEEN ... AND / NOT BETWEEN — диапазон значений
  • IN / NOT IN — проверка вхождения в список
  • IS NULL / IS NOT NULL
  • LIKE с масками % и _, BINARY для учёта регистра
  • AND, OR, NOT и скобки для приоритета
  • Таблица приоритета операций: NOT → арифметика → сравнения → AND → OR → XOR

Что выводит: Файл не содержит исполняемых запросов — это чисто справочный комментарий (весь текст закомментирован /* ... */), выполнять в СУБД нечего.

Начало файла
/* Позволяет создавать запрос к базе данных
SELECT
    * или (имена полей через запятую)
FROM
    имя таблицы (обычно имя_базы.имя_таблицы)
WHERE
    условие (условия)
; - точка с запятой, обязательный элемент завершения каждого запроса


 Синтаксис              |        Функционал
========================|===============================================================
=, <, >, <> (!=), <=, >=|    равен, меньше,больше,неравен,меньше или равно,больше или равно
                        |
Показать файл целиком (62 строк)
/* Позволяет создавать запрос к базе данных
SELECT
    * или (имена полей через запятую)
FROM
    имя таблицы (обычно имя_базы.имя_таблицы)
WHERE
    условие (условия)
; - точка с запятой, обязательный элемент завершения каждого запроса


 Синтаксис              |        Функционал
========================|===============================================================
=, <, >, <> (!=), <=, >=|    равен, меньше,больше,неравен,меньше или равно,больше или равно
                        |
                        |
    BETWEEN ... AND,    |    значение в диапазоне, включая границы
NOT BETWEEN ... AND     |    (или значения ВНЕ диапазона)
                        |    salary BETWEEN 2000 AND 3000
                        |
                        |
IN, NOT IN              |    значение в списке              id IN (10, 20, 30)
                        |    (или любые значения, кроме тех, что в списке)
                        |
                        |
IS NULL, IS NOT NULL    |    проверка наличия (или отсутствия) записей со значением NULL
                        |
                        |
LIKE, NOT LIKE          |    значение подходит по маске
                        |    % - множество символов, включая пустую строку
                        |    _ - строго один символ
                        |       name LIKE '%k%' - все имена с символом k или K в середине name
                        |
                        |    Если нужен фильтр с учётом регистра, используйте BINARY
                        |       BINARY name LIKE 'K%'  - вернёт имена, начинающиеся с заглавной K
                        |
                        |
AND, OR, NOT            |    логические И, ИЛИ, НЕ
                        |
()                      |    указание приоритета
========================|===============================================================


                 ТАБЛИЦА ПРИОРИТЕТОВ

 ===========|============================|===============================
  Приоритет |        Операция            |          Описание
 ===========|============================|===============================
      1	    |           NOT              |   Логическое отрицание
            |                            |
      2	    |   Арифметические операции  |   Выполнение математических
            |   (+, -, *, /, %)	         |     вычислений
            |                            |
      3	    |   Операторы сравнения      |   Сравнение значений
            |   (=, !=, <, >, <=, >=)	 |
            |                            |
      4	    |           AND              |   Логическое "и"
            |                            |
      5	    |           OR               |   Логическое "или"
            |                            |
      6	    |           XOR              |   Исключающее "или"
 ===========|============================|==================================
 */
Проверьте себя: В условии WHERE a = 1 OR b = 2 AND c = 3 какая часть выполнится первой согласно таблице приоритетов — AND или OR, и как это меняет результат по сравнению с (a = 1 OR b = 2) AND c = 3?
Открыть файл →
2
SQLSQL-сценарий43 строк

CREATE TABLE, INSERT и создание таблицы-копии через SELECT

04__CREATE_INSERT_UPDATE/theory_01__CREATE_TABLE.sql

Показывает полный синтаксис CREATE TABLE на реальной таблице Employees с разными типами колонок (AUTO_INCREMENT PRIMARY KEY, VARCHAR NOT NULL, DATE, DEFAULT (CURRENT_DATE), DECIMAL с CHECK, UNIQUE, ENUM с DEFAULT), затем массовую вставку через INSERT ... VALUES с несколькими кортежами сразу. В конце — приём CREATE TABLE ... AS SELECT для создания копии таблицы прямо из результата выборки, без повторного описания структуры.

  • CREATE DATABASE IF NOT EXISTS ... / USE ...
  • CREATE TABLE Employees — AUTO_INCREMENT PRIMARY KEY, DEFAULT (CURRENT_DATE), CHECK, UNIQUE, ENUM DEFAULT
  • INSERT INTO Employees (...) VALUES (...), (...) — вставка нескольких строк
  • CREATE TABLE Employees_2 AS SELECT * FROM Employees — копия таблицы из выборки

Что выводит: Файл — набор DDL/DML-команд для выполнения на живом сервере MySQL (требует подключения и прав на создание БД/таблиц); фактически не запускался. Ожидаемый эффект: создаётся база 060326_ptm_ClassWork, в ней таблица Employees с двумя строками (John Smith, Jane Smith), а затем Employees_2 — точная копия текущего содержимого Employees.

Начало файла
/* 
Синтаксис формирования таблицы

CREATE TABLE <table_name> (
	<column1_name> <data_type>,
	<column2_name> <data_type>,
	<column3_name> <data_type>,
	...
    <columnN_name> <data_type>
);
 */

CREATE DATABASE IF NOT EXISTS 060326_ptm_ClassWork;
Показать файл целиком (43 строк)
/* 
Синтаксис формирования таблицы

CREATE TABLE <table_name> (
	<column1_name> <data_type>,
	<column2_name> <data_type>,
	<column3_name> <data_type>,
	...
    <columnN_name> <data_type>
);
 */

CREATE DATABASE IF NOT EXISTS 060326_ptm_ClassWork;

USE 060326_ptm_ClassWork;

CREATE TABLE IF NOT EXISTS Employees (
    EmployeeID INT AUTO_INCREMENT PRIMARY KEY,
    FirstName VARCHAR(50) NOT NULL,
    LastName VARCHAR(50) NOT NULL,
    BirthDate DATE,
    HireDate DATE DEFAULT (CURRENT_DATE),
    Salary DECIMAL(9, 2) CHECK (Salary > 0),
    Email VARCHAR(100) UNIQUE,
    Position ENUM('manager', 'developer', 'designer') DEFAULT 'manager'
);

/*
INSERT INTO TableName (Column1, Column2, Column3, ...)
VALUES (Value1, Value2, Value3, ...);
*/

INSERT INTO Employees (FirstName, LastName, BirthDate,  Salary, Email)
VALUES
	('John', 'Smith', '2000-02-03', 5000, 'john.smith@asdasd.com'),
	('Jane', 'Smith', '2002-02-03', 5000, 'jane.smith@asdasd.com');

SELECT * FROM Employees;


/* Создать копию таблицы (сохранить результат выборки как таблицу) */
CREATE TABLE Employees_2 AS
SELECT * FROM Employees;
Проверьте себя: Если убрать список колонок в INSERT INTO Employees (FirstName, LastName, BirthDate, Salary, Email) и просто написать VALUES с теми же пятью значениями — что произойдёт с полями EmployeeID, HireDate и Position?
Открыть файл →
3
SQLSQL-сценарий51 строк

AUTO_INCREMENT: автоматическая генерация PRIMARY KEY

04__CREATE_INSERT_UPDATE/theory_02__AUTO_INCREMENT.sql

Демонстрирует поведение AUTO_INCREMENT на двух похожих таблицах toys1 и toys2. toys1 объявляет toy_id как AUTO_INCREMENT, поэтому INSERT можно делать без указания id вообще. toys2 — обычный PRIMARY KEY без AUTO_INCREMENT, но показывает, что можно явно передать NULL в INSERT, и MySQL по-разному обработает это в зависимости от объявления колонки.

  • CREATE TABLE toys1 — toy_id INT AUTO_INCREMENT PRIMARY KEY
  • INSERT INTO toys1 (toy_name, weight) — без указания id, одна и несколько строк сразу
  • CREATE TABLE toys2 — PRIMARY KEY без AUTO_INCREMENT
  • INSERT INTO toys2 (toy_id, ...) VALUES (NULL, ...) — попытка вставить NULL в PRIMARY KEY

Что выводит: DDL/DML для живого сервера MySQL, не выполнялся. Ожидаемый эффект: в toys1 появляются 3 строки (Велосипед, Самокат, Скейтборд) с id, сгенерированными автоматически 1, 2, 3; в toys2 попытка вставить (NULL, 'Велосипед', 10) в PRIMARY KEY без AUTO_INCREMENT завершится ошибкой, так как PRIMARY KEY не допускает NULL.

Начало файла
/* В MySQL и некоторых других БД - атрибут AUTO_INCREMENT, 
то есть поле, значение которого увеличивается базой данных автоматически 
при добавлении каждой новой записи в таблицу. */

USE 060326_ptm_ClassWork;

CREATE TABLE toys1 (
    toy_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    toy_name VARCHAR(100),
    weight INTEGER
);

SELECT * FROM toys1;
Показать файл целиком (51 строк)
/* В MySQL и некоторых других БД - атрибут AUTO_INCREMENT, 
то есть поле, значение которого увеличивается базой данных автоматически 
при добавлении каждой новой записи в таблицу. */

USE 060326_ptm_ClassWork;

CREATE TABLE toys1 (
    toy_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    toy_name VARCHAR(100),
    weight INTEGER
);

SELECT * FROM toys1;

INSERT INTO toys1 
	(toy_name, weight) 
VALUES 
	("Велосипед", 10);


INSERT INTO toys1 
	(toy_name, weight) 
VALUES 
	("Самокат", 10),
    ("Скейтборд", 10);


-- =================================================================================

CREATE TABLE toys2 (
    toy_id INT PRIMARY KEY,
    toy_name VARCHAR(100),
    weight INTEGER
);

SELECT * FROM toys2;

INSERT INTO toys2
	(toy_id, toy_name, weight) 
VALUES 
	(NULL, "Велосипед", 10);










Проверьте себя: Почему INSERT INTO toys2 (toy_id, toy_name, weight) VALUES (NULL, 'Велосипед', 10) не сработает так же, как для toys1, хотя обе таблицы используют toy_id как PRIMARY KEY?
Открыть файл →
4
SQLSQL-сценарий42 строк

CREATE VIEW: виртуальная таблица поверх toys1 (база training_db)

04__CREATE_INSERT_UPDATE/theory_03__CREATE_VIEW.sql

Создаёт представление v_table как SELECT с условием WHERE по toys1, затем меняет исходную таблицу через UPDATE и проверяет её содержимое — иллюстрирует, что view не хранит данные сама, а пересчитывается при каждом обращении на основе текущего состояния таблицы-источника.

  • CREATE VIEW v_table AS SELECT * FROM toys1 WHERE ...
  • SELECT * FROM v_table — чтение через представление
  • UPDATE toys1 SET weight = 15 WHERE toy_name = 'Скутер' LIMIT 1 — изменение исходной таблицы
  • Повторный SELECT * FROM toys1 — проверка эффекта UPDATE

Что выводит: DDL/DML для живого сервера MySQL (база training_db), не выполнялся. Ожидаемый эффект: v_table покажет строки toys1, где toy_name = 'Велосипед' или weight > 0; последующий UPDATE toys1 SET weight = 15 WHERE toy_name = 'Скутер' изменит исходную таблицу (при условии, что такая строка там есть — в примере из theory_02 её нет, значит обновится 0 строк).

Начало файла
/*  Представление (view) - это виртуальная таблица, 
созданная на основе одной или нескольких таблиц в базе данных. 
Оно предоставляет удобный способ доступа к данным, а также может 
использоваться для упрощения выполнения сложных запросов. 

Представление сохраняет определенный запрос как объект в базе данных, 
к которому можно обратиться, как если бы это была обычная таблица.


CREATE VIEW v_table AS
	SELECT
		<column1_name>,
		<column2_name>, 
		<column3_name>
Показать файл целиком (42 строк)
/*  Представление (view) - это виртуальная таблица, 
созданная на основе одной или нескольких таблиц в базе данных. 
Оно предоставляет удобный способ доступа к данным, а также может 
использоваться для упрощения выполнения сложных запросов. 

Представление сохраняет определенный запрос как объект в базе данных, 
к которому можно обратиться, как если бы это была обычная таблица.


CREATE VIEW v_table AS
	SELECT
		<column1_name>,
		<column2_name>, 
		<column3_name>
	FROM 
		<table_name>
	WHERE
		<condition1> AND <condition2>;
*/

USE training_db;

CREATE VIEW v_table AS
    SELECT 
        *
    FROM
        toys1
    WHERE
        toy_name = 'Велосипед' OR weight > 0;
        
/* Проверям результат */         
SELECT * FROM v_table;

/* Меняем данные исзодной таблицы */         
UPDATE toys1 
SET 
    weight = 15
WHERE
    toy_name = 'Скутер' LIMIT 1;
    
/* Проверям результат изменений в исходной таблицы и затем во view*/        
SELECT * FROM toys1;
Проверьте себя: Если после UPDATE снова сделать SELECT * FROM v_table — обновится ли представление автоматически, или его нужно пересоздавать?
Открыть файл →
5
SQLSQL-сценарий32 строк

CREATE VIEW: тот же приём поверх toys1 (база 060326_ptm_ClassWork)

04__CREATE_INSERT_UPDATE/theory_03__VIEW.sql

Почти дословный повтор предыдущего файла про VIEW, но привязан к базе 060326_ptm_ClassWork (та же, где создавались toys1/toys2 и Employees) и с другим условием фильтра — weight > 2 вместо weight > 0. Без шага с UPDATE — здесь фокус только на создании и чтении представления.

  • USE 060326_ptm_ClassWork — та же база, где создавалась toys1
  • CREATE VIEW v_table AS SELECT * FROM toys1 WHERE toy_name = 'Велосипед' OR weight > 2
  • SELECT * FROM v_table

Что выводит: DDL для живого сервера MySQL, не выполнялся. Ожидаемый эффект: v_table содержит строки toys1, где toy_name = 'Велосипед' или weight > 2 — то есть все три ранее вставленные игрушки (вес у всех 10), если toys1 к этому моменту ещё существует в базе.

Начало файла
/*  Представление (view) - это виртуальная таблица, 
созданная на основе одной или нескольких таблиц в базе данных. 
Оно предоставляет удобный способ доступа к данным, а также может 
использоваться для упрощения выполнения сложных запросов. 

Представление сохраняет определенный запрос как объект в базе данных, 
к которому можно обратиться, как если бы это была обычная таблица.


CREATE VIEW v_table AS
	SELECT
		<column1_name>,
		<column2_name>, 
		<column3_name>
Показать файл целиком (32 строк)
/*  Представление (view) - это виртуальная таблица, 
созданная на основе одной или нескольких таблиц в базе данных. 
Оно предоставляет удобный способ доступа к данным, а также может 
использоваться для упрощения выполнения сложных запросов. 

Представление сохраняет определенный запрос как объект в базе данных, 
к которому можно обратиться, как если бы это была обычная таблица.


CREATE VIEW v_table AS
	SELECT
		<column1_name>,
		<column2_name>, 
		<column3_name>
	FROM 
		<table_name>
	WHERE
		<condition1> AND <condition2>;
*/

USE 060326_ptm_ClassWork;

CREATE VIEW v_table AS
    SELECT 
        *
    FROM
        toys1
    WHERE
        toy_name = 'Велосипед' OR weight > 2;
        
SELECT * FROM v_table;

Проверьте себя: Чем условие weight > 2 в этом файле отличается по результату от weight > 0 в предыдущем файле theory_03__CREATE_VIEW.sql, если у всех трёх игрушек в toys1 вес равен 10?
Открыть файл →
6
SQLSQL-сценарий30 строк

UPDATE: изменение данных с WHERE/LIMIT и предупреждение про безопасный режим

04__CREATE_INSERT_UPDATE/theory_04__UPDATE.sql

Показывает синтаксис UPDATE ... SET ... WHERE ... LIMIT N и явно предупреждает про защитный режим MySQL Workbench, который по умолчанию блокирует UPDATE/DELETE без WHERE или LIMIT («неограниченные» запросы). Второй пример в файле — сознательно опасный UPDATE без WHERE (только LIMIT), меняющий вес у всех строк подряд.

  • Синтаксис UPDATE <table> SET ... WHERE ... LIMIT N
  • Предупреждение: Workbench блокирует UPDATE без WHERE/LIMIT по умолчанию
  • UPDATE toys1 SET weight = 15 WHERE weight > 0 LIMIT 100
  • UPDATE toys1 SET weight = 20 LIMIT 100 — без WHERE, меняет все строки в пределах лимита

Что выводит: DML для живого сервера MySQL, не выполнялся. Ожидаемый эффект: первый UPDATE установит weight = 15 для всех строк toys1 с weight > 0 (то есть для всех трёх игрушек); второй UPDATE toys1 SET weight = 20 LIMIT 100 (без WHERE) перезапишет weight = 20 у всех строк, попавших в лимит 100.

Начало файла
/*    ИЗМЕНЕНИЕ ДАННЫХ
Для изменения данных таблицы можно использовать команду UPDATE,
которая позволяет изменить данные в какой-либо таблице.

(ВНИМАНИЕ: В Workbench по умолчанию стоит ограничение,
    которое не позволяет изменять данные с помощью
    "неограниченных" запросов (без WHERE и / или LIMIT)
)

UPDATE <table_name>
SET
    <column1_name> = <value1>,
    <column2_name> = <value2>
WHERE
Показать файл целиком (30 строк)
/*    ИЗМЕНЕНИЕ ДАННЫХ
Для изменения данных таблицы можно использовать команду UPDATE,
которая позволяет изменить данные в какой-либо таблице.

(ВНИМАНИЕ: В Workbench по умолчанию стоит ограничение,
    которое не позволяет изменять данные с помощью
    "неограниченных" запросов (без WHERE и / или LIMIT)
)

UPDATE <table_name>
SET
    <column1_name> = <value1>,
    <column2_name> = <value2>
WHERE
    <condition1>' LIMIT N;
*/

USE 060326_ptm_ClassWork;

UPDATE toys1 
SET 
    weight = 15
WHERE
    weight > 0 LIMIT 100;

SELECT * FROM toys1;

UPDATE toys1 
SET 
    weight = 20 LIMIT 100;
Проверьте себя: Почему UPDATE toys1 SET weight = 20 LIMIT 100 в MySQL Workbench может потребовать отдельного отключения safe-режима, даже несмотря на LIMIT?
Открыть файл →
7
SQLSQL-сценарий16 строк

DROP TABLE / DROP VIEW / DROP DATABASE — с IF EXISTS

04__CREATE_INSERT_UPDATE/theory_05__DROP.sql

Три команды удаления объектов базы данных подряд: таблица toys1, представление view_toys1 и целая база данных 170225_dam_ClassWork. Все три используют IF EXISTS — приём, позволяющий безопасно запускать скрипт повторно, не получая ошибку, если объект уже удалён или никогда не существовал.

  • DROP TABLE IF EXISTS toys1
  • DROP VIEW IF EXISTS view_toys1
  • DROP DATABASE IF EXISTS 170225_dam_ClassWork

Что выводит: DDL для живого сервера MySQL, не выполнялся. Ожидаемый эффект: удаление таблицы toys1, представления view_toys1 и базы 170225_dam_ClassWork — необратимая операция, откат через ROLLBACK невозможен (в отличие от DML).

Файл целиком (16 строк)
/*   Удаление таблицы, вью, базы данных

DROP <table_name>;
DROP <view_name>;
DROP <database_name>;

*/

USE 060326_ptm_ClassWork;

DROP TABLE IF EXISTS toys1;

DROP VIEW IF EXISTS view_toys1;

DROP DATABASE IF EXISTS 170225_dam_ClassWork;
Проверьте себя: Почему во всех трёх командах используется IF EXISTS, и что произойдёт при повторном запуске этого файла, если объекты уже удалены?
Открыть файл →
8
SQLSQL-сценарий52 строк

ENUM: ограниченный список строковых значений и когда его лучше не использовать

04__CREATE_INSERT_UPDATE/theory_06__ENUM.sql

Вводит тип ENUM на примере статусов пользователя (users.status) и заказов (orders.status DEFAULT 'pending'), объясняет, что MySQL хранит ENUM как числовой индекс списка (отсюда быстрый поиск), а не как строку — при этом сравнивать можно и строкой, и числом-индексом. Завершается практической рекомендацией: если значения могут часто меняться, лучше не ENUM, а отдельная таблица-справочник со FOREIGN KEY, потому что добавление нового значения ENUM требует ALTER TABLE.

  • CREATE TABLE users — status ENUM('active', 'inactive', 'banned') NOT NULL
  • ENUM хранится как числовой индекс (small/medium/large → 1/2/3)
  • SELECT ... WHERE status = 'active' и WHERE status = 1 — эквивалентны
  • CREATE TABLE orders — status ENUM(...) DEFAULT 'pending'
  • Альтернатива для часто меняющихся значений: таблица statuses + FOREIGN KEY вместо ENUM

Что выводит: DDL/DML для живого сервера MySQL, не выполнялся. Ожидаемый эффект: SELECT * FROM users WHERE status = 'active' и SELECT * FROM users WHERE status = 1 вернут одни и те же строки, так как 'active' — первое значение в списке ENUM и хранится как индекс 1.

Начало файла
/*MySQL ENUM — это специальный тип данных, который хранит одно значение из предопределенного списка строковых значений. Используется для хранения ограниченного набора возможных значений, что делает его удобным для статусов, категорий и других фиксированных вариантов.
Синтаксис:*/

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('active', 'inactive', 'banned') NOT NULL
);

/* Особенности ENUM:
    Хранение и производительность
        MySQL хранит ENUM как числовое значение (индекс в списке).
        ENUM('small', 'medium', 'large') хранится как 1, 2, 3 соответственно.
    Поиск быстрее, чем с VARCHAR, так как сравниваются числа, а не строки.
    Добавление новых значений требует ALTER TABLE, что может быть неудобно.
Показать файл целиком (52 строк)
/*MySQL ENUM — это специальный тип данных, который хранит одно значение из предопределенного списка строковых значений. Используется для хранения ограниченного набора возможных значений, что делает его удобным для статусов, категорий и других фиксированных вариантов.
Синтаксис:*/

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('active', 'inactive', 'banned') NOT NULL
);

/* Особенности ENUM:
    Хранение и производительность
        MySQL хранит ENUM как числовое значение (индекс в списке).
        ENUM('small', 'medium', 'large') хранится как 1, 2, 3 соответственно.
    Поиск быстрее, чем с VARCHAR, так как сравниваются числа, а не строки.
    Добавление новых значений требует ALTER TABLE, что может быть неудобно.
*/

/* Сравнение значений
        ENUM можно сравнивать как строки: */
SELECT * FROM users WHERE status = 'active';

/*      Или как числа (по индексу): */

SELECT * FROM users WHERE status = 1;  -- 'active'

/* Значение по умолчанию */

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('pending', 'shipped', 'delivered') DEFAULT 'pending'
);


/* Когда использовать?

✅ Если значения фиксированы и изменяются редко (например, status, type).
❌ Если значения могут часто изменяться — лучше использовать отдельную таблицу и FOREIGN KEY.

Если значения могут часто изменяться, лучше использовать таблицу справочник:
 */

CREATE TABLE statuses (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) UNIQUE NOT NULL
);

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status_id INT NOT NULL,
    FOREIGN KEY (status_id) REFERENCES statuses(id)
);

-- Это позволит легко добавлять и изменять статусы без ALTER TABLE.
Проверьте себя: Почему для статусов, которые часто добавляются или переименовываются, рекомендуется таблица-справочник со FOREIGN KEY, а не ENUM?
Открыть файл →
9
MarkdownРазбор концепции56 строк

DDL vs DML: структура базы данных против её содержимого

04__CREATE_INSERT_UPDATE/theory_07__DDL_vs_DML.md

Разграничивает два подмножества SQL: DDL (CREATE, ALTER, DROP, TRUNCATE, RENAME) управляет структурой — таблицами, схемами, индексами, и все операции автокоммитятся без возможности отката; DML (SELECT, INSERT, UPDATE, DELETE) работает с содержимым строк и может быть отменено через ROLLBACK. Сравнительная таблица в конце сводит оба критерия — что делает и как ведёт себя автокоммит — в одном месте.

  • DDL: CREATE, ALTER, DROP, TRUNCATE, RENAME — структура БД
  • DML: SELECT, INSERT, UPDATE, DELETE — содержимое таблиц
  • DDL — автокоммит, необратимо; DML — можно откатить через ROLLBACK
  • Сравнительная таблица DDL vs DML
Показать начало файла (56 строк всего)
### DDL (Data Definition Language) — язык определения данных

**DDL** используется для **описания структуры** базы данных:  
создание, изменение и удаление таблиц, схем, индексов и т.д.

**DDL** управляет *“каркасом”* базы данных, а не её содержимым.

#### Основные команды DDL:

| Команда    | Назначение                                                   |
| ---------- | ------------------------------------------------------------ |
| `CREATE`   | Создать объект (таблицу, схему, индекс и т.д.)               |
| `ALTER`    | Изменить структуру объекта                                   |
| `DROP`     | Удалить объект                                               |
| `TRUNCATE` | Очистить таблицу (удалить все строки без возможности отката) |
| `RENAME`   | Переименовать объект                                         |

**Пример:**

```sql
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    salary DECIMAL(10, 2)
);
```

### DML (Data Manipulation Language) — язык манипулирования данными

**DML** используется для **работы с содержимым таблиц** — то есть для  
добавления, изменения, удаления и получения строк данных.

#### Основные команды DML:

| Команда  | Назначение                    |
| -------- | ----------------------------- |
| `SELECT` | Выбор данных                  |
| `INSERT` | Вставка новых строк           |
| `UPDATE` | Изменение существующих данных |
| `DELETE` | Удаление строк                |

**Пример:**

```sql
INSERT INTO employees (id, name, salary)
VALUES (1, 'Иван', 55000.00);
```

### Сравнение DDL и DML:

| Критерий       | DDL (Data Definition Language) | DML (Data Manipulation Language)      |
| -------------- |--------------------------------|---------------------------------------|
| Что делает     | Определяет структуру БД        | Управляет данными                     |
| Автокоммит     | Да (операции необратимы)       | Нет (можно откатить через `ROLLBACK`) |
| Примеры команд | CREATE, ALTER, DROP            | SELECT, INSERT, UPDATE, DELETE        |
Проверьте себя: Почему TRUNCATE относится к DDL, а не к DML, хотя визуально он «просто удаляет строки», как DELETE?
10
SQLSQL-сценарий23 строк

DATETIME vs TIMESTAMP: реакция на смену часового пояса сессии

04__CREATE_INSERT_UPDATE/theory_08__DATETIME_vs_TIMESTAMP.sql

Ключевой практический эксперимент файла: создаётся таблица tmp с двумя колонками одинакового момента времени — DATETIME (fixed_date) и TIMESTAMP (flex_date), обе заполняются NOW(). Затем часовой пояс сессии меняется на '+00:00', и таблица читается заново — DATETIME хранит время «как записали» и не меняется, а TIMESTAMP хранится в UTC и пересчитывается под текущий часовой пояс сессии при чтении, поэтому его отображаемое значение меняется.

  • CREATE TABLE tmp — fixed_date DATETIME, flex_date TIMESTAMP
  • INSERT ... VALUE (NOW(), NOW()) — одинаковый момент в обе колонки
  • SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS offset — текущее смещение сессии
  • SET time_zone = '+00:00' — смена часового пояса сессии
  • Повторный SELECT * FROM tmp — fixed_date не изменилась, flex_date изменилась

Что выводит: DDL/DML для живого сервера MySQL, не выполнялся. Ожидаемый эффект: сразу после вставки fixed_date и flex_date показывают одно и то же время; после SET time_zone = '+00:00' повторный SELECT покажет fixed_date без изменений и flex_date, сдвинутый на разницу часовых поясов (то же значение, что показывает TIMEDIFF(NOW(), UTC_TIMESTAMP()) до смены пояса).

Начало файла
DROP TABLE IF EXISTS tmp;

CREATE TABLE IF NOT EXISTS tmp (
	id INT PRIMARY KEY AUTO_INCREMENT,
    fixed_date DATETIME,
    flex_date TIMESTAMP
);

INSERT INTO tmp (fixed_date, flex_date)
VALUE (NOW(), NOW());

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS offset;
-- fixed_date ничем не отличается от flex_date
SELECT * FROM tmp;
Показать файл целиком (23 строк)
DROP TABLE IF EXISTS tmp;

CREATE TABLE IF NOT EXISTS tmp (
	id INT PRIMARY KEY AUTO_INCREMENT,
    fixed_date DATETIME,
    flex_date TIMESTAMP
);

INSERT INTO tmp (fixed_date, flex_date)
VALUE (NOW(), NOW());

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS offset;
-- fixed_date ничем не отличается от flex_date
SELECT * FROM tmp;

-- меняем системное время в пределах сессии
SELECT @@session.time_zone;
SET time_zone = '+00:00';

-- fixed_date не изменилась, в отличии от flex_date
SELECT * FROM tmp;

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS offset;
Проверьте себя: Почему после SET time_zone = '+00:00' значение flex_date в таблице меняется при чтении, хотя сама строка в базе физически не перезаписывалась?
Открыть файл →
11
PythonКонфигурация27 строк

Шаблон файла с параметрами подключения к MySQL (dbconfig)

13__Dbeaver_sqlite_mysql_PD/_local_settings.py

Конфигурационный файл-заготовка с двумя наборами параметров подключения — dbconfig (для чтения из общей учебной базы, HOST/USER/PASSWORD пустые в репозитории) и dbconfig_write (для собственной базы студента, с явным комментарием-предупреждением заменить DATABASE_WRITE на свою). Не исполняемый скрипт сам по себе — импортируется другими файлами (theory_07) как источник секретов подключения.

  • HOST, USER, PASSWORD, DATABASE — параметры общей базы (для чтения)
  • HOST_WRITE, USER_WRITE, PASSWORD_WRITE, DATABASE_WRITE — параметры личной базы (для записи)
  • dbconfig и dbconfig_write — словари, готовые для **dbconfig в mysql.connector.connect()

Что выводит: Не исполняемый файл — просто объявляет два словаря с параметрами подключения; напрямую не запускается, импортируется другими скриптами. Реальные HOST/USER/PASSWORD в репозитории не заполнены (плейсхолдеры и '********').

Начало файла
HOST = ''
USER = ''
PASSWORD = '********'
DATABASE = 'sakila'

HOST_WRITE = ''
USER_WRITE = ''
PASSWORD_WRITE = '********'

# ВНИМАНИЕ!!! Заменить на СВОЮ БД!!!
DATABASE_WRITE = ''

dbconfig = {
'host': HOST,
Показать файл целиком (27 строк)
HOST = ''
USER = ''
PASSWORD = '********'
DATABASE = 'sakila'

HOST_WRITE = ''
USER_WRITE = ''
PASSWORD_WRITE = '********'

# ВНИМАНИЕ!!! Заменить на СВОЮ БД!!!
DATABASE_WRITE = ''

dbconfig = {
'host': HOST,
'user': USER,
'password': PASSWORD,
'database': DATABASE,
}

dbconfig_write = {
'host': HOST_WRITE,
'user': USER_WRITE,
'password': PASSWORD_WRITE,
'database': DATABASE_WRITE,
}


Проверьте себя: Почему в файле два отдельных словаря — dbconfig и dbconfig_write — вместо одного набора параметров подключения?
Открыть файл →
12
MarkdownРазбор концепции56 строк

Установка и настройка DBeaver (Windows/macOS/Ubuntu)

13__Dbeaver_sqlite_mysql_PD/theory_01__install_DBeaver.md

Организационная инструкция по установке DBeaver под три ОС (exe/dmg/deb с apt install) и настройка интерфейса: тема оформления, размер шрифта интерфейса и отдельно шрифт SQL-редактора, включение UpperCase для ключевых слов SQL (KeywordCase: Upper) в автоформатировании.

  • Windows — .exe, macOS — .dmg, Ubuntu — wget + apt install .deb
  • Preferences → Appearance → Theme — смена темы
  • Preferences → Colors and Fonts — шрифт интерфейса и шрифт SQL-редактора отдельно
  • Preferences → SQL Editor → Formatting → KeywordCase: Upper
Показать начало файла (56 строк всего)
# Установка DBeaver

[https://dbeaver.io/download/](https://dbeaver.io/download/)

***

## Windows 

Скачайте `.exe` файл

***

## macOS

Скачайте `.dmg` файл

***

## Ubuntu (Установка через .deb - рекомендуется)

### 1. Скачайте `.deb`-пакет с официального сайта
```
wget https://dbeaver.io/files/dbeaver-ce_latest_amd64.deb
```
### 2. Установите .deb-пакет
```
sudo apt install ./dbeaver-ce_latest_amd64.deb
```
### 3. Запустите DBeaver:
```
dbeaver
```

## Полезные DBeaver
### 1. Изменить настройки цвета фона и стиля:
```
Window -> Preferences -> User Interface -> Appearance -> Theme
```

### 2. Изменить размер шрифта
- шрифт интерфейса
```
Window -> Preferences -> User Interface -> Appearance -> Colors and Fonts -> DBeaver Fonts -> Main font.
```
- шрифт SQL редактора
```
Window > Preferences > User Interface > Appearance > Colors and Fonts > DBeaver Fonts > Monospace font.
```

### 3. Установка UpperCase для команд SQL

UpperCase установлен по умолчанию.
Если требуется корректировка: 
```
Window -> Preferences -> Editors -> SQL Editor -> Formatting -> KewwordCase: Upper
```
Проверьте себя: Зачем в SQL-редакторе DBeaver отдельно настраивается моноширинный шрифт, отличный от шрифта общего интерфейса программы?
13
MarkdownРазбор концепции26 строк

Установка pandas, mysql-connector-python и pymongo для Jupyter Notebook

13__Dbeaver_sqlite_mysql_PD/theory_02__install_pandas_and_mysql.md

Три команды pip install подряд — pandas (табличные данные), mysql-connector-python (подключение к MySQL из Python) и pymongo (заодно, впрок для MongoDB, чтобы не возвращаться к этому вопросу отдельно).

  • pip install pandas
  • pip install mysql-connector-python
  • pip install pymongo — впрок, для будущей темы MongoDB
Показать начало файла (26 строк всего)
### Установка pandas на Jupyter Notebook

```
pip install pandas
```

***


### Установка mysql-connector на Jupyter Notebook
```
pip install mysql-connector-python
```

***


### Установка pymongo на Jupyter Notebook

(Заодно, чтобы, как говорится "два раза не вставать")
```
pip install pymongo
```

***
Проверьте себя: Почему в файле про подключение к MySQL заодно ставится pymongo, хотя тема MongoDB ещё не началась?
14
MarkdownРазбор концепции112 строк

SQLite из Python: sqlite3, курсор как одноразовый итератор, tabulate

13__Dbeaver_sqlite_mysql_PD/theory_03__connect_to_sqlite.md

Пошаговое введение в модуль sqlite3 (входит в стандартную библиотеку, сервер не нужен, база — файл): подключение, создание таблицы users, вставка строки, чтение через fetchall(). Ключевой акцент — курсор является итератором и одноразовый: повторный fetchall() после того, как результат уже прочитан, вернёт пустой список. Отдельно — обязательность commit() (кроме серверов с autocommit=True) и приём с tabulate для красивого вывода таблицы с заголовками, извлечёнными из cursor.description.

  • sqlite3.connect('my_database.db') — файл БД создаётся автоматически
  • cursor.execute("CREATE TABLE users (...)") + conn.commit()
  • cursor.execute("INSERT INTO users ... VALUES (?, ?, ?)", (...)) — параметризованный запрос
  • cursor.fetchall() дважды — второй раз возвращает [] (курсор одноразовый)
  • for row in cursor: — курсор работает как итератор в цикле
  • headers = [col[0] for col in cursor.description] + tabulate() — красивый вывод
Показать начало файла (112 строк всего)
**SQLite** — это лёгкая встроенная система управления базами данных (СУБД), которая хранит всю базу в одном файле.

SQLite прекрасно подходит для 
* небольших проектов, 
* обучения SQL, 
* локального хранения данных без настройки отдельного сервера.


Особенности:

* **Не требует установки сервера** — работает прямо внутри программы.
* **Данные хранятся в файле** (например, `my_database.db`).
* **Поддерживает SQL-запросы** (`SELECT`, `INSERT`, `UPDATE`, `DELETE` и др.).
* **Входит в стандартную библиотеку Python** через модуль `sqlite3`.
* **`SQLite` не имеет встроенной системы пользователей и паролей** 
  * Доступ к базе определяется правами доступа к файлу БД.


### Подключение к базе данных

Создаём подключение к SQLite.  
* Пакет `sqlite3` уже в базовой конфигурации Python (ничего дополнительно инсталлировать не надо!)
* БД тоже специально создавать не надо:
  * Если файл БД `my_database.db` ещё не существует, он будет создан автоматически.

```python
import sqlite3

# Подключение к базе данных
conn = sqlite3.connect('my_database.db')

# Создание курсора для выполнения SQL-запросов
cursor = conn.cursor()
```

### Создание таблицы

Создаём таблицу `users` для хранения информации о пользователях.

```python
cursor.execute("""
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    age INTEGER,
    email TEXT
);
""")

# Сохраняем изменения в базе данных
conn.commit()
```

### Добавление данных в БД

Добавляем новую запись в таблицу `users`.

```python
cursor.execute(
    "INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
…
Проверьте себя: Почему второй вызов cursor.fetchall() после того же execute() возвращает пустой список, а не те же данные повторно?
15
PythonИсполняемый пример59 строк

Полный рабочий пример SQLite: создание таблицы, вставка, курсор-итератор, tabulate

13__Dbeaver_sqlite_mysql_PD/theory_04__connect_to_sqlite.py

Исполняемая версия примера из theory_03__connect_to_sqlite.md, собранная в один скрипт: создаёт (или переиспользует, IF NOT EXISTS) таблицу users в my_database.db, вставляет John Doe, явно проверяет через isinstance(cursor, Iterator), что курсор — итератор, демонстрирует одноразовость fetchall(), читает через for row in cursor, затем добавляет вторую запись Jane Doe и выводит итоговую таблицу через tabulate с форматом psql.

  • sqlite3.connect('my_database.db'); CREATE TABLE IF NOT EXISTS users
  • INSERT ... VALUES (?, ?, ?) с John Doe + commit()
  • isinstance(cursor, Iterator) — проверка, что курсор итератор
  • cursor.fetchall() дважды подряд — второй раз пусто
  • for row in cursor: — тот же результат через цикл
  • Вторая вставка (Jane Doe) + tabulate(rows, headers=..., tablefmt="psql")

Что выводит: Не запускался (по договорённости с ведущим агентом — для файлов, работающих с БД, вывод не подтверждается запуском). SQLite здесь не требует внешнего сервера — сработал бы локально при наличии установленного пакета tabulate. Ожидаемый эффект: файл my_database.db создаётся/пополняется в текущей директории; печатается True для isinstance-проверки, затем список из одной записи, затем пустой список, затем та же строка через for, и в конце — таблица из двух строк (John Doe, Jane Doe) в формате psql.

Начало файла
import sqlite3
from typing import Iterator

# Создаём коннектор - подключение к БД
conn = sqlite3.connect('my_database.db')

# Создание курсора для выполнения SQL-запросов
cursor = conn.cursor()


# Создаём таблицу `users` для хранения информации о пользователях.
q_create_table = """
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
Показать файл целиком (59 строк)
import sqlite3
from typing import Iterator

# Создаём коннектор - подключение к БД
conn = sqlite3.connect('my_database.db')

# Создание курсора для выполнения SQL-запросов
cursor = conn.cursor()


# Создаём таблицу `users` для хранения информации о пользователях.
q_create_table = """
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        age INTEGER,
        email TEXT
    );"""

cursor.execute(q_create_table)

# Сохраняем изменения в базе данных
conn.commit()

# Добавляем новую запись в таблицу `users`.

q_insert = "INSERT INTO users (name, age, email) VALUES (?, ?, ?);"
cursor.execute(q_insert,("John Doe", 25, "johndoe@example.com"))

# Сохраняем изменения
conn.commit()


# Получаем и выводим все записи из таблицы `users`.
cursor.execute("SELECT * FROM users;")

# Курсор - это итератор?
print("Курсор - это итератор?", isinstance(cursor, Iterator))
# Курсор - это итератор? True

print(cursor.fetchall())  # [(1, 'John Doe', 25, 'johndoe@example.com')]
print(cursor.fetchall())  # []

# То же самое с помощью цикла for
cursor.execute("SELECT * FROM users;")

for row in cursor:
    print(row)

# --- "Красивый" вывод таблицы в терминал: -------------------
cursor.execute(q_insert,("Jane Doe", 25, "janedoe@example.com"))
cursor.execute("SELECT * FROM users;")
rows = cursor.fetchall()

headers = [col[0] for col in cursor.description]

from tabulate import tabulate  # pip install tabulate

print(tabulate(rows, headers=headers, tablefmt="psql"))
Проверьте себя: Если запустить этот файл дважды подряд без удаления my_database.db, сколько записей John Doe окажется в таблице users после второго запуска, и почему?
Открыть файл →
16
MarkdownРазбор концепции108 строк

pandas + SQLite: создание таблицы из DataFrame через to_sql/read_sql_query

13__Dbeaver_sqlite_mysql_PD/theory_05__create_sql_table_by_pandas.md

Показывает связку pandas и sqlite3: DataFrame создаётся из словаря (ключи → колонки, списки → строки одинаковой длины), затем df.to_sql() записывает его как таблицу в SQLite без явного CREATE TABLE, с параметром if_exists (replace/fail/append), объясняя разницу между ними. Симметричный метод read_sql_query() выполняет SQL-запрос и сразу возвращает результат в виде DataFrame — самый удобный способ прочитать данные обратно.

  • data = {...}; df = pd.DataFrame(data) — словарь → таблица
  • sqlite3.connect('students.db') — подключение/создание файла БД
  • df.to_sql('new_table', conn, if_exists='replace', index=False)
  • if_exists: 'replace' / 'fail' / 'append' — три режима поведения
  • pd.read_sql_query('SELECT * FROM new_table', conn) — чтение обратно в DataFrame
Показать начало файла (108 строк всего)
## Создание SQL таблицы с помощью DataFrame (pandas + SQLite)

```python
import pandas as pd
import sqlite3
```

### Что такое `pandas`?:

* `pandas` — библиотека для работы с табличными данными (DataFrame)
* `sqlite3` — встроенный модуль Python для работы с SQLite
* В отличии от `sqlite3`, `pandas` является внешней библиотекой. 
  * Поэтому, требует предварительной инсталляции:`pip install pandas`
* Вместе они позволяют легко:
  * создавать таблицы из DataFrame
  * сохранять данные в базу данных
  * читать данные обратно в DataFrame

---

### Создание DataFrame

```python
# Создаём словарь с данными
data = {
    'column1': ['value1', 'value2', 'value3'],
    'column2': ['value1', 'value2', 'value3'],
    'column3': ['value1', 'value2', 'value3'],
}

# Преобразуем словарь в DataFrame
df = pd.DataFrame(data)

# Выводим таблицу
print(df)
```

### Что такое `DataFrame`?

* `DataFrame` — это таблица (как в Excel)
* ключи словаря → названия колонок
* списки → строки значений
* все столбцы должны быть одинаковой длины

---

### Загрузка DataFrame в SQLite

#### 1. Создаём подключение к СУБД SQLite

```python
# Подключение к базе данных (файл создаётся автоматически, если его нет)
conn = sqlite3.connect('students.db')
```

#### 2. `pandas` содержит встроенный метод `to_sql`, благодаря чему

* без использования команды `CREATE TABLE` создаётся файл базы `students.db`
  * если файл уже есть — просто открывается
  * это “точка входа” в базу данных
…
Проверьте себя: Чем отличаются друг от друга режимы if_exists='replace' и if_exists='append' при повторном запуске одного и того же скрипта?
17
PythonИсполняемый пример48 строк

Исполняемая версия: DataFrame → SQLite → обратно в DataFrame

13__Dbeaver_sqlite_mysql_PD/theory_06__create_sql_table_by_pandas.py

Рабочий скрипт из theory_05: создаёт DataFrame из трёх колонок с тремя строками, сохраняет его в students.db как new_table через to_sql(if_exists='replace'), затем немедленно читает эту же таблицу обратно через read_sql_query и печатает оба DataFrame — до записи и после чтения — которые должны совпадать по содержимому.

  • data = {...}; df = pd.DataFrame(data); print(df) — исходная таблица
  • conn = sqlite3.connect('students.db')
  • df.to_sql('new_table', conn, if_exists='replace', index=False)
  • df_from_db = pd.read_sql_query('SELECT * FROM new_table', conn); print(df_from_db)

Что выводит: Не запускался (по договорённости — работа с БД не выполняется вживую). SQLite здесь локальный файл, внешний сервер не нужен; пакет pandas должен быть установлен. Ожидаемый эффект (соответствует комментариям в самом файле): дважды печатается одна и та же таблица 3×3 со значениями value1/value2/value3 в трёх столбцах column1/column2/column3, до записи в students.db и после чтения оттуда.

Начало файла
import pandas as pd
import sqlite3

# Создаём словарь с данными
data = {
    'column1': ['value1', 'value2', 'value3'],
    'column2': ['value1', 'value2', 'value3'],
    'column3': ['value1', 'value2', 'value3'],
}

# Преобразуем словарь в DataFrame
df = pd.DataFrame(data)

# Выводим таблицу
Показать файл целиком (48 строк)
import pandas as pd
import sqlite3

# Создаём словарь с данными
data = {
    'column1': ['value1', 'value2', 'value3'],
    'column2': ['value1', 'value2', 'value3'],
    'column3': ['value1', 'value2', 'value3'],
}

# Преобразуем словарь в DataFrame
df = pd.DataFrame(data)

# Выводим таблицу
print(df)

#   column1 column2 column3
# 0  value1  value1  value1
# 1  value2  value2  value2
# 2  value3  value3  value3


# 1. Создаём подключение к СУБД SQLite
conn = sqlite3.connect('students.db')

# 2. `pandas` содержит встроенный метод `to_sql`, благодаря чему
df.to_sql(
    'new_table',   # имя таблицы в БД
    conn,          # подключение к базе
    if_exists='replace',  # заменить таблицу, если она уже существует
    index=False    # не сохранять индекс pandas как отдельный столбец
)

# Выполняем SQL-запрос и сразу получаем DataFrame
df_from_db = pd.read_sql_query(
    'SELECT * FROM new_table',
    conn
)

# Вывод результата
print(df_from_db)

#   column1 column2 column3
# 0  value1  value1  value1
# 1  value2  value2  value2
# 2  value3  value3  value3


Проверьте себя: Почему print(df) и print(df_from_db) в конце файла печатают одинаковые данные, хотя один DataFrame получен из словаря в памяти, а другой — SQL-запросом к файлу на диске?
Открыть файл →
18
PythonИсполняемый пример31 строк

Подключение к реальному серверу MySQL (база sakila) через mysql.connector

13__Dbeaver_sqlite_mysql_PD/theory_07__get_access_to_mysql.py

Показывает подключение к внешнему серверу MySQL через пакет mysql.connector с параметрами, вынесенными в отдельный файл local_settings.py (dbconfig как **kwargs). После подключения скрипт получает список всех таблиц через SHOW TABLES и выводит содержимое таблицы category (жанры) из учебной базы sakila, распаковывая строки через id, genre, *_ (отбрасывая лишние колонки).

  • import mysql.connector; from local_settings import dbconfig
  • mysql.connector.connect(**dbconfig) — подключение с распаковкой словаря настроек
  • cursor.execute("SHOW TABLES;") — список таблиц базы
  • cursor.execute("SELECT * FROM category;") + for id, genre, *_ in cursor: — распаковка с отбрасыванием лишних полей

Что выводит: Не запускался: скрипт требует живого подключения к серверу MySQL и реальных учётных данных в local_settings.py — в репозитории лежит только шаблон _local_settings.py с пустыми полями HOST/USER и PASSWORD='********', так что без правки реального доступа к серверу нет. Ожидаемый эффект при рабочем подключении: печать списка всех таблиц базы sakila, затем построчный вывод id и названия жанра из таблицы category.

Начало файла
"""
Пакет mysql.connector внешней, поэтому требует предварительной инсталляции:

pip install mysql-connector-python

Кроме того, требуется сохранить в отдельном файле local_settings.py параметры подключения
"""

import mysql.connector
from local_settings import dbconfig


connection = mysql.connector.connect(**dbconfig)
Показать файл целиком (31 строк)
"""
Пакет mysql.connector внешней, поэтому требует предварительной инсталляции:

pip install mysql-connector-python

Кроме того, требуется сохранить в отдельном файле local_settings.py параметры подключения
"""

import mysql.connector
from local_settings import dbconfig


connection = mysql.connector.connect(**dbconfig)

cursor = connection.cursor()


# Получение списка таблиц
cursor.execute("SHOW TABLES;")
tables = cursor.fetchall()

# Вывод списка таблиц
print("Список таблиц в базе данных sakila:")
for table in tables:
    print(table[0])


print("Список жанров из БД sakila:")
cursor.execute("SELECT * FROM category;")
for id, genre, *_ in cursor:
    print(id, genre)
Проверьте себя: Скрипт импортирует `from local_settings import dbconfig`, а файл в репозитории называется `_local_settings.py` (с подчёркиванием) — сработает ли такой импорт без изменений, и почему это важно проверить перед запуском?
Открыть файл →