首页 > 解决方案 > Flask-SQLAlchemy SQL Server 使用字符串作为主键

问题描述

我正在构建一个网页,它使用 SQL Server 作为数据库 + Flask 用于 Web 框架。我希望能够将用户添加到我的网页,并创建了一个 SQLAlchemy 类,如下所示:

from datetime import datetime
from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(), unique=True)
    password = db.Column(db.String())
    created_at = db.Column(db.DateTime(), default=datetime.now())

    def __repr__(self):
        return self.username

但是,当我尝试创建表时,SQL Server 给了我以下错误:

sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'email' in table 'user' is of a type that is invalid for use as a key column in an index. (1919) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Could not create constraint or index. See previous erro
    rs. (1750)")
    [SQL:
    CREATE TABLE [user] (
            id INTEGER NOT NULL IDENTITY(1,1),
            email VARCHAR(max) NULL,
            password VARCHAR(max) NULL,
            created_at DATETIME NULL,
            PRIMARY KEY (id),
            UNIQUE (email)
    )]

如果我删除Unique=True它工作正常。我想这与 SQL Server 不了解课堂上发生的事情有关,反之亦然。

任何想法如何从 SQLAlchemy 在 SQL Server 中使键唯一?

标签: pythonsql-serversqlalchemy

解决方案


来自SQLAlchemy 文档

SQL Server 支持 sqltypes.VARCHAR 和 sqltypes.NVARCHAR 数据类型中的特殊字符串“MAX”,以指示“可能的最大长度”。方言当前将其处理为基本类型中的“无”长度......

并且 api 参考sqlalchemy.dialects.mssql.VARCHAR将构造函数签名显示为:

class sqlalchemy.dialects.mssql.VARCHAR(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False)

由于lengthisNone和 SQLAlchemy 用于length=None表示最大长度 varchar 的默认值,您的所有String列都被定义为这样,您可以在您发布的错误消息中看到:

..email VARCHAR(max) NULL,密码VARCHAR(max) NULL

SQL Server 文档

不能将 ntext、text、image、varchar(max)、nvarchar(max) 和 varbinary(max) 数据类型的列指定为索引键列...

它继续说它们可以用作聚集索引中的非键索引列,但根据这个答案varchar(max)将存储超过 20 亿个单字节字符。我高度怀疑您不需要在电子邮件字段中存储那么多字符,所以我建议限制电子邮件列的长度是这里的方法:

email = db.Column(db.String(256), unique=True)

推荐阅读