Как проверить наличие столбца в базе данных Postgres, к которой я подключен в Python?

Я использую postgres в Python с библиотекой psycopg2. После подключения к базе данных я пытаюсь проверить, существует ли таблица с заданным именем. В postgres я делаю это со следующими строками:

\connect myDB
select exists(select * from pg_tables where schemaname='public' AND tablename='mytable';)

Это работает, если таблица существует, но также и в том случае, если ее нет. В python я делаю это со следующими строками:

import psycopg2 as pg
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT;
from psycopg2 import sql;

conn = pg.connect(user='postgres', host='localhost', password = "pwd");
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT);
conn.autocommit = True
sql_table_check = sql.SQL("select exists(select * from pg_tables where schemaname='public' AND tablename = {});")\
        .format(sql.Identifier("mytable"));
cur = conn.cursor()

но это возвращает ошибку

psycopg2.errors.UndefinedColumn: column "mytable" does not exist
LINE 1: ...m pg_tables where schemaname='public' AND tablename = "mytable");

потому что такая таблица еще не создана.

Как правильно проверить, существует ли столбец в psycopg2?

РЕДАКТИРОВАТЬ

Обратите внимание, что я хотел бы проверить наличие таблицы в базе данных, к которой я подключен, я не возражаю, если она существует в другой базе данных.

Почему бы не select count(*) AS tbl_ct from pg_tables where schemaname='public' AND tablename='mytable', а затем проверить на tbl_ct > 0? Не используйте sql.Identifier для имени таблицы. Это значение, а не идентификатор.

Adrian Klaver 12.12.2020 19:38

Должен ли я отформатировать строку как %s?

roschach 12.12.2020 19:42

Смотрите мой ответ ниже.

Adrian Klaver 12.12.2020 19:44
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
468
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

так что вы можете перейти к ошибке, используя try и except, чтобы продолжить

sql_table_check = sql.SQL("select exists(select * from pg_tables where schemaname='public' AND tablename = {});")\
        .format(sql.Identifier("mytable"));
try:
    cur = conn.cursor()
    print('Table exists')
except:
    print('Table does not exist')

Отредактировано на основе комментария

вы также можете поймать ошибку, чтобы проверить ее позже,

sql_table_check = sql.SQL("select exists(select * from pg_tables where schemaname='public' AND tablename = {});")\
        .format(sql.Identifier("mytable"));
try:
    cur = conn.cursor()
    print('Table exists')
except Exception as e:
    print(e)
    print('Table does not exist')

например, и просто, если мы попробуем:

try:
    a = 5 / 0
except Exception as e:
    print(e)

Мы получим вывод

division by zero

вы можете получить точную строку формата путем отладки содержимого e в части исключения.

поэтому мы можем затем использовать это для идентификации ошибки, чтобы использовать ее снова, например:

try:
    a = a / 0
except Exception as e:
    print(e)
    if e.args[0] == 'division by zero':
        print('it is division by zero Error')
    else:
        raise(e)

поэтому, если ошибка не является предполагаемой, возникнет другая ошибка.

вы можете получить исключение ошибки из psycopg2 документации, как и для python в https://docs.python.org/3/library/exceptions.html

как в следующем коде:

try:
    a = 5 / 0
except ZeroDivisionError:
    print('it is division by zero Error')

так что мы получаем:

it is division by zero Error

но когда у нас есть другая ошибка, например:

try:
    a = 5 / 0
except ZeroDivisionError:
    print('it is division by zero Error')

мы получаем другую ошибку

NameError: name 'b' is not defined

Я не думаю, что это надежно, потому что могут быть сгенерированы другие несвязанные исключения

roschach 12.12.2020 19:41
Ответ принят как подходящий

Мой комментарий в качестве ответа:

import psycopg2

con = psycopg2.connect("dbname=production host=localhost user=postgres")
tbl_sql = "SELECT count(*) FROM pg_tables WHERE schemaname='public' AND tablename= %s"
cur = con.cursor()
cur.execute(tbl_sql, ('cell_per',))
cur.fetchone()
(1,)

cur.execute(tbl_sql, ('cell_p',))
cur.fetchone()
(0,)

Существует проблема с этим кодом: если таблица с таким же именем существует в другой базе данных, но не в базе данных, к которой я подключен, ваш ответ, похоже, возвращает, что таблица существует. Кроме того, как я могу запустить этот запрос непосредственно на postgres?

roschach 24.12.2020 15:40

@ФранческоБой. pg_tables показывает только таблицы для базы данных, в которой вы выполняете запрос. Для запуска непосредственно в psql выполните: SELECT count(*) FROM pg_tables WHERE schemaname='public' AND tablename= <some_table> или вы просите что-то еще?

Adrian Klaver 24.12.2020 16:14

@AdrianKavler Судя по результатам, которые я получаю, это не так.

roschach 24.12.2020 16:48

Какой запрос вы выполняете и каков результат? Если вы получаете количество> 0, эта таблица находится в базе данных.

Adrian Klaver 24.12.2020 17:35
tbl_sql = "SELECT count(*) FROM pg_tables WHERE schemaname='public' AND tablename= %s"; cursor.execute(tbl_sql, ('myTable',)); cursor.fetchone(). Проблема в том, что он возвращает 1, но myTable не является таблицей базы данных, к которой я подключен (production в примерах), а является таблицей другой базы данных.
roschach 24.12.2020 18:41

Затем либо вы подключены к другому экземпляру Postgres, у которого он есть, либо он находится в базе данных production. pg_tables будет отображать только таблицы в базе данных, в которой он запущен. Чтобы проверить в psql -d production, выполните: \dt myTable и \dt "myTable"

Adrian Klaver 24.12.2020 18:49

Хорошо, в методе connect отсутствовал параметр: мне не хватало параметра dbname, извините. Кстати, тоже SELECT exists(SELECT * FROM pg_tables WHERE schemaname='public' AND tablename= %s) работает.

roschach 24.12.2020 20:44

Другие вопросы по теме