SQLAlchemy kullanarak yeni bir veritabanı nasıl oluşturulur?


103

SQLAlchemy kullanarak, aşağıdaki gibi bir Engine nesnesi oluşturulur:

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

engineArgümanında belirtilen veritabanı create_engine(bu durumda, mydb) yoksa erişim başarısız olur . Belirtilen veritabanı yoksa SQLAlchemy'ye yeni bir veritabanı oluşturmasını söylemek mümkün müdür?


2
Yeni bir veritabanı mı yoksa sadece tablolar mı oluşturacaksınız? Aslında veritabanları oluşturan pek çok ORM'ye rastlamadım.
Noufal Ibrahim

4
Ben buldunuz bu
Noufal Ibrahim

Yanıtlar:


100

Postgreslerde, normalde varsayılan olarak üç veritabanı bulunur. Bir süper kullanıcı olarak bağlanabiliyorsanız (örneğin, postgresrol), o zaman postgresveya template1veritabanlarına bağlanabilirsiniz . Varsayılan pg_hba.conf yalnızca adı verilen unix kullanıcısının rolü postgreskullanmasına izin verir postgres, bu nedenle en basit şey o kullanıcı haline gelmektir. Her halükarda, veritabanı oluşturma izinlerine sahip bir kullanıcıyla her zamanki gibi bir motor oluşturun:

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

engine.execute()Ancak kullanamazsınız çünkü postgres işlemler içinde veritabanları oluşturmanıza izin vermez ve sqlalchemy her zaman bir işlemde sorgu çalıştırmaya çalışır. Bunu aşmak için altta yatan bağlantıyı motordan alın:

>>> conn = engine.connect()

Ancak bağlantı yine de bir işlemin içinde olacaktır, bu nedenle açık işlemi bir ile sonlandırmanız gerekir commit:

>>> conn.execute("commit")

Daha sonra uygun PostgreSQL komutunu kullanarak veritabanını oluşturmaya devam edebilirsiniz.

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

3
Bu benim için iyi çalıştı. Bir yan not olarak, yaptığımda conn.execute('drop database DBWithCaps')kapakları tanımamakla ilgili sorunlar yaşadım. conn.execute('drop database "DBWithCaps"')(alıntılarla) iyi çalıştı.
KobeJohn

PostgreSQL'in, alıntı yapılmadığı sürece tüm varlıkların küçük harf olmasını beklediğini biliyorum. Dolayısıyla, MyColumn'u kullanarak bir alan oluşturduysanız, bazı DB'ler bu alanı sütunum olarak alacaktır. Başka bir deyişle, tablonuzu nasıl oluşturduğunuzdan emin değilsiniz, ancak tırnak işaretleri kullanılarak oluşturulmuşsa, büyük / küçük harfe duyarlı olacaktır , bu nedenle bir SQL deyiminde ona eriştiğinizde tırnak işaretlerine de ihtiyacınız olacaktır.
guyarad

121

SQLAlchemy-Utils , SQLAlchemy için özel veri türleri ve çeşitli yardımcı program işlevleri sağlar. En son resmi sürümü pip kullanarak kurabilirsiniz:

pip install sqlalchemy-utils

Veritabanı yardımcıları bir şunlardır create_databaseişlevi:

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
Bu tam kod bloğu çalışırken bu hatayı alıyorum: psycopg2.OperationalError: fe_sendauth: no password supplied. Kullanırken "postgres://test:abc123@localhost:5432/test"alıyorumpsycopg2.OperationalError: FATAL: password authentication failed for user "test"
Guus

Spam için özür dilerim, ancak bağlantı noktasını 9000 olarak değiştirmeyi denedim ve şimdi şunu alıyorum:"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.
Guus

9

Veritabanı oluştururken manuel işlem yönetiminden kaçınmak isolation_level='AUTOCOMMIT'için şu create_engineişlevi sağlamak mümkündür:

import sqlalchemy

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

Ayrıca, veritabanının var olmadığından emin değilseniz, sqlalchemy.exc.ProgrammingErroristisnayı ortadan kaldırarak veritabanı oluşturma hatasını göz ardı etmenin bir yolu vardır :

import contextlib
import sqlalchemy.exc

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

Görünüşe göre bir veritabanı belirtmeden bir progres sunucusuna bağlanamazsınız, bu nedenle muhtemelen veritabanı oluşturma komutlarını yürütmek için varsayılan "postgres" veritabanına bağlanmak isteyeceksiniz, aksi takdirde varsayılan "kullanıcıya bağlanmaya çalışacaktır. "veritabanı ve yoksa şikayet edin.
Acorn

0

Lütfen yukarıdaki önerileri alamadığımı unutmayın, database_existsçünkü veritabanının var olup olmadığını kontrol database_exists(engine.url):ettiğimde , değilse bu hatayı alıyorum:

InterfaceError ('(pyodbc.InterfaceError) (\' 28000 \ ', u \' [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Oturum \\ 'myUser \\' kullanıcısı için başarısız oldu. (18456) (SQLDriverConnect); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Oturum açma tarafından istenen "MY_DATABASE" veritabanı açılamıyor. Oturum açma başarısız. (4060); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] \\ 'myUser \\' kullanıcısı için oturum açma başarısız. (18456); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Oturum açma tarafından istenen "MY_DATABASE" veritabanı açılamıyor . Giriş başarısız oldu. (4060) \ ')',)

Ayrıca contextlib/suppressçalışmıyordu ve kullanmıyorum, postgresbu yüzden veritabanı SQL Server ile zaten mevcutsa istisnayı yok saymak için bunu yaptım:

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))  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.