Bagaimana cara membuat database baru menggunakan SQLAlchemy?

103

Menggunakan SQLAlchemy, objek Engine dibuat seperti ini:

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

Mengakses enginegagal jika database yang ditentukan dalam argumen ke create_engine(dalam kasus ini, mydb) tidak ada. Apakah mungkin untuk memberi tahu SQLAlchemy untuk membuat database baru jika database yang ditentukan tidak ada?

Anand Chitipothu
sumber
2
Buat database baru atau hanya tabel? Saya belum menemukan banyak ORM yang benar-benar membuat database.
Noufal Ibrahim
4
Saya menemukan ini
Noufal Ibrahim

Jawaban:

97

Pada postgres, tiga database biasanya hadir secara default. Jika Anda dapat terhubung sebagai pengguna super (misalnya, postgresperan), maka Anda dapat terhubung ke database postgresatau template1. Default pg_hba.conf hanya mengizinkan pengguna unix yang diberi nama postgresuntuk menggunakan postgresperan tersebut, jadi hal yang paling sederhana adalah menjadi pengguna tersebut. Bagaimanapun, buat mesin seperti biasa dengan pengguna yang memiliki izin untuk membuat database:

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

engine.execute()Namun, Anda tidak dapat menggunakan , karena postgres tidak mengizinkan Anda membuat database di dalam transaksi, dan sqlalchemy selalu mencoba menjalankan kueri dalam transaksi. Untuk menyiasati ini, dapatkan koneksi yang mendasari dari mesin:

>>> conn = engine.connect()

Tetapi koneksi tersebut masih ada di dalam transaksi, jadi Anda harus mengakhiri transaksi terbuka dengan commit:

>>> conn.execute("commit")

Dan Anda kemudian dapat melanjutkan untuk membuat database menggunakan perintah PostgreSQL yang tepat untuknya.

>>> conn.execute("create database test")
>>> conn.close()
SingleNegationElimination
sumber
3
Ini bekerja dengan baik untuk saya. Sebagai catatan tambahan, ketika saya melakukannya, conn.execute('drop database DBWithCaps')saya memiliki masalah dengan itu tidak mengenali topi. conn.execute('drop database "DBWithCaps"')(dengan tanda kutip) bekerja dengan baik.
KobeJohn
Saya tahu bahwa PostgreSQL mengharapkan semua entitas dalam huruf kecil, kecuali dikutip. Jadi jika Anda membuat bidang menggunakan MyColumn, beberapa DB akan menganggapnya sebagai kolom saya. Dengan kata lain, tidak yakin bagaimana Anda membuat tabel Anda, tetapi jika dibuat menggunakan tanda kutip, itu akan peka huruf besar / kecil, jadi ketika Anda mengaksesnya dalam pernyataan SQL Anda akan membutuhkan tanda kutip juga.
guyarad
119

SQLAlchemy-Utils menyediakan tipe data kustom dan berbagai fungsi utilitas untuk SQLAlchemy. Anda dapat menginstal versi resmi terbaru menggunakan pip:

pip install sqlalchemy-utils

The pembantu Database termasuk create_databasefungsi:

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))
buhtz
sumber
2
Saya mendapatkan error ini ketika mencoba codeblock tepat ini: psycopg2.OperationalError: fe_sendauth: no password supplied. Saat menggunakan "postgres://test:abc123@localhost:5432/test"I getpsycopg2.OperationalError: FATAL: password authentication failed for user "test"
Guus
Maaf untuk spam, tetapi saya mencoba mengubah port menjadi 9000 dan sekarang saya mendapatkan ini:"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

Ini mungkin untuk menghindari manajemen transaksi pengguna sekaligus menciptakan database dengan memberikan isolation_level='AUTOCOMMIT'ke create_enginefungsi:

import sqlalchemy

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

Juga jika Anda tidak yakin bahwa database tidak ada, ada cara untuk mengabaikan kesalahan pembuatan database karena keberadaannya dengan menekan sqlalchemy.exc.ProgrammingErrorpengecualian:

import contextlib
import sqlalchemy.exc

with contextlib.suppress(sqlalchemy.exc.ProgrammingError):
    # creating database as above
renskiy
sumber
Tampaknya Anda tidak dapat terhubung ke server progres tanpa menentukan database, jadi Anda mungkin ingin terhubung ke database "postgres" default untuk menjalankan perintah pembuatan db, jika tidak maka akan mencoba menghubungkan ke "user" default "database dan komplain jika tidak ada.
Acorn
0

Harap dicatat bahwa saya tidak bisa mendapatkan saran di atas database_existskarena setiap kali saya memeriksa apakah database ada menggunakan jika tidak database_exists(engine.url):saya mendapatkan kesalahan ini:

InterfaceError ('(pyodbc.InterfaceError) (\' 28000 \ ', u \' [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Login gagal untuk pengguna \\ 'myUser \\'. (18456) (SQLDriverConnect); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Tidak dapat membuka database "MY_DATABASE" yang diminta oleh login. Login gagal. (4060); [28000] [Microsoft] [SQL Server Native Klien 11.0] [SQL Server] Login gagal untuk pengguna \\ 'myUser \\'. (18456); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Tidak dapat membuka database "MY_DATABASE" yang diminta oleh login . Login gagal. (4060) \ ')',)

Juga contextlib/suppresstidak berfungsi dan saya tidak menggunakan postgresjadi saya akhirnya melakukan ini untuk mengabaikan pengecualian jika database sudah ada dengan 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))  
pengguna8128167
sumber