簡體   English   中英

Sqlalchemy 如果表不存在

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM