在pysqlite中,违反NOT NULL
或UNIQUE
约束同样会引发IntegrityError。
不幸的是,此Exception类型不提供错误代码,而只提供消息。
所以,假设我想忽略唯一约束违规,因为我知道这对给定数据是安全的,但是应该报告关键列中的Null值。
我提出了以下解决方案:
con = sqlite3.connect(':MEMORY:')
con.execute('''CREATE TABLE ABCD (A TEXT NOT NULL,
B TEXT NOT NULL,
C TEXT NOT NULL,
D TEXT NOT NULL,
PRIMARY KEY (A, B))''')
with con:
for a, b, c, d in inputs:
try:
con.execute('INSERT INTO ABCD VALUES (?, ?, ?, ?)',
(a, b, c, d))
except sqlite3.IntegrityError as e:
# Skip 'not unique' errors, but raise others.
if not e.message.endswith('not unique'):
raise
con.close()
但是,解析错误消息似乎是错误的,可能不可靠。
有没有更好的方法来实现这一点,甚至可能使用con.executemany()
?
答案 0 :(得分:2)
这就是我最终做的事情:
con = sqlite3.connect(':MEMORY:')
con.execute('''CREATE TABLE ABCD (A TEXT NOT NULL,
B TEXT NOT NULL,
C TEXT NOT NULL,
D TEXT NOT NULL,
PRIMARY KEY (A, B))''')
with con:
for a, b, c, d in inputs:
if any(elem is None for elem in (a, b, c, d)):
raise ValueError('Fields must not be empty.')
con.execute('INSERT OR IGNORE INTO ABCD VALUES (?, ?, ?, ?)',
(a, b, c, d))
con.close()
像这样,空值被捕获"手动"在执行DB操作之前。如果在execute
期间发生任何错误(例如违反UNIQUE
约束),则跳过该条目。请注意INSERT OR IGNORE
并不意味着忽略唯一性约束,而是忽略(即跳过)输入行。
此解决方案的缺点是检查空值两次。我想这不是太糟糕,因为它可能是相当便宜的操作。我认为,它仍然比解析错误消息更清晰,并且可能对更改更加健壮(例如pysqlite更新,这可能会更改错误消息中的某些细节)。
致谢:这个想法来自与Lutz的讨论。它也是Martijn独立提出的。
答案 1 :(得分:0)
更优雅的解决方案是完全依赖SQL(ite)功能。
通过为主键(ON CONFLICT IGNORE
)指定冲突子句,已经实现了所需的行为:
con = sqlite3.connect(':memory:')
con.execute('''CREATE TABLE ABCD (A TEXT NOT NULL,
B TEXT NOT NULL,
C TEXT NOT NULL,
D TEXT NOT NULL,
PRIMARY KEY (A, B) ON CONFLICT IGNORE)''')
因此,会以静默方式跳过重复行(违反主键的唯一性约束),而Null值会导致中止(导致sqlite3
异常)。这一切都是在没有预先过滤Null / None值的数据或摆弄sqlite3
API的错误消息的情况下实现的。
我们现在可以简单地拨打con.executemany()
,而不用再费力了:
with con:
con.executemany('INSERT INTO ABCD VALUES (?, ?, ?, ?)', inputs)
答案 2 :(得分:-1)
以下是工作代码:
import sqlite3
con = sqlite3.connect(':memory:')
con.execute('''CREATE TABLE ABCD (A TEXT NOT NULL,
B TEXT NOT NULL,
C TEXT NOT NULL,
D TEXT NOT NULL,
PRIMARY KEY (A, B));''')
inputs = [('cow', 'pig', 'cat', 'dog'), ('cow', 'pig', 'quail', 'turkey')]
with con:
for a, b, c, d in inputs:
try:
con.execute('INSERT INTO ABCD VALUES (?, ?, ?, ?);',
(a, b, c, d))
except sqlite3.IntegrityError as e:
if 'not null' in e.args[0].lower():
print('There is a NULL value')
elif 'unique constraint' in e.args[0].lower():
print('There is unique violation')
else:
raise
测试:
>>>
There is a NULL value
>>>
第二次测试结果:
>>>
There is unique violation
>>>
希望,可以帮到你。