SQLAlchemyを使用して新しいデータベースを作成する方法


103

SQLAlchemyを使用すると、次のようにEngineオブジェクトが作成されます。

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

engineの引数で指定されたデータベースcreate_engine(この場合はmydb)が存在しない場合、アクセスは失敗します。指定したデータベースが存在しない場合、SQLAlchemyに新しいデータベースを作成するように指示することはできますか?


2
新しいデータベースまたは単にテーブルを作成しますか?実際にデータベースを作成する多くのORMに出会ったことはありません。
Noufal Ibrahim


回答:


97

postgresでは、通常、デフォルトで3つのデータベースが存在します。スーパーユーザー(postgresロールなど)として接続できる場合は、postgresまたはtemplate1データベースに接続できます。デフォルトのpg_hba.confはpostgrespostgresロールを使用するように指定されたUNIXユーザーのみを許可するため、最も単純なことは、そのユーザーになることだけです。とにかく、データベースを作成する権限を持つユーザーで通常どおりエンジンを作成します。

>>> 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()

3
これは私にとってはうまくいきました。補足として、私がconn.execute('drop database DBWithCaps')それをしたとき、それがキャップを認識しないという問題がありました。conn.execute('drop database "DBWithCaps"')(引用符で)うまくいきました。
神戸ジョン2013年

引用されていない限り、PostgreSQLではすべてのエンティティが小文字であると想定しています。したがって、MyColumnを使用してフィールドを作成した場合、一部のDBはそれをmycolumnとして受け取ります。言い換えれば、あなたは、あなたのテーブルを作成していないことを確認する方法、それは引用符を使用して作成された場合、それはなります大文字と小文字を区別し、あなたはSQL文でそれにアクセスするときに引用符が必要にもなります。
Guyarad 2016

119

SQLAlchemy-Utilsは、SQLAlchemyのカスタムデータ型とさまざまなユーティリティ関数を提供します。最新の公式バージョンは、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))

2
この正確なコードブロックを試すと、このエラーが発生しますpsycopg2.OperationalError: fe_sendauth: no password supplied。使用する"postgres://test:abc123@localhost:5432/test"と、psycopg2.OperationalError: FATAL: password authentication failed for user "test"
Guusの

申し訳ありませんが、スパムのために、私は9000にポートを変更しようと、今、私はこれを取得:"postgres://test:abc123@localhost:9000/test" psycopg2.OperationalError: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.
フース・

9

以下の機能を提供することで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

データベースを指定せずにprogresサーバーに接続できないようです。そのため、おそらくデフォルトの「postgres」データベースに接続してdb作成コマンドを実行する必要があります。そうしないと、デフォルトの「user」に接続しようとします。 "データベースが存在しない場合は文句を言う。
ドングリ

0

上記の提案を取得できなかったことに注意してください。database_existsデータベースが存在するかどうかを確認するたびに、database_exists(engine.url):次のエラーが発生するからです。

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]ログインで要求されたデータベース「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))  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.