【问题标题】:Integrity Error when trying to upload to MySQL DB in python尝试在 python 中上传到 MySQL DB 时出现完整性错误
【发布时间】:2020-06-04 14:25:56
【问题描述】:

如果 id 已经存在,我目前有这段代码可以让我更新 mySQL 数据库中的学校数据。但是,我还试图实现的是,如果数据库中不存在 ID,它会插入这些值。这是我目前得到的代码:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/dbName'
db = SQLAlchemy(app)

class Example(db.Model):
    __tablename__ = 'schools'
    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)

    def __init__(self, id, establishmentNumber):
        self.id = id
        self.establishmentNumber = establishmentNumber

update_this = Example.query.filter_by(_id=school._id.iloc[0]).first()

update_this.establishmentNumber = 'bob'
db.session.commit()

examples = Example.query.all()
examples

for ex in examples:
    print (ex.establishmentNumber)

但是,当我尝试使用以下代码向数据库添加一个全新的学校时,这将正确更新:

new_ex = Example('5c12345scl', 'fifth')
db.session.add(new_ex)
db.session.commit()

我收到此错误:

IntegrityError: (MySQLdb._exceptions.IntegrityError) (1364, "Field '_id' doesn't have a default value")
[SQL: INSERT INTO schools (`establishmentNumber`) VALUES (%s)]
[parameters: ('fifth',)]
(Background on this error at: http://sqlalche.me/e/gkpj)

有谁知道如何摆脱这个错误?

'''''''''''''''''''''''''''''''''''''''''''' '''''''''''' 更新 ''''''''''''''''''''''''''''''''''''''''''''' '''''''''

以上内容现在正在运行。我现在正在尝试组合 add 和 update 函数,以便它检查表中是否存在 id。如果不是,它会插入一个新行。如果是这样,那么它只是更新值。以下是我目前的代码,感谢@James Summers:

class Example(db.Model):
    __tablename__ = 'schools'
    _id = db.Column('_id', db.Unicode, primary_key=True)
    establishmentNumber = db.Column('establishmentNumber', db.Unicode)
    laCode = db.Column('laCode', db.Unicode)
    urn = db.Column('urn', db.Unicode)
    name = db.Column('name', db.Unicode)
    phaseOfEducation = db.Column('phaseOfEducation', db.Unicode)
    wondeID = db.Column('wondeID', db.Unicode)

    def __init__(self, _id, establishmentNumber, laCode, urn, name, phaseOfEducation, wondeID):
        self._id = _id
        self.establishmentNumber = establishmentNumber
        self.laCode = laCode
        self.urn = urn
        self.name = name
        self.phaseOfEducation = phaseOfEducation
        self.wondeID = wondeID

        def add_or_update(self, _id, establishmentNumber, laCode, urn, name, phaseOfEducation, wondeID):
            update_this = Example.query.filter_by(_id=school._id.iloc[0]).first()

            if not update_this:
                new_ex = Example(school._id.iloc[0], school.establishmentNumber.iloc[0], school.laCode.iloc[0], school.urn.iloc[0], school.name.iloc[0], school.phaseOfEducation.iloc[0], school.wondeID.iloc[0])
                db.session.add(new_ex)
                db.session.commit()

            else:
                update_this.establishmentNumber = 'hello'
                db.session.commit()

            return new_ex

它没有产生任何错误,但也没有添加或更新。谁能看到我做错了什么?

【问题讨论】:

  • 有谁知道如何消除此错误? 只需更改表格并将默认值(例如,零)添加到有问题的字段。
  • 感谢@Akina 的快速回复。我很抱歉,但我不太明白。我希望将 _id 字段设置为 '5c12345scl' 并将establishmentNumber 设置为 'fifth'。所以,我不想要一个默认值。
  • 你问过“如何摆脱这个错误?”。所以你假设其他的一切都是正确的。我给你解决方案。真的 - 错误消息告诉您的程序尝试执行 INSERT INTO schools (`establishmentNumber`) VALUES (%s) 并且没有在此查询中设置 _id - 这意味着您的代码中有一些逻辑或算法错误。搜索它(我无法帮助你解决这个任务,除了它存在的事实,我不知道烧瓶)。

标签: python mysql database flask-sqlalchemy


【解决方案1】:

感谢@Akina 的 cmets。我意识到问题出在这个函数的代码上:

def __init__(self, id, establishmentNumber):
    self.id = id
    self.establishmentNumber = establishmentNumber

我写的id没有下划线,所以这是固定版本:

def __init__(self, _id, establishmentNumber):
    self._id = _id
    self.establishmentNumber = establishmentNumber

【讨论】:

    【解决方案2】:

    错误可能与您的构造函数有关。

    你有一个班级成员是: _id = db.Column('_id', db.Unicode, primary_key=True)

    但是在你的构造函数中你设置self.id = id

    解决此问题的方法是更新您的模型以使代码如下所示:

    class Example(db.Model):
        __tablename__ = 'schools'
        _id = db.Column('_id', db.Unicode, primary_key=True)
        establishmentNumber = db.Column('establishmentNumber', db.Unicode)
    
        def __init__(self, id, establishmentNumber):
            self._id = id
            self.establishmentNumber = establishmentNumber
    

    或 cmets 中的某个人建议通过向您的列添加默认值来执行此操作。但是,我不建议为您的主键添加默认值。

    这个问题的另一个可能的解决方案是为你的类创建一个add_or_update 方法,从长远来看,这是更好的解决方案。您可以通过添加一个通过 id 获取结果的类方法来做到这一点,如果它不存在,您的代码将创建一个或更新现有的检索结果。这就是您将如何实现以下代码的方式:

    class Example(db.Model):
        __tablename__ = 'schools'
    
        _id = db.Column('_id', db.Unicode, primary_key=True)
        establishmentNumber = db.Column('establishmentNumber', db.Unicode)
    
        def __init__(self, id, establishmentNumber):
            self._id = id
            self.establishmentNumber = establishmentNumber
    
        @classmethod
        def add_or_update(cls, example_id, establishmentNumber):
            entity = cls.query.filter_by(id=example_id).first()
    
            if not entity:
              entity = cls(example_id, establishmentNumber)
    
            entity.establishmentNumber = establishmentNumber
    
            db.session.add(entity)
            db.session.commit()
    
            return entity
    

    祝你好运和欢呼!

    【讨论】:

    • 非常感谢@James Summers 的详细回复。我试图实现你的 add_or_update 函数,但是,它似乎没有工作。你能看看我做错了什么吗?它不会产生任何错误,但也不会添加或更新。请参阅我的代码的更新问题。谢谢
    • 我看到在您的代码示例中,您没有使用 @classmethod 装饰器。这就是为什么您的 add_or_update 方法无法按预期工作的原因。因为您没有使用该装饰器,所以您的方法需要一个自身的实例,然后才能调用该方法。通过使用 classmethod 装饰器,您可以调用您的函数,而无需先获取类的实例然后再使用它。我还可以在您提供的示例代码中看到,您已经在构造函数中定义了该方法。把它移出去。方法的使用方法是Example.add_or_update(1, 2)
    • 谢谢@James Summers。它现在正在工作。只是一个简单的问题 - 我如何更改 add_or_update 函数中的 iloc[0] 以查看所有可用的 id 而不是只做第一个?
    • 我不确定 iloc 数组是什么,因为我还没有看到它的代码。而且我似乎找不到你从哪里得到学校物品的地方。您可以将学校对象传递给 add_or_update 方法,然后循环 iloc 数组。 for school in school.iloc: Example.add_or_update(school),类似的东西。或者,您可以在 add_or_update 方法中循环学校 iloc 数组。
    • 谢谢@James Summers。刚刚意识到我不需要 iloc。只需添加 row._id 等,它就会为我循环
    猜你喜欢
    • 2022-08-11
    • 2016-07-08
    • 1970-01-01
    • 2017-01-11
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多