จะสร้างฐานข้อมูลใหม่โดยใช้ SQLAlchemy ได้อย่างไร?


103

การใช้ SQLAlchemy อ็อบเจ็กต์ Engine ถูกสร้างขึ้นเช่นนี้:

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

การเข้าถึงengineล้มเหลวหากไม่มีฐานข้อมูลที่ระบุในอาร์กิวเมนต์ถึงcreate_engine(ในกรณีนี้mydb) เป็นไปได้หรือไม่ที่จะบอกให้ SQLAlchemy สร้างฐานข้อมูลใหม่หากไม่มีฐานข้อมูลที่ระบุ


2
สร้างฐานข้อมูลใหม่หรือแค่ตาราง? ฉันไม่พบ ORM จำนวนมากที่สร้างฐานข้อมูลจริง
Noufal Ibrahim

4
ฉันพบสิ่งนี้
Noufal Ibrahim

คำตอบ:


100

ใน postgres โดยปกติจะมีฐานข้อมูลสามฐานตามค่าเริ่มต้น หากคุณสามารถเชื่อมต่อในฐานะ superuser (เช่นpostgresบทบาท) คุณสามารถเชื่อมต่อกับฐานข้อมูลpostgresหรือ template1pg_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()

3
นี้ทำงานได้ดีสำหรับฉัน. ตามบันทึกด้านข้างเมื่อconn.execute('drop database DBWithCaps')ฉันมีปัญหากับการไม่รู้จักตัวพิมพ์ใหญ่ conn.execute('drop database "DBWithCaps"')(พร้อมคำพูด) ใช้งานได้ดี
KobeJohn

ฉันรู้ว่า PostgreSQL ต้องการเอนทิตีทั้งหมดเป็นตัวพิมพ์เล็กยกเว้นที่ยกมา ดังนั้นหากคุณสร้างฟิลด์โดยใช้ MyColumn ฐานข้อมูลบางส่วนจะใช้เป็น mycolumn กล่าวอีกนัยหนึ่งไม่แน่ใจว่าคุณสร้างตารางของคุณอย่างไร แต่ถ้าสร้างโดยใช้เครื่องหมายคำพูดมันจะคำนึงถึงขนาดตัวพิมพ์ดังนั้นเมื่อคุณเข้าถึงในคำสั่ง SQL คุณจะต้องมีเครื่องหมายคำพูดด้วย
Guyarad

121

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
ฉันได้รับข้อผิดพลาดนี้เมื่อพยายาม codeblock psycopg2.OperationalError: fe_sendauth: no password suppliedตรงนี้: เมื่อใช้"postgres://test:abc123@localhost:5432/test"I getpsycopg2.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.
Guus

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" เริ่มต้นเพื่อดำเนินการคำสั่งการสร้างฐานข้อมูลมิฉะนั้นจะพยายามเชื่อมต่อกับผู้ใช้ "เริ่มต้น "ฐานข้อมูลและร้องเรียนหากไม่มี
Acorn

0

โปรดทราบว่าฉันไม่สามารถรับคำแนะนำข้างต้นได้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))  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.