SQL Server Can a primary_key be avoided in SQLAlchemy when creating a table?

gab6jxml  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(114)

I have a database with a bunch of huge tables, and I would like to

  1. Use SQLAlchemy to interact with these tables
  2. Create similar tables (with a few rows) in a local sqlite database for testing
  3. Test SQLAlchemy queries against sqlite tables for unittests

So I found out that one can get metadata from a remote table in the following way:

# Imports
from sqlalchemy import create_engine, Table, MetaData

# Creating engine for interacting with db
engine = create_engine("mssql+pyodbc://my_server/my_database?trusted_connection=yes&driver=my_driver")

# Fetching table metadata
metadata = MetaData()
my_table = Table("my_table", 
                 metadata, 
                 schema="my_database.my_schema",
                 autoload_with=engine)

# Listing columns, their types and settings
list(table.columns)

In practice I would like the definition of this table to live in Python, such that my unit tests are not dependent on connecting to a remote database. So I tried to construct it in SQLAlchemy.

# Imports
from sqlalchemy.dialects.mssql import DATE, VARCHAR, TINYINT

# Declaring base
Base = declarative_base()

# Constructing table
class MyTable(Base):
    __tablename__ = 'my_table'

    col1= Column('col1', DATE(), nullable=False),
    col2= Column('col2', VARCHAR(length=15), nullable=False),
    col3= Column('col3', TINYINT(), nullable=False)

When I construct the table with the same types as those identified above I get the following error:

ArgumentError: Mapper mapped class Targets->my_table could not assemble any primary key columns for mapped table 'my_table'

Apparently the SQLAlchemy ORM requires tables to have a primary_key if you construct them yourself. But the table I want to "mirror" does not have a primary_key in the database, and that is something I cannot change due to the company's organization and setup.

Is there a smarter way to construct a table with identical types?

mpbci0fu

mpbci0fu1#

As mentioned by @snakecharmerb the answer can be found in the following part of the documentation. One has two choices:

Option 1

Here we don't use the ORM, and we simply use a Table.

# Constructing table
my_table = Table(
    __tablename__ = 'my_table'

    Column('col1', DATE(), nullable=False),
    Column('col2', VARCHAR(length=15), nullable=False),
    Column('col3', TINYINT(), nullable=False)

    autoload=True, 
    autoload_with=engine,
    schema='my_schema'
)

Option 2

If one exists on using the declarative_base one can do the following

# Constructing table
my_table = Table(
    __tablename__ = 'my_table'

    Column('col1', DATE(), nullable=False),
    Column('col2', VARCHAR(length=15), nullable=False),
    Column('col3', TINYINT(), nullable=False)
    UniqueConstraint("col1", "col2", "col3")

    autoload=True, 
    autoload_with=engine,
    schema='my_schema'
)

# Constructing base class
class MyTable(Base):
    __tablename__ = 'my_table'
    __mapper_args__ = {"primary_key": [my_table.c.col1, my_table.c.col2, my_table.c.col3]}

相关问题