问题:如何使用SQLAlchemy创建新数据库?

使用SQLAlchemy,将创建一个Engine对象,如下所示:

from sqlalchemy import create_engine
engine = create_engine("postgresql://localhost/mydb")

engine如果在参数create_engine(在这种情况下为mydb)中指定的数据库不存在,则访问将失败。如果指定的数据库不存在,是否可以告诉SQLAlchemy创建一个新数据库?

Using SQLAlchemy, an Engine object is created like this:

from sqlalchemy import create_engine
engine = create_engine("postgresql://localhost/mydb")

Accessing engine fails if the database specified in the argument to create_engine (in this case, mydb) does not exist. Is it possible to tell SQLAlchemy to create a new database if the specified database doesn’t exist?


回答 0

在postgres上,默认情况下通常存在三个数据库。如果您能够以超级用户身份(例如,postgres角色)进行连接,则可以连接到postgrestemplate1数据库。默认的pg_hba.conf仅允许名为unix的用户postgres使用该postgres角色,因此最简单的方法就是成为该用户。无论如何,使用有权创建数据库的用户照常创建引擎:

>>> engine = sqlalchemy.create_engine("postgres://postgres@/postgres")

engine.execute()但是,您无法使用,因为postgres不允许您在事务内部创建数据库,而sqlalchemy始终尝试在事务中运行查询。要解决此问题,请从引擎获取基础连接:

>>> conn = engine.connect()

但是连接仍将在事务内部,因此您必须使用以下命令结束打开的事务commit

>>> conn.execute("commit")

然后,您可以使用适当的PostgreSQL命令继续创建数据库。

>>> conn.execute("create database test")
>>> conn.close()

On postgres, three databases are normally present by default. If you are able to connect as a superuser (eg, the postgres role), then you can connect to the postgres or template1 databases. The default pg_hba.conf permits only the unix user named postgres to use the postgres role, so the simplest thing is to just become that user. At any rate, create an engine as usual with a user that has the permissions to create a database:

>>> engine = sqlalchemy.create_engine("postgres://postgres@/postgres")

You cannot use engine.execute() however, because postgres does not allow you to create databases inside transactions, and sqlalchemy always tries to run queries in a transaction. To get around this, get the underlying connection from the engine:

>>> conn = engine.connect()

But the connection will still be inside a transaction, so you have to end the open transaction with a commit:

>>> conn.execute("commit")

And you can then proceed to create the database using the proper PostgreSQL command for it.

>>> conn.execute("create database test")
>>> conn.close()

回答 1

SQLAlchemy-UtilsSQLAlchemy提供自定义数据类型和各种实用程序功能。您可以使用pip安装最新的正式版本:

pip install sqlalchemy-utils

数据库的助手包括create_database功能:

from sqlalchemy import create_engine
from sqlalchemy_utils import database_exists, create_database

engine = create_engine("postgres://localhost/mydb")
if not database_exists(engine.url):
    create_database(engine.url)

print(database_exists(engine.url))

SQLAlchemy-Utils provides custom data types and various utility functions for SQLAlchemy. You can install the most recent official version using pip:

pip install sqlalchemy-utils

The database helpers include a create_database function:

from sqlalchemy import create_engine
from sqlalchemy_utils import database_exists, create_database

engine = create_engine("postgres://localhost/mydb")
if not database_exists(engine.url):
    create_database(engine.url)

print(database_exists(engine.url))

回答 2

通过提供isolation_level='AUTOCOMMIT'以下create_engine功能,可以避免在创建数据库时进行手动事务管理:

import sqlalchemy

with sqlalchemy.create_engine(
    'postgresql:///postgres',
    isolation_level='AUTOCOMMIT'
).connect() as connection:
    connection.execute('CREATE DATABASE my_database')

另外,如果不确定数据库是否存在,可以通过抑制sqlalchemy.exc.ProgrammingError异常来忽略由于存在而导致的数据库创建错误:

import contextlib
import sqlalchemy.exc

with contextlib.suppress(sqlalchemy.exc.ProgrammingError):
    # creating database as above

It’s possible to avoid manual transaction management while creating database by providing isolation_level='AUTOCOMMIT' to create_engine function:

import sqlalchemy

with sqlalchemy.create_engine(
    'postgresql:///postgres',
    isolation_level='AUTOCOMMIT'
).connect() as connection:
    connection.execute('CREATE DATABASE my_database')

Also if you are not sure that database doesn’t exist there is a way to ignore database creation error due to existence by suppressing sqlalchemy.exc.ProgrammingError exception:

import contextlib
import sqlalchemy.exc

with contextlib.suppress(sqlalchemy.exc.ProgrammingError):
    # creating database as above

回答 3

请注意,我无法获得上述建议,database_exists因为每当我检查数据库是否存在时,如果没有database_exists(engine.url):,就会出现此错误:

InterfaceError(’(pyodbc.InterfaceError)(\’28000 \’,u \'[28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server]用户\\’myUser \\’的登录失败。(18456) (SQLDriverConnect); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server]无法打开登录请求的数据库“ MY_DATABASE”。登录失败。(4060); [28000] [Microsoft] [SQL Server Native客户端11.0] [SQL Server]用户\\’myUser \\’的登录失败。(18456); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server]无法打开登录请求的数据库“ MY_DATABASE” 。登录失败。(4060)\’)’,)

同样contextlib/suppress也无法正常工作,并且我没有使用,postgres因此如果数据库恰好已存在于SQL Server中,那么我最终会这样做来忽略异常:

import logging
import sqlalchemy

logging.basicConfig(filename='app.log', format='%(asctime)s-%(levelname)s-%(message)s', level=logging.DEBUG)
engine = create_engine('mssql+pyodbc://myUser:mypwd@localhost:1234/MY_DATABASE?driver=SQL+Server+Native+Client+11.0?trusted_connection=yes', isolation_level = "AUTOCOMMIT")

try: 
    engine.execute('CREATE DATABASE ' + a_database_name)
except Exception as db_exc:
    logging.exception("Exception creating database: " + str(db_exc))  

Please note that I couldn’t get the above suggestions with database_exists because whenever I check if the database exists using if not database_exists(engine.url): I get this error:

InterfaceError(‘(pyodbc.InterfaceError) (\’28000\’, u\'[28000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Login failed for user \\’myUser\\’. (18456) (SQLDriverConnect); [28000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Cannot open database “MY_DATABASE” requested by the login. The login failed. (4060); [28000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Login failed for user \\’myUser\\’. (18456); [28000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Cannot open database “MY_DATABASE” requested by the login. The login failed. (4060)\’)’,)

Also contextlib/suppress was not working and I’m not using postgres so I ended up doing this to ignore the exception if the database happens to already exist with SQL Server:

import logging
import sqlalchemy

logging.basicConfig(filename='app.log', format='%(asctime)s-%(levelname)s-%(message)s', level=logging.DEBUG)
engine = create_engine('mssql+pyodbc://myUser:mypwd@localhost:1234/MY_DATABASE?driver=SQL+Server+Native+Client+11.0?trusted_connection=yes', isolation_level = "AUTOCOMMIT")

try: 
    engine.execute('CREATE DATABASE ' + a_database_name)
except Exception as db_exc:
    logging.exception("Exception creating database: " + str(db_exc))  

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。