Я использую 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?
РЕДАКТИРОВАТЬ
Обратите внимание, что я хотел бы проверить наличие таблицы в базе данных, к которой я подключен, я не возражаю, если она существует в другой базе данных.
Должен ли я отформатировать строку как %s
?
Смотрите мой ответ ниже.
так что вы можете перейти к ошибке, используя 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
Я не думаю, что это надежно, потому что могут быть сгенерированы другие несвязанные исключения
Мой комментарий в качестве ответа:
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?
@ФранческоБой. pg_tables
показывает только таблицы для базы данных, в которой вы выполняете запрос. Для запуска непосредственно в psql
выполните: SELECT count(*) FROM pg_tables WHERE schemaname='public' AND tablename= <some_table>
или вы просите что-то еще?
@AdrianKavler Судя по результатам, которые я получаю, это не так.
Какой запрос вы выполняете и каков результат? Если вы получаете количество> 0, эта таблица находится в базе данных.
tbl_sql = "SELECT count(*) FROM pg_tables WHERE schemaname='public' AND tablename= %s"
; cursor.execute(tbl_sql, ('myTable',))
; cursor.fetchone()
. Проблема в том, что он возвращает 1
, но myTable
не является таблицей базы данных, к которой я подключен (production
в примерах), а является таблицей другой базы данных.
Затем либо вы подключены к другому экземпляру Postgres, у которого он есть, либо он находится в базе данных production
. pg_tables
будет отображать только таблицы в базе данных, в которой он запущен. Чтобы проверить в psql -d production
, выполните: \dt myTable
и \dt "myTable"
Хорошо, в методе connect
отсутствовал параметр: мне не хватало параметра dbname
, извините. Кстати, тоже SELECT exists(SELECT * FROM pg_tables WHERE schemaname='public' AND tablename= %s)
работает.
Почему бы не
select count(*) AS tbl_ct from pg_tables where schemaname='public' AND tablename='mytable'
, а затем проверить наtbl_ct > 0
? Не используйтеsql.Identifier
для имени таблицы. Это значение, а не идентификатор.