psycopg2 为什么没有创建架构?
psycopg2 why is the schema not created?
我正在尝试使用 psycopg2 在 postgres 数据库中创建模式。
由于某种原因,未创建架构,随后代码崩溃,因为它试图引用丢失的架构。连接设置为自动提交模式,这绝对有效,因为我可以使用此特定连接创建数据库。
出于调试目的,我将每一步都包含在它自己的 try/except 语句中。
代码如下,因为它就在那里,它不会引发任何异常,只是后续崩溃,因为模式丢失。
def createDB(dbName, connString):
conn = psycopg2.connect(connString)
conn.set_session(autocommit =True) # autocommit must be True sein, else CREATE DATABASE will fail https://www.psycopg.org/docs/usage.html#transactions-control
cursor = conn.cursor()
createDB = sql.SQL('CREATE DATABASE {};').format(
sql.Identifier(dbName)
)
createSchema = sql.SQL('CREATE SCHEMA IF NOT EXISTS schema2;')
searchpath = sql.SQL('ALTER DATABASE {} SET search_path TO public, schema2;').format(
sql.Identifier(dbName)
)
dropDB = sql.SQL('DROP DATABASE IF EXISTS {};').format(
sql.Identifier(dbName)
)
try:
cursor.execute(dropDB)
except Exception as e:
print('drop DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createDB)
except Exception as e:
print('create DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createSchema)
print('schema created')
except Exception as e:
print('create schema failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(searchpath)
except Exception as e:
print('set searchpath failed')
logging.error(e)
conn.close()
exit()
conn.close()
添加显式提交也无济于事。
我错过了什么?
编辑
我在控制台日志中添加了一个小屏幕截图。如您所见,下面的代码被执行了。
编辑 2
出于纯粹的好奇心,我试图在 pgadmin 中执行这个非常 SQL 的语句:
CREATE SCHEMA IF NOT EXISTS schema2
它工作得很好,这表明我的 SQL 没有错,所以回到第一个问题。
编辑 3 -- 解决方案
所以我想出了一个解决方案,感谢@jjanes 为我指明了正确的方向。这个函数不连接到特定的数据库,而是连接到整个服务器,因为我用它来创建新的数据库,因此连接字符串看起来像这样:
user=postgres password=12345 host=localhost port=5432
这让我可以执行服务器级别的操作,例如创建和删除数据库。但是模式是数据库级别的操作。将完全相同的逻辑移动到连接到新创建的数据库的代码部分就像一个魅力。
您在连接字符串指定的原始数据库中创建了架构。创建新数据库后,您需要连接到它才能在其中工作。否则,您只是在旧数据库中工作。
我正在尝试使用 psycopg2 在 postgres 数据库中创建模式。
由于某种原因,未创建架构,随后代码崩溃,因为它试图引用丢失的架构。连接设置为自动提交模式,这绝对有效,因为我可以使用此特定连接创建数据库。
出于调试目的,我将每一步都包含在它自己的 try/except 语句中。
代码如下,因为它就在那里,它不会引发任何异常,只是后续崩溃,因为模式丢失。
def createDB(dbName, connString):
conn = psycopg2.connect(connString)
conn.set_session(autocommit =True) # autocommit must be True sein, else CREATE DATABASE will fail https://www.psycopg.org/docs/usage.html#transactions-control
cursor = conn.cursor()
createDB = sql.SQL('CREATE DATABASE {};').format(
sql.Identifier(dbName)
)
createSchema = sql.SQL('CREATE SCHEMA IF NOT EXISTS schema2;')
searchpath = sql.SQL('ALTER DATABASE {} SET search_path TO public, schema2;').format(
sql.Identifier(dbName)
)
dropDB = sql.SQL('DROP DATABASE IF EXISTS {};').format(
sql.Identifier(dbName)
)
try:
cursor.execute(dropDB)
except Exception as e:
print('drop DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createDB)
except Exception as e:
print('create DB failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(createSchema)
print('schema created')
except Exception as e:
print('create schema failed')
logging.error(e)
conn.close()
exit()
try:
cursor.execute(searchpath)
except Exception as e:
print('set searchpath failed')
logging.error(e)
conn.close()
exit()
conn.close()
添加显式提交也无济于事。 我错过了什么?
编辑 我在控制台日志中添加了一个小屏幕截图。如您所见,下面的代码被执行了。
编辑 2 出于纯粹的好奇心,我试图在 pgadmin 中执行这个非常 SQL 的语句:
CREATE SCHEMA IF NOT EXISTS schema2
它工作得很好,这表明我的 SQL 没有错,所以回到第一个问题。
编辑 3 -- 解决方案
所以我想出了一个解决方案,感谢@jjanes 为我指明了正确的方向。这个函数不连接到特定的数据库,而是连接到整个服务器,因为我用它来创建新的数据库,因此连接字符串看起来像这样:
user=postgres password=12345 host=localhost port=5432
这让我可以执行服务器级别的操作,例如创建和删除数据库。但是模式是数据库级别的操作。将完全相同的逻辑移动到连接到新创建的数据库的代码部分就像一个魅力。
您在连接字符串指定的原始数据库中创建了架构。创建新数据库后,您需要连接到它才能在其中工作。否则,您只是在旧数据库中工作。