6

我正在使用 sqlalchemy 0.8 和 mysql 5.5

我有一个简单的表,其 ORM 定义如下所示

class TrackingTable(db.Model):

    __tablename__ = 'tracking_table'

    trackid = db.Column(db.BigInteger,primary_key=True)
    custid = db.Column(db.String(20), db.ForeignKey('customer.id'))
    tracktime = db.Column(db.DateTime ,nullable=False)
    formdata = db.Column(db.String(100),nullable=False)

我假设(根据文档)trackid 是 BIGINT 类型的主键,因此它将自动递增。

但是当我尝试在数据库中添加记录时

updateRecord = TrackingTable(custid='002',tracktime='2013-02-02',formdata='logged in')

db_session.add(updateRecord)
db_session.flush()
db_session.commit()

它发出警告警告:字段“trackid”没有默认值

并且它总是为 trackid 取值 0,因此第二次添加总是失败并出现错误 IntegrityError: (IntegrityError) (1062, "Duplicate entry '0' for key 'PRIMARY'") 'INSERT INTO tracking_table (custid, tracktime , 表格数据)

请帮我解决这个问题。理想情况下,我希望这是一个由数据库处理的增量值,但我不知道如何实现这一点。

提前致谢

4

4 回答 4

2

最可能的原因是tracking_table数据库中存在一个名为的现有表,该表具有定义的主键列,默认值为 0 但没有设置autoincrement,如下所示(省略了一些列):

CREATE TABLE `tracking_table` (
  `trackid` int(11) NOT NULL DEFAULT 0,
  `formdata` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`trackid`)
)

因为表已经存在,SQLAlchemy 不会尝试创建它。trackid一旦表包含等于零的单行,尝试写入表将触发观察到的异常。

至少有两种方法可以解决这个问题:

  • 在 trackid 列上设置自动增量;如果表中没有行,或者单行trackid等于零,这将起作用

    ALTER TABLE tracking_table MODIFY COLUMN  trackid int(11) auto_increment
    

    如果已经存在行,则更复杂

    ALTER TABLE tracking_table DROP CONSTRAINT PRIMARY KEY;
    ALTER TABLE tracking_table ADD COLUMN id int(11) primary key auto_increment;
    ALTER TABLE tracking_table DROP COLUMN trackid;
    ALTER TABLE tracking_table CHANGE COLUMN id trackid int(11) auto_increment;
    

    如果有外键关系,那就更棘手了。

  • 删除表并在数据库中或使用 SQLALchemy 的元数据方法重新创建它。同样,外键关系会使事情复杂化。

于 2021-08-17T13:16:12.147 回答
0

无法复制,在这里工作正常:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class TrackingTable(Base):

    __tablename__ = 'tracking_table'

    trackid = Column(BigInteger, primary_key=True)
    formdata = Column(String(100), nullable=False)

e = create_engine("mysql://scott:tiger@localhost/test", echo=True)
Base.metadata.create_all(e)

s = Session(e)

updateRecord = TrackingTable(formdata='logged in')

s.add(updateRecord)
s.commit()

print updateRecord.trackid

输出(记录垃圾被修剪掉):

SELECT DATABASE()
SHOW VARIABLES LIKE 'character_set%%'
SHOW VARIABLES LIKE 'sql_mode'
DESCRIBE `tracking_table`
ROLLBACK

CREATE TABLE tracking_table (
trackid BIGINT NOT NULL AUTO_INCREMENT, 
formdata VARCHAR(100) NOT NULL, 
PRIMARY KEY (trackid)
)

COMMIT
BEGIN (implicit)
INSERT INTO tracking_table (formdata) VALUES (%s)
('logged in',)
COMMIT
BEGIN (implicit)
SELECT tracking_table.trackid AS tracking_table_trackid, tracking_table.formdata AS tracking_table_formdata 
FROM tracking_table 
WHERE tracking_table.trackid = %s
(1L,)
1
于 2013-06-17T04:57:31.627 回答
0

您需要将字段值设置为“AUTO_INCREMENT”,而不是将实际值传递给它,而是传递 NULL。尝试先传递 NULL,因为它可能已经设置为 AUTO_INCREMENT。

于 2013-06-12T22:07:00.370 回答
0

你需要先刷新你的会话,然后它会知道你的索引位置要从哪里增加(我在这里借用@zzzeek的代码示例):

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class TrackingTable(Base):
    __tablename__ = 'tracking_table'
    trackid = Column(BigInteger, primary_key=True)
    formdata = Column(String(100), nullable=False)

e = create_engine("mysql://scott:tiger@localhost/test", echo=True)
Base.metadata.create_all(e)
s = Session(e)
# table tracking_table already exists, flush session to get index position
s.flush()
# you can now add new record 
updateRecord = TrackingTable(formdata='logged in') 
s.add(updateRecord)
s.commit()
于 2021-08-17T08:49:07.333 回答