LINUX.ORG.RU

Взаимодействие Python и Mysql

 ,


0

1

Разбираюсь с БД. Написал пару скриптов(делающих одно и то же) для добавления пользователя в бд если его там нет. Оба варианта работают, но возник ряд вопросов.

Первый вариант.

  • Здесь три запроса. Первые два выполняются в одной транзакции и еще один в другой? Логика была такая: если пользователь отсутствует, то сразу добавляем, иначе между поиском и добавлением может вклиниться еще один запрос и получится в таблице два пользователя с одинаковыми логинами.
  • После последнего select нужно делать commit? Вообще, когда мы не вносим изменения commit делается?
import mysql.connector

dbconfig = {
	'host': 'localhost',
	'user': 'root',
	'password': '010',
	'database': 'testdb'
}

conn = mysql.connector.connect(**dbconfig)
cursor = conn.cursor()
login = 'user4'
cursor.execute("SELECT * FROM USER WHERE login=%s", (login,))
users = cursor.fetchall()
if len(users) == 0:
	cursor.execute('INSERT INTO USER(login) VALUES(%s)', (login,))
	conn.commit()
	cursor.execute("SELECT * FROM USER WHERE login=%s", (login,))
	users = cursor.fetchall()
	if len(users) > 0:
		print('Пользователь добавлен!')
	else:
		print('Ошибка записи')
else:
	print('Пользователь существует!')
conn.commit()
cursor.close()
conn.close()

Второй вариант(использовал диспетчер контекста).

  • Здесь все запросы выполняются в одной транзакции? Верно?
  • Последний запрос(SELECT) видит изменения даже если коммит не выполнен. Я так понимаю изменения кешируются и запросы на выборку тоже учитывают эти не примененные изменения? Если так, то всегда ли эти изменения(до выполнения commit) будут учитываться?
  • Если все действия успешно выполнены(три запроса) может commit(в exit) не выполниться?
import mysql.connector

dbconfig = {
	'host': 'localhost',
	'user': 'root',
	'password': '010',
	'database': 'testdb'
}

class UseDatabase:

  def __init__(self, config: dict) -> None:
    self.configuration = config

  def __enter__(self) -> 'cursor':
    self.conn = mysql.connector.connect(**self.configuration)
    self.cursor = self.conn.cursor()
    return self.cursor

  def __exit__(self, exc_type, exc_value, exc_trace) -> None:
    self.conn.commit()
    self.cursor.close()
    self.conn.close()

with UseDatabase(dbconfig) as cursor:
	login = 'user1'
	cursor.execute("SELECT * FROM USER WHERE login=%s", (login,))
	users = cursor.fetchall()
	if len(users) == 0:
		cursor.execute('INSERT INTO USER(login) VALUES(%s)', (login,))
		cursor.execute("SELECT * FROM USER WHERE login=%s", (login,))
		users = cursor.fetchall()
		if len(users) > 0:
			print('Пользователь добавлен!')
		else:
			print('Ошибка записи')
	else:
		print('Пользователь существует!')



Ты хочешь INSERT IGNORE + SELECT

commit

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

no-such-file ★★★★★
()

Код не читал, в логику не вникал. Из первого абзаца очевидно, что тебе нужно unique constraint. Транзакции тут вообще не в тему.

WitcherGeralt ★★
()

Делать коммит на select бессмысленно. Есть смысл только на вставку или обновление.

dicos ★★
()
Ответ на: комментарий от VirRaa

Ну и select count(*) вместо получения списка всех пользователей. Да и вообще:

$ pip install poetry

$ cd ~/Development
$ poetry new school-project && cd school-project
$ poetry add sqlalchemy mysql-connector-python

$ poetry -h

А дальше читать про этот SQLAlchemy.

tz4678 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.