【问题标题】:Peewee, MySQL and INSERT IGNOREPeewee、MySQL 和 INSERT IGNORE
【发布时间】:2017-01-24 13:31:48
【问题描述】:

我在一个带有 MySQL DB 的小 Python 脚本中使用 Peewee 作为 ORM。

#!/usr/bin/python3
#coding: utf-8

import peewee
from peewee import *

db = MySQLDatabase(**config)
class Foo(peewee.Model):
    bar = peewee.CharField(unique=True, null=False)
    class Meta:
        database = db

try:
    Foo.create_table()
except:
    pass

foo_data = [{'bar':'xyz'},{'bar':'xyz'}]
Foo.insert_many(foo_data).on_conflict(action='IGNORE').execute()

如你所见,我有同样的钥匙。我想第二次使用on_conflict 方法忽略它(described in the API reference,但仅适用于 SQLite3),但运行脚本时出现此错误(正常,因为未针对 MySQL 实现):

peewee.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OR IGNORE INTO `foo` (`bar`) VA' at line 1")

如果我删除.on_conflict(action='IGNORE'),MySQL 也不喜欢它(重复键)。如果它是重复键,我如何让 peewee 插入新键或忽略它?

【问题讨论】:

    标签: python mysql python-3.x orm peewee


    【解决方案1】:

    使用db.__str__()。它返回

    <peewee.MySQLDatabase object at 0x7f4d6a996198>
    

    如果连接数据库是 MySQL 并且

    <peewee.SqliteDatabase object at 0x7fd0f4524198>
    

    如果连接数据库是Sqlite。

    所以你可以使用这样的 if 语句:

    if 'SqliteDatabase' in db.__str__():
        Foo.insert_many(foo_data).on_conflict(action='IGNORE').execute()
    elif 'MySQLDatabase' in db.__str__():
        try:
            Foo.insert_many(foo_data).execute() # or whatever you want with MySQL
        except:
            pass
    

    我认为对于 MySQL 数据库,您可以这样做:

    for data in foo_data:
        for k,v in data.items():
            if (Foo.select(Foo.bar).where(Foo.bar == v).count()) == 0:
                Foo.insert(bar=v).execute()
    

    所以这可以是:

    if 'SqliteDatabase' in db.__str__():
        Foo.insert_many(foo_data).on_conflict(action='IGNORE').execute()
    elif 'MySQLDatabase' in db.__str__():
        with db.atomic():
            for data in foo_data:
                for k, v in data.items():
                    if (Foo.select(Foo.bar).where(Foo.bar == v).count()) == 0:
                        Foo.insert(bar=v).execute()
    

    【讨论】: