如何将SqlServer ON [PRIMARY]转换为Sqlalchemy模型?

时间:2018-05-23 13:39:20

标签: python flask sqlalchemy flask-sqlalchemy

我在sqlserver中有查询,我想使用sqlalchemy orm编写与之对应的模型。我需要知道如何将ON [PRIMARY]转换为sqlalchemy。

这是我的问题:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[UserModel](
[userid] [nvarchar](255) NULL,
[username] [nvarchar](255) NULL,
[serialnumber] [nvarchar](255) NULL
) ON [PRIMARY]

GO

这是我的模特:

class UserModel(db.Model):
    __tablename__ = 'UserModel'

    userid = Column('userid', Unicode(255))
    username = Column('username', Unicode(255))
    serialnumber = Column('serialnumber', Unicode(255))

任何建议,我将如何实现这一目标 目前我收到如下错误:

sqlalchemy.exc.ArgumentError: Mapper Mapper|UserModel|UserModel could not assemble any primary key columns for mapped table 'UserModel'

我知道我的模型中没有定义主键,但上面的查询工作正常。所以我想用sqlalchemy orm翻译上面的查询。

1 个答案:

答案 0 :(得分:0)

您不能使用大多数ORM来翻译上述DDL,至少是直接翻译,因为数据库中有they expect Python objects to correspond to uniquely identifiable rows。现在,如果您确定例如UserModel.userid唯一标识行,则可以指示SQLAlchemy将其用作“主键”:

class UserModel(db.Model):
    __tablename__ = 'UserModel'

    userid = Column('userid', Unicode(255))
    username = Column('username', Unicode(255))
    serialnumber = Column('serialnumber', Unicode(255))

    __mapper_args__ = {
        'primary_key': [userid]
    }

请记住,您已经对ORM撒谎,并且任何后果都在您身上。

至于定义文件组,表格应该使用ON [PRIMARY]存储,你必须稍微增加mssql dialect

from sqlalchemy import Table
from sqlalchemy.schema import CreateTable
from sqlalchemy.ext.compiler import compiles

# Add our custom dialect specific argument
Table.argument_for('mssql', 'on', None)

@compiles(CreateTable, 'mssql')
def compile_create_table(create, compiler, **kw):
    stmt = compiler.visit_create_table(create, **kw)
    filegroup = create.element.kwargs.get('mssql_on')

    if filegroup:
        stmt = stmt.rstrip()  # Prettier output, remove newlines
        filegroup = compiler.preparer.quote(filegroup)
        stmt = f"{stmt} ON {filegroup}\n\n"

    return stmt

并将必要的表格args添加到模型定义中:

class UserModel(db.Model):
    ...
    __table_args__ = {
        'mssql_on': 'PRIMARY'
    }

您可以验证生成的DDL是否符合要求:

In [4]: print(CreateTable(UserModel.__table__).compile(dialect=engine.dialect))

CREATE TABLE [UserModel] (
        userid NVARCHAR(255) NULL, 
        username NVARCHAR(255) NULL, 
        serialnumber NVARCHAR(255) NULL
) ON [PRIMARY]

请注意,至少根据this Q/A primary是默认值,因此ON [PRIMARY]可以省略。