Як створити нову базу даних за допомогою SQLAlchemy?


103

Використовуючи SQLAlchemy, об’єкт Engine створюється так:

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

Не engineвдається отримати доступ, якщо база даних, зазначена в аргументі create_engine(у цьому випадку mydb), не існує. Чи можна сказати SQLAlchemy створити нову базу даних, якщо зазначена база даних не існує?


2
Створити нову базу даних або просто таблиці? Я не натрапив на багато ОРМ, які фактично створюють бази даних.
Нуфал Ібрагім

4
Я знайшов це
Нуфал Ібрагім

Відповіді:


97

На postgres за замовчуванням зазвичай присутні три бази даних. Якщо ви зможете підключитися як супер-користувач (наприклад, postgresроль), ви можете підключитися до баз даних postgresабо template1. За замовчуванням pg_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, деякі БД вважатимуть це мій стовпцем. Іншими словами, не впевнений, як ви створили свою таблицю, але якщо вона створена за допомогою лапок, вона буде залежно від регістру, тому коли ви отримаєте доступ до неї в операторі SQL, вам також знадобляться цитати.
гуярад

119

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
Я отримую цю помилку при спробі це точно кодоблока: psycopg2.OperationalError: fe_sendauth: no password supplied. При використанні "postgres://test:abc123@localhost:5432/test"я отримуюpsycopg2.OperationalError: FATAL: password authentication failed for user "test"
Гус

Вибачте за спам, але я спробував змінити порт 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.
Гус

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

Здається, ви не можете підключитися до сервера прогресу без введення бази даних, тому, ймовірно, ви захочете підключитися до бази даних "postgres" за замовчуванням для виконання команд створення db, інакше він спробує підключитися до користувача за замовчуванням " "база даних та скаржиться, якщо її не існує.
Жолудь

0

Зауважте, що я не міг отримати вищезазначені пропозиції, database_existsтому що коли я перевіряю, чи існує база даних, використовуючи, якщо ні, database_exists(engine.url):я отримую цю помилку:

InterfaceError ('(pyodbc.InterfaceError) (\' 28000 \ ', u \' [28000] [Microsoft] [Native Client SQL Server 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))  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.