【发布时间】:2010-12-24 20:26:24
【问题描述】:
如何使用 Psycopg2 Python 库确定表是否存在?我想要一个真或假布尔值。
【问题讨论】:
标签: python postgresql psycopg2
如何使用 Psycopg2 Python 库确定表是否存在?我想要一个真或假布尔值。
【问题讨论】:
标签: python postgresql psycopg2
怎么样:
>>> import psycopg2
>>> conn = psycopg2.connect("dbname='mydb' user='username' host='localhost' password='foobar'")
>>> cur = conn.cursor()
>>> cur.execute("select * from information_schema.tables where table_name=%s", ('mytable',))
>>> bool(cur.rowcount)
True
使用 EXISTS 的替代方法更好,因为它不需要检索所有行,而只需至少存在一个这样的行:
>>> cur.execute("select exists(select * from information_schema.tables where table_name=%s)", ('mytable',))
>>> cur.fetchone()[0]
True
【讨论】:
exists()。 :)
where 条件的第一行,而rowcount 则必须检索所有行。
exists() 解决方案,但您应该使用cur.fetcone()[0] 而不是bool(cur.rowcount)(此请求总是返回一个值,其中第一列是exists() 结果,True 或False)
psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block
我不知道具体的 psycopg2 库,但是可以使用以下查询来检查表是否存在:
SELECT EXISTS(SELECT 1 FROM information_schema.tables
WHERE table_catalog='DB_NAME' AND
table_schema='public' AND
table_name='TABLE_NAME');
与直接从 pg_* 表中选择相比,使用 information_schema 的优势在于查询的某种程度的可移植性。
【讨论】:
select exists(select relname from pg_class
where relname = 'mytablename' and relkind='r');
【讨论】:
第一个答案对我不起作用。我发现成功检查了 pg_class 中的关系:
def table_exists(con, table_str):
exists = False
try:
cur = con.cursor()
cur.execute("select exists(select relname from pg_class where relname='" + table_str + "')")
exists = cur.fetchone()[0]
print exists
cur.close()
except psycopg2.Error as e:
print e
return exists
【讨论】:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import psycopg2
import sys
con = None
try:
con = psycopg2.connect(database='testdb', user='janbodnar')
cur = con.cursor()
cur.execute('SELECT 1 from mytable')
ver = cur.fetchone()
print ver //здесь наш код при успехе
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
【讨论】:
我知道你要求 psycopg2 答案,但我想我会添加一个基于 pandas 的实用程序函数(它在引擎盖下使用 psycopg2),只是因为 pd.read_sql_query() 让事情变得如此方便,例如避免创建/关闭游标。
import pandas as pd
def db_table_exists(conn, tablename):
# thanks to Peter Hansen's answer for this sql
sql = f"select * from information_schema.tables where table_name='{tablename}'"
# return results of sql query from conn as a pandas dataframe
results_df = pd.read_sql_query(sql, conn)
# True if we got any results back, False if we didn't
return bool(len(results_df))
我仍然使用 psycopg2 创建 db-connection 对象conn,类似于此处的其他答案。
【讨论】:
您可以查看pg_class目录:
目录 pg_class 目录表和大多数其他有 列或在其他方面类似于表。这包括索引(但 另见 pg_index),序列(但另见 pg_sequence),视图, 物化视图、复合类型和 TOAST 表;见relkind。 下面,当我们指的是我们所说的所有这些类型的对象时 “关系”。并非所有列对所有关系类型都有意义。
假设以cur为光标打开连接,
cur.execute("SELECT EXISTS(SELECT relname FROM pg_class WHERE relname = 'mytable');")
if cur.fetchone()[0]:
# if table exists, do something here
return True
cur.fetchone() 将解析为 True 或 False,因为 EXISTS() 函数。
【讨论】:
以下解决方案也处理schema:
import psycopg2
with psycopg2.connect("dbname='dbname' user='user' host='host' port='port' password='password'") as conn:
cur = conn.cursor()
query = "select to_regclass(%s)"
cur.execute(query, ['{}.{}'.format('schema', 'table')])
exists = bool(cur.fetchone()[0])
【讨论】:
扩展上述 EXISTS 的使用,我需要一些东西来测试表的存在性。我发现在 select 语句上使用 fetch 测试结果会在现有的空表上产生结果“None”——不理想。
这是我想出的:
import psycopg2
def exist_test(tabletotest):
schema=tabletotest.split('.')[0]
table=tabletotest.split('.')[1]
existtest="SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = '"+schema+"' AND table_name = '"+table+"' );"
print('existtest',existtest)
cur.execute(existtest) # assumes youve already got your connection and cursor established
# print('exists',cur.fetchall()[0])
return ur.fetchall()[0] # returns true/false depending on whether table exists
exist_test('someschema.sometable')
【讨论】: