求助:Python3.6+SQLite3如何仅插入非空值(INSERT OR IGNORE失效)
解决方案:仅在值非空时插入SQLite数据库
首先咱们先理清你遇到的问题根源:你用的INSERT OR IGNORE只会忽略违反唯一约束的行,但SQLite里NULL和任何值都不相等——包括另一个NULL。所以如果你的唯一约束列(比如你代码里注释的column5,作为主键/唯一键)允许NULL的话,插入多少条全NULL的行都会成功,因为它们不会被判定为重复,自然不会被IGNORE。
接下来针对你的需求,给你几个实用的解决办法:
方法一:在SQL语句里加条件过滤空值
直接在INSERT语句里用SELECT ... WHERE做判断,只有当至少一个字段非空时才执行插入。不用改Python逻辑,靠SQL本身过滤掉全空的情况:
cursor.execute(""" INSERT OR IGNORE INTO mytable (column1, column2, column3, column4, column5, column6) SELECT ?, ?, ?, ?, ?, ? WHERE ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL """, (value1, value2, value3, value4, value5, value6, value1, value2, value3, value4, value5, value6)) conn.commit()
如果你只要求特定字段必须非空才插入(比如主键column5),可以简化WHERE条件:
cursor.execute(""" INSERT OR IGNORE INTO mytable (column1, column2, column3, column4, column5, column6) SELECT ?, ?, ?, ?, ?, ? WHERE ? IS NOT NULL """, (value1, value2, value3, value4, value5, value6, value5)) conn.commit()
方法二:在Python代码里提前判断
如果觉得SQL里重复传参数麻烦,也可以在执行插入前先检查要插入的值:
# 检查是否至少有一个值非空(Python的None对应SQL的NULL) if any(v is not None for v in [value1, value2, value3, value4, value5, value6]): cursor.execute(""" INSERT OR IGNORE INTO mytable (column1, column2, column3, column4, column5, column6) VALUES (?, ?, ?, ?, ?, ?) """, (value1, value2, value3, value4, value5, value6)) conn.commit()
方法三:修改表结构,限制字段非空
如果你的业务逻辑要求某些字段绝对不能为NULL(比如主键column5),可以修改表结构给这些字段加上NOT NULL约束。这样插入NULL到这些字段时会触发约束冲突,INSERT OR IGNORE就会自动忽略这些行。
不过SQLite不支持直接修改现有列的约束,你需要通过临时表迁移数据:
-- 先创建带NOT NULL约束的新表 CREATE TABLE mytable_new ( column1 ..., column2 ..., column3 ..., column4 ..., column5 INT PRIMARY KEY UNIQUE NOT NULL, column6 ... ); -- 迁移旧数据 INSERT INTO mytable_new SELECT * FROM mytable; -- 删除旧表,重命名新表 DROP TABLE mytable; ALTER TABLE mytable_new RENAME TO mytable;
这样之后,再插入包含NULL的column5时,就会被INSERT OR IGNORE忽略掉了。
内容的提问来源于stack exchange,提问作者mrdd
相关产品推荐
相关产品推荐

