![](/img/trans.png)
[英]SQLAlchemy Polymorphism: Parent table does not exist when creating a child record
[英]Sqlalchemy if table does not exist
我寫了一個模塊來創建一個空的數據庫文件
def create_database():
engine = create_engine("sqlite:///myexample.db", echo=True)
metadata = MetaData(engine)
metadata.create_all()
但是在另一個函數中,我想打開myexample.db
數據庫,如果它還沒有該表,則為其創建表。
我將創建的第一個后續表的 EG 將是:
Table(Variable_TableName, metadata,
Column('Id', Integer, primary_key=True, nullable=False),
Column('Date', Date),
Column('Volume', Float))
(由於它最初是一個空數據庫,因此其中沒有表,但隨后,我可以向其中添加更多表。這就是我想說的。)
有什么建議?
我已經設法弄清楚我打算做什么。 我使用engine.dialect.has_table(engine, Variable_tableName)
檢查數據庫中是否有表。 如果沒有,那么它將繼續在數據庫中創建一個表。
示例代碼:
engine = create_engine("sqlite:///myexample.db") # Access the DB Engine
if not engine.dialect.has_table(engine, Variable_tableName): # If table don't exist, Create.
metadata = MetaData(engine)
# Create a table with the appropriate Columns
Table(Variable_tableName, metadata,
Column('Id', Integer, primary_key=True, nullable=False),
Column('Date', Date), Column('Country', String),
Column('Brand', String), Column('Price', Float),
# Implement the creation
metadata.create_all()
這似乎給了我我正在尋找的東西。
請注意,在“Base.metadata” 文檔中,它說明了 create_all:
默認情況下有條件,不會嘗試重新創建目標數據庫中已經存在的表。
如果您可以看到 create_all 接受以下參數:create_all(self, bind=None, tables=None, checkfirst=True),並且根據文檔:
默認為 True,不要為目標數據庫中已經存在的表發出 CREATE。
所以如果我正確理解你的問題,你可以跳過條件。
對於那些首先在某些models.table
文件中定義表的人,以及其他表。 這是一個代碼片段,用於查找代表我們要創建的表的類(以便稍后我們可以使用相同的代碼來查詢它)
但是加上上面寫的if
,我還是用checkfirst=True
運行代碼
ORMTable.__table__.create(bind=engine, checkfirst=True)
class TableA(Base):
class TableB(Base):
class NewTableC(Base):
id = Column('id', Text)
name = Column('name', Text)
然后在表單操作文件中:
engine = create_engine("sqlite:///myexample.db")
if not engine.dialect.has_table(engine, table_name):
# Added to models.tables the new table I needed ( format Table as written above )
table_models = importlib.import_module('models.tables')
# Grab the class that represents the new table
# table_name = 'NewTableC'
ORMTable = getattr(table_models, table_name)
# checkfirst=True to make sure it doesn't exists
ORMTable.__table__.create(bind=engine, checkfirst=True)
engine.dialect.has_table 在 cx_oracle 上對我不起作用。 我收到AttributeError: 'OracleDialect_cx_oracle' object has no attribute 'default_schema_name'
我寫了一個解決方法:
from sqlalchemy.engine.base import Engine
def orcl_tab_or_view_exists(in_engine: Engine, in_object: str, in_object_name: str,)-> bool:
"""Checks if Oracle table exists in current in_engine connection
in_object: 'table' | 'view'
in_object_name: table_name | view_name
"""
obj_query = """SELECT {o}_name FROM all_{o}s WHERE owner = SYS_CONTEXT ('userenv', 'current_schema') AND {o}_name = '{on}'
""".format(o=in_object, on=in_object_name.upper())
with in_engine.connect() as connection:
result = connection.execute(obj_query)
return len(list(result)) > 0
接受的答案會打印一條警告,指出engine.dialect.has_table()
僅供內部使用,而不是公共 API 的一部分。 該消息建議將此作為替代方案,這對我有用:
import os
import sqlalchemy
# Set up a connection to a SQLite3 DB
test_db = os.getcwd() + "/test.sqlite"
db_connection_string = "sqlite:///" + test_db
engine = create_engine(db_connection_string)
# The recommended way to check for existence
sqlalchemy.inspect(engine).has_table("BOOKS")
另請參閱 SQL Alchemy 文檔。
這是為我工作的代碼,用於創建使用Base
類定義的所有模型類的所有表
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
class YourTable(Base):
__tablename__ = 'your_table'
id = Column(Integer, primary_key = True)
DB_URL="mysql+mysqldb://<user>:<password>@<host>:<port>/<db_name>"
scoped_engine = create_engine(DB_URL)
Base = declarative_base()
Base.metadata.create_all(scoped_engine)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.