简体   繁体   中英

How to map a MS SQL Server table that has a UNIQUEIDENTIFIER primary key?

Using sqlalchemy 1.4, I want to map a class to a table that has a UNIQUEIDENTIFIER primary key.

Using sqlalchemy.String does not work (complains about the fact that you cannot increment it).

Checking dialects, I tried to used sqlalchemy.dialects.mssql.UNIQUEIDENTIFIER , however this does not work either:

class Result(Base):

    __tablename__ = os.environ["RESULT_TABLE_NAME"]
    __table_args__ = {"schema": "myschema"}

    id = Column(UNIQUEIDENTIFIER)

sqlalchemy.exc.ArgumentError: Mapper mapped class Result->DT_ODS_RESULT could not assemble any primary key columns for mapped table 'DT_ODS_RESULT'

Using the primary key parameters:

class Result(Base):

    __tablename__ = os.environ["RESULT_TABLE_NAME"]
    __table_args__ = {"schema": "SIDODS"}

    id = Column(UNIQUEIDENTIFIER, primary_key=True)

sqlalchemy.orm.exc.FlushError: Instance <Result at 0x7fbf9ab99d60> has a NULL identity key.  If this is an auto-generated value, check that the database table allows generation of new primary key values, and that the mapped Column object is configured to expect these generated values.  Ensure also that this flush() is not occurring at an inappropriate time, such as within a load() event.

Which I do not understand, because my column has a default value, as shown in this query part:

ALTER TABLE [SIDODS].[DT_ODS_RESULT] ADD  DEFAULT (newid()) FOR [ID]

The row is inserted with the following:

r = Result(
    query_id=query_id,
    trigger_id=trigger_id,
    insertion_datetime=get_datetime_at_timezone()
)
session.add(r)
session.commit()

How to correctly map my sqlalchemy model class so that I can insert, without specifying it manually, a row with a UNIQUEIDENTIFIER type?

Specifying primary_key=True and server_default=text("newid()") is sufficient to let SQLAlchemy know that the server will take case of assigning the PK value:

from sqlalchemy import Column, String, create_engine, select, text
from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER
from sqlalchemy.orm import Session, declarative_base

engine = create_engine("mssql+pyodbc://scott:tiger^5HHH@mssql_199")
Base = declarative_base()


class Thing(Base):
    __tablename__ = "thing"
    id = Column(UNIQUEIDENTIFIER, primary_key=True, server_default=text("newid()"))
    description = Column(String(100))


Base.metadata.drop_all(engine, checkfirst=True)
engine.echo = True
Base.metadata.create_all(engine)
"""DDL emitted:
CREATE TABLE thing (
    id UNIQUEIDENTIFIER NOT NULL DEFAULT newid(), 
    description VARCHAR(100) NULL, 
    PRIMARY KEY (id)
)
"""
engine.echo = False

with Session(engine) as sess:
    sess.add(Thing(description="a thing"))
    sess.commit()

with engine.begin() as conn:
    print(conn.execute(select(Thing.__table__)).all())
    # [('32570502-7F18-40B5-87E2-7A60232FE9BD', 'a thing')]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM