如何在sqlalchemy-redshift模型中定义Redshift自增IDENTITY列?
解决Redshift-SQLAlchemy中IDENTITY自动填充列的插入问题
问题场景
使用redshift-sqlalchemy连接SQLAlchemy与Redshift,手动在Redshift创建表:
CREATE TABLE companies ( id INTEGER IDENTITY(1,1) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id) );
SQLAlchemy模型映射代码如下:
Base = declarative_base() class Company(Base): __tablename__ = 'companies' id = Column(BigInteger, primary_key=True, redshift_identity=(1, 1)) name = Column(String, nullable=False) def __init__(self, name: str): self.name = name
执行插入操作时:
company = Company(name = 'Hoge') session.add(company) session.commit()
出现报错:
(sqlalchemy.exc.ProgrammingError) (redshift_connector.error.ProgrammingError) {'S': 'ERROR', 'C': '42P01', 'M': 'relation "companies_id_seq" does not exist', 'F': '../src/pg/src/backend/catalog/namespace.c', 'L': '267', 'R': 'LocalRangeVarGetRelid'} [SQL: INSERT INTO companies (id, name) VALUES (%s, %s)] [parameters: [{'name': 'Hoge'}]]
直接执行对应INSERT语句也会触发Redshift原生错误:
ERROR: cannot set an identity column to a value.
问题原因
- Redshift的IDENTITY列由数据库自动生成值,不允许手动赋值
- SQLAlchemy默认会将主键列包含在INSERT语句中,而
redshift_identity=(1,1)参数仅负责表创建时生成IDENTITY定义,并未告知SQLAlchemy该列无需客户端插入值 - SQLAlchemy误将IDENTITY列当作PostgreSQL的序列自增列,尝试查找对应的序列表(
companies_id_seq),而Redshift并不用序列实现IDENTITY,因此报错
解决方法
在id列的定义中添加autoincrement=False,明确告诉SQLAlchemy不要将该列纳入INSERT逻辑,也不要尝试生成序列:
Base = declarative_base() class Company(Base): __tablename__ = 'companies' id = Column(BigInteger, primary_key=True, redshift_identity=(1, 1), autoincrement=False) name = Column(String, nullable=False) def __init__(self, name: str): self.name = name
修改后,SQLAlchemy生成的INSERT语句会自动忽略id列,变为:
INSERT INTO companies (name) VALUES (%s)
此时插入数据时,Redshift会自动为id列填充递增数值,符合预期。
如果是通过SQLAlchemy自动创建表,redshift_identity=(1,1)会正确生成IDENTITY列定义,配合autoincrement=False即可正常使用。
内容的提问来源于stack exchange,提问作者Pirikara
相关产品推荐
相关产品推荐

