Не работает условие if... then...

Kim Jon

Новичок
Пользователь
Авг 1, 2021
22
2
3
риветствую Друзья!!!
Наконец-то я дошел до своей любимой темы - "Создание Базы Данных". И столкнулся не понятной мне ситуации (который день я потею над ним....) иными словами просто взрыв мозга....
Суть проблемы вот в чем...... Написав код по созданию таблицы (листинг ниже):
Код:
from PyQt6 import QtWidgets, QtSql
import sys

app = QtWidgets.QApplication(sys.argv)
con = QtSql.QSqlDatabase.addDatabase('QSQLITE')
con.setDatabaseName('data.sqlite')
con.open()
# Проверим есть ли в базе данных таблица good, и, если таковой нет,
# создаём её SQL-командой CREATE TABLE
if 'good' not in con.tables():
    query = QtSql.QSqlQuery()
    query.exec("create table good (id integer primary key autoincrement," + "goodname text, goodcount integer)")
con.close()

При запуске скрипта таблица не создается, но если закомментировать условие: if 'good' not in con.tables():
аблица создается. Я знаю многие скажут поставь SQL ниже а в условие напиши Print("Таблица не найдена") или что-то в этом роде. И я с этим соглашусь. Мне просто очень нужно знать на будущее, при каких случаях может не сработать условиях try... except..., if .... then....и другие.
Пожалуйста подскажите в чем здесь неправильно (если можно по подробнее). Заранее благодарю Вас!!!
 
  • Мне нравится
Реакции: Dr. Mundo

Dr. Mundo

Модератор
Команда форума
Модератор
Фев 13, 2024
26
1
3
Ниже разберём основные причины, почему условие if 'good' not in con.tables(): может вести себя «странно» и в итоге мешать созданию таблицы.

1. Таблица «good» уже существует в базе, а вы смотрите не туда​

Частый сценарий с SQLite:
  • Скрипт уже когда-то успешно создал таблицу «good»,
  • Файл data.sqlite лежит в том же каталоге (или в каком-то другом),
  • При запуске проверка if 'good' not in con.tables(): возвращает False, потому что в этой базе таблица уже есть.
Но вы, возможно, смотрите в другую копию data.sqlite (или просто не обновили вкладку в какой-нибудь SQLite-браузере и не видите там таблицу).
Попробуйте:

Python:
print(con.databaseName())        # посмотрите, какой именно файл открыт
print(con.tables())              # выведите все таблицы

Если в выводе будет ['good'], значит таблица уже там.
Если файл не тот, что ожидается, — поправьте путь в con.setDatabaseName(...).


2. Проверка проходит, но ничего не происходит из-за проблем с открытием базы​

Иногда база не открывается (например, из-за отсутствия прав записи или к базе нет доступа).
Убедитесь, что:

Python:
if not con.open():
    print("Не удалось открыть базу данных!", con.lastError().text())

Если база не открывается, con.tables() будет выдавать пустой список (в большинстве случаев). Но тогда и query.exec(...) работать корректно не будет. В таких случаях всегда проверяйте результат open() и lastError().


3. Неявная транзакция не подтверждена (редко, но бывает)​

В стандартном режиме SQLite в PyQt/QT-SQL изменения, как правило, применяются сразу (Auto-commit). Но если вы вдруг включили транзакции вручную (например, con.transaction()), нужно после query.exec(...) вызвать con.commit(). Иначе изменения не сохранятся.
В вашем коде транзакций не видно, так что, скорее всего, это не ваш случай.


4. Особенности регистров и имён таблиц​

con.tables() возвращает список таблиц в том виде, в каком они хранятся в метаданных СУБД. Обычно SQLite приводит имена к нижнему регистру, но всякое бывает.
Чаще всего, если вы создали таблицу good, в списке тоже будет 'good'. Но на всякий случай можно сделать:

Python:
tables_in_db = [t.lower() for t in con.tables()]
if 'good' not in tables_in_db:
    ...

Таким образом вы исключите «шальные» расхождения по регистру (но в обычной практике с SQLite это не проблема).

5. Вы не закрыли соединение или не освободили курсор перед con.tables()​

Иногда (особенно в более старых версиях PyQt5/PyQt6) после query.exec(...) нужно «освободить» этот query, прежде чем вызывать con.tables(). Но в вашем примере порядок такой:
  1. con.open()
  2. if 'good' not in con.tables(): ...
  3. con.close()
— здесь всё выглядит нормально. Если таблица не существовала, она должна создаться. Если она была, то if ... not in ... не сработает.

6. Наконец, самый банальный сценарий: логика​

Если вы раньше уже запускали этот скрипт с закомментированным if и таблица успешно создалась, то теперь:
  1. Таблица физически уже есть в data.sqlite.
  2. Естественно, if 'good' not in con.tables() вернёт False.
  3. Строка с create table ... не выполняется.
  4. Вы смотрите в «тот же» data.sqlite и говорите: «Почему она не создаётся?!» — потому что она уже существует.

Что делать, чтобы «убедиться»?​

  1. Удалите или переименуйте файл data.sqlite, чтобы начать «с чистого листа».
  2. Запустите ваш код снова с условием if 'good' not in con.tables():.
  3. Добавьте отладочные print(...):
    Python:
    from PyQt6 import QtWidgets, QtSql
    import sys
    
    app = QtWidgets.QApplication(sys.argv)
    con = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    con.setDatabaseName('data.sqlite')
    
    if not con.open():
        print("Не удалось открыть базу данных:", con.lastError().text())
    else:
        print("База данных открыта:", con.databaseName())
        print("Таблицы в БД до проверки:", con.tables())
    
        if 'good' not in con.tables():
            print("Таблица 'good' не найдена, создаём...")
            query = QtSql.QSqlQuery()
            res = query.exec("CREATE TABLE good ("
                             "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "goodname TEXT, "
                             "goodcount INTEGER)")
            print("Результат CREATE TABLE =", res, "Ошибки:", query.lastError().text())
        else:
            print("Таблица 'good' уже существует, пропускаем создание.")
    
    con.close()
  4. После выполнения посмотрите, что выведется.
    • Если увидите: «Таблица 'good' уже существует» и в итоге таблица там действительно есть, значит всё нормально.
    • Если вывелось, что таблица не найдена, а потом «Результат CREATE TABLE = True», значит она создалась.
    • Если выводятся ошибки (например, «unable to open database file»), нужно разбираться с правами/путями.

В итоге​

Судя по всему, в вашем случае причина проста: таблица «good» уже есть, поэтому условие if 'good' not in con.tables(): не выполняется. Именно поэтому при закомментированной проверке (вызывается create table без всяких условий) вы «замечаете», что таблица «будто бы создаётся».

Это нередкая ситуация при работе с локальными файлами SQLite:
  • люди забывают, что файл «data.sqlite» уже где-то лежит,
  • скрипт (или IDE) запускается из другой папки,
  • а потом удивляются, почему при проверке con.tables() всегда видна эта таблица.
Попробуйте по шагам проверить пути/файлы, удалить «старый» data.sqlite и добавить print(...) в отладку — всё станет ясно.

Удачи в дальнейшей разработке!
 

Форум IT Специалистов