web-dev-qa-db-ja.com

SQLAlchemyは、create()から生のSQLを出力します

私はPylonsにSQLAlchemyを試してみましたが、気に入っています。1つだけあります。実行される前に、Table().create()から生成された生のSQL CREATE TABLEデータを出力することは可能ですか?

42
Mads Madsen
from sqlalchemy.schema import CreateTable

print(CreateTable(table))

宣言構文を使用している場合:

print(CreateTable(Model.__table__))

更新:

受け入れられた回答があり、重要な情報が klenwell answer にあるので、ここにも追加します。

エンジンでコンパイルすることにより、特定のデータベース(MySQL、Postgresqlなど)のSQLを取得できます。

print(CreateTable(Model.__table__).compile(engine))

更新2:

@jackotonyeエンジンなしでそれを行う方法をコメントに追加しました。

print(CreateTable(Model.__table__).compile(dialect=postgresql.dialect()))
89
Antoine Leclair

いくつかの既存のモデルのテストをセットアップするために、生のテーブルSQLを取得する必要がありました。これは、コンセプトの証明として Antoineの答え に基づいてSQLAlchemy 0.7.4に対して作成した成功した単体テストです。

from sqlalchemy import create_engine
from sqlalchemy.schema import CreateTable
from model import Foo

sql_url = "sqlite:///:memory:"    
db_engine = create_engine(sql_url)

table_sql = CreateTable(Foo.table).compile(db_engine)
self.assertTrue("CREATE TABLE foos" in str(table_sql))
14
klenwell

以下を使用して、メタデータ作成シーケンスをダンプするようにエンジンを設定できます。

def metadata_dump(sql, *multiparams, **params):
    # print or write to log or file etc
    print(sql.compile(dialect=engine.dialect))

engine = create_engine(myDatabaseURL, strategy='mock', executor=metadata_dump)
metadata.create_all(engine)

このアプローチの利点の1つは、列挙型とインデックスが出力に含まれることです。 CreateTableを使用すると、これは省略されます。

もう1つの利点は、スキーマ定義の順序が正しく、(ほとんど)スクリプトとして使用できることです。

11
Lars

このようなもの? (SQLA FAQから)

http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html

8

これは単純明快です。

from sqlalchemy.dialects import postgresql
from sqlalchemy.schema import CreateTable
from sqlalchemy import Table, Column, String, MetaData

metadata = MetaData()

users = Table('users', metadata,
              Column('username', String)
)

statement = CreateTable(users)

print(statement.compile(dialect=postgresql.dialect()))

これを出力します:

CREATE TABLE users (
    username VARCHAR
)

さらに、準備されたステートメントでバインドされたパラメーターをサポートすることもできます。

参照

バインドされたパラメーターをインライン化して、SQL式を文字列としてレンダリングするにはどうすればよいですか?

...

またはエンジンなし:

from sqlalchemy.dialects import postgresql
print(statement.compile(dialect=postgresql.dialect()))

出典: http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html#faq-sql-expression-string

例:SQL Alchemyを使用してユーザー名変更スクリプトを生成する

#!/usr/bin/env python
import csv
from sqlalchemy.dialects import postgresql
from sqlalchemy import bindparam, Table, Column, String, MetaData

metadata = MetaData()

users = Table('users', metadata,
              Column('username', String)
)

renames = []

with open('users.csv') as csvfile:
    for row in csv.DictReader(csvfile):
        renames.append({
            'from': row['sAMAccountName'],
            'to': row['mail']
        })

for rename in renames:
    stmt = (users.update()
            .where(users.c.username == rename['from'])
            .values(username=rename['to']))
    print(str(stmt.compile(dialect=postgresql.dialect(),
                           compile_kwargs={"literal_binds": True})) + ';')

このusers.csvを処理する場合:

sAMAccountName,mail
bmcboatface,[email protected]
ndhyani,[email protected]

次のような出力が得られます。

UPDATE users SET username='[email protected]' WHERE users.username = 'bmcboatface';
UPDATE users SET username='[email protected]' WHERE users.username = 'ndhyani';users.username = 'ndhyani';

調査船にメールアドレスがある理由はまだ不明です。私はExample IncのITチームと連絡を取り、応答がありませんでした。

5
Alain O'Dea

Sqlalchemy.create_engineのechoパラメータですか?

/ tmp $ cat test_s.py

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Department(Base):
    __tablename__ = "departments"

    department_id = sa.Column(sa.types.Integer, primary_key=True)
    name = sa.Column(sa.types.Unicode(100), unique=True)
    chief_id = sa.Column(sa.types.Integer)
    parent_department_id = sa.Column(sa.types.Integer,
                                     sa.ForeignKey("departments.department_id"))

    parent_department = sa.orm.relation("Department")


engine = sa.create_engine("sqlite:///:memory:", echo=True)
Base.metadata.create_all(bind=engine)

/ tmp $ python test_s.py

2011-03-24 15:09:58,311 INFO sqlalchemy.engine.base.Engine.0x...42cc PRAGMA table_info("departments")
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc ()
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc 
CREATE TABLE departments (
    department_id INTEGER NOT NULL, 
    name VARCHAR(100), 
    chief_id INTEGER, 
    parent_department_id INTEGER, 
    PRIMARY KEY (department_id), 
    UNIQUE (name), 
    FOREIGN KEY(parent_department_id) REFERENCES departments (department_id)
)

2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc ()
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc COMMIT
1
xni