Làm cách nào để tạo cơ sở dữ liệu mới bằng SQLAlchemy?


103

Sử dụng SQLAlchemy, một đối tượng Engine được tạo như sau:

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

Không thể truy cập enginenếu cơ sở dữ liệu được chỉ định trong đối số create_engine(trong trường hợp này là mydb) không tồn tại. Có thể yêu cầu SQLAlchemy tạo cơ sở dữ liệu mới nếu cơ sở dữ liệu được chỉ định không tồn tại không?


2
Tạo một cơ sở dữ liệu mới hay chỉ các bảng? Tôi chưa gặp nhiều ORM thực sự tạo cơ sở dữ liệu.
Noufal Ibrahim

4
Tôi đã tìm thấy này
Noufal Ibrahim

Câu trả lời:


97

Trên postgres, ba cơ sở dữ liệu thường hiển thị theo mặc định. Nếu bạn có thể kết nối với tư cách là người dùng siêu cấp (ví dụ: postgresvai trò), thì bạn có thể kết nối với postgreshoặc template1cơ sở dữ liệu. Mặc định pg_hba.conf chỉ cho phép người dùng unix có tên postgressử dụng postgresvai trò, vì vậy điều đơn giản nhất là chỉ cần trở thành người dùng đó. Ở bất kỳ mức độ nào, hãy tạo một công cụ như bình thường với người dùng có quyền tạo cơ sở dữ liệu:

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

engine.execute()Tuy nhiên, bạn không thể sử dụng vì postgres không cho phép bạn tạo cơ sở dữ liệu bên trong các giao dịch và sqlalchemy luôn cố gắng chạy các truy vấn trong một giao dịch. Để giải quyết vấn đề này, hãy lấy kết nối cơ bản từ động cơ:

>>> conn = engine.connect()

Nhưng kết nối sẽ vẫn ở bên trong một giao dịch, vì vậy bạn phải kết thúc giao dịch đang mở bằng commit:

>>> conn.execute("commit")

Và sau đó bạn có thể tiến hành tạo cơ sở dữ liệu bằng lệnh PostgreSQL thích hợp cho nó.

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

3
Điều này làm việc tốt cho tôi. Như một lưu ý phụ, khi tôi thực hiện, conn.execute('drop database DBWithCaps')tôi đã gặp vấn đề với việc nó không nhận dạng được các nắp. conn.execute('drop database "DBWithCaps"')(với các dấu ngoặc kép) hoạt động tốt.
KobeJohn

Tôi biết rằng PostgreSQL mong đợi tất cả các thực thể ở dạng chữ thường, trừ khi được trích dẫn. Vì vậy, nếu bạn đã tạo một trường bằng MyColumn, một số DB sẽ lấy nó làm cột của tôi. Nói cách khác, không chắc bạn đã tạo bảng của mình như thế nào, nhưng nếu nó được tạo bằng cách sử dụng dấu ngoặc kép, nó sẽ phân biệt chữ hoa chữ thường, vì vậy khi bạn truy cập nó trong một câu lệnh SQL, bạn cũng sẽ cần dấu ngoặc kép.
guyarad

119

SQLAlchemy-Utils cung cấp các kiểu dữ liệu tùy chỉnh và các chức năng tiện ích khác nhau cho SQLAlchemy. Bạn có thể cài đặt phiên bản chính thức gần đây nhất bằng cách sử dụng pip:

pip install sqlalchemy-utils

Trình trợ giúp cơ sở dữ liệu bao gồm một create_databasechức năng:

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
Tôi nhận được lỗi này khi cố gắng codeblock này chính xác: psycopg2.OperationalError: fe_sendauth: no password supplied. Khi sử dụng, "postgres://test:abc123@localhost:5432/test"tôi nhận đượcpsycopg2.OperationalError: FATAL: password authentication failed for user "test"
Guus

Xin lỗi vì thư rác, nhưng tôi đã thử thay đổi cổng thành 9000 và bây giờ tôi nhận được thông báo này:"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

Có thể tránh quản lý giao dịch thủ công khi tạo cơ sở dữ liệu bằng cách cung cấp isolation_level='AUTOCOMMIT'cho create_enginechức năng:

import sqlalchemy

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

Ngoài ra, nếu bạn không chắc rằng cơ sở dữ liệu không tồn tại, có một cách để bỏ qua lỗi tạo cơ sở dữ liệu do tồn tại bằng cách loại bỏ sqlalchemy.exc.ProgrammingErrorngoại lệ:

import contextlib
import sqlalchemy.exc

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

Có vẻ như bạn không thể kết nối với máy chủ progres mà không chỉ định cơ sở dữ liệu, vì vậy có thể bạn sẽ muốn kết nối với cơ sở dữ liệu "postgres" mặc định để thực thi các lệnh tạo db, nếu không nó sẽ cố gắng kết nối với "người dùng" mặc định "cơ sở dữ liệu và khiếu nại nếu nó không tồn tại.
Acorn

0

Xin lưu ý rằng tôi không thể nhận được các đề xuất ở trên database_existsbởi vì bất cứ khi nào tôi kiểm tra xem cơ sở dữ liệu có tồn tại bằng cách sử dụng hay không, database_exists(engine.url):tôi gặp lỗi này:

InterfaceError ('(pyodbc.InterfaceError) (\' 28000 \ ', u \' [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Đăng nhập không thành công cho người dùng \\ 'myUser \\'. (18456) (SQLDriverConnect); [28000] [Microsoft] [SQL Server Native Client 11.0] [SQL Server] Không thể mở cơ sở dữ liệu "MY_DATABASE" do đăng nhập yêu cầu. Đăng nhập không thành công. (4060); [28000] [Microsoft] [SQL Server Native Máy khách 11.0] [Máy ​​chủ SQL] Đăng nhập không thành công cho người dùng \\ 'myUser \\'. (18456); [28000] [Microsoft] [Máy ​​khách gốc SQL 11.0] [Máy ​​chủ SQL] Không thể mở cơ sở dữ liệu "MY_DATABASE" do đăng nhập yêu cầu . Đăng nhập không thành công. (4060) \ ')',)

Cũng contextlib/suppresskhông hoạt động và tôi không sử dụng postgresvì vậy tôi đã kết thúc việc này để bỏ qua ngoại lệ nếu cơ sở dữ liệu đã tồn tại với 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))  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.