django SQL 插入数据:on duplicate key update

1、作用

insert数据时如果数据存在则更新对应行记录,否则插入数据。

具体看应用。

2、应用

……
def createtable(……):
    CREATE TABLE IF NOT EXISTS `access_equipment` (
        id int(10) NOT NULL AUTO_INCREMENT,
        access_id varchar(255) NOT NULL,
        access_ip varchar(255) NOT NULL,
        access_name varchar(255) NOT NULL,
        access_online int(2) NOT NULL,
        PRIMARY KEY (id, access_id, access_ip)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

def insert(……):
    insert_sql = f"""insert into `{table_name}` ({",".join(storage_columns)}) values {data_str}
    on duplicate key update {",".join([f'{i} = values({i})' for i in storage_columns])}"""  
    ……
……

注意:

  • 我在id,access_id,access_ip创建了复合主键。 id是自增类型,AUTO_INCREMENT。

插入结果:

  • 如果这样去插入数据on duplicate key是不会生效的,即第一次插入了10条数据,第二次插入10条,并且第二次插入的10条中有5条是跟第一次插入时是相同的,那么现在数据库中数据是20条,而不是我们期望的15条。

原因:

  • 我们需要确保插入的数据中存在相同的 (id, access_id, access_ip) 组合,才能触发 ON DUPLICATE KEY UPDATE。但是id是自增的,所以不存在相同的该组合。导致on duplicate key不生效。

解决:

  1. 不要设置id为自增,可以用雪花算法等生成数据库唯一ID
  2. 不要id这个选项,只在(access_id, access_ip)设置复合主键。这样当插入的数据(access_id, access_ip)相同时就会更新而不是直接插入。

正确创建表代码:

……
def createtable(……):
    CREATE TABLE IF NOT EXISTS `access_equipment` (
        access_id varchar(255) NOT NULL,
        access_ip varchar(255) NOT NULL,
        access_name varchar(255) NOT NULL,
        access_online int(2) NOT NULL,
        PRIMARY KEY (id, access_id, access_ip)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
……

发表评论

评论列表,共 0 条评论

    暂无评论