SQLite NOT NULL约束不适用于INSERT或IGNORE

时间:2013-04-18 20:23:45

标签: python sql python-2.7 sqlite

我使用的是Python 2.7和SQLite3。

以下是代码:

#!/usr/bin/env python

import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('''CREATE TABLE stocks
             (transctionid text not null collate nocase primary key,
             trans text,
             symbol text not null,
             qty real,
             price real)''')
purchases = [('B1Jan', 'BUY', 'IBM', 1000, 45.00),
             ('C2Jan', 'BUY', 'MSFT', 1000, 72.00),
             ('D3Jan', 'SELL', 'IBM', 500, 53.00),
             ('d3jan', 'SELL', 'IBM', 500, 53.00),
             ('', 'SELL', 'IBM', 500, 53.00),
             ('E5Jan', 'SELL', '', 500, 53.00),
            ]
c.executemany('INSERT OR IGNORE INTO stocks VALUES (?,?,?,?,?)', purchases)
conn.commit()
for row in c.execute('SELECT * FROM stocks ORDER BY price'):
    print row
conn.close()

结果是:

(u'B1Jan', u'BUY', u'IBM', 1000.0, 45.0)
(u'D3Jan', u'SELL', u'IBM', 500.0, 53.0)
(u'', u'SELL', u'IBM', 500.0, 53.0)
(u'E5Jan', u'SELL', u'', 500.0, 53.0)
(u'C2Jan', u'BUY', u'MSFT', 1000.0, 72.0)

INSERT或IGNORE仅适用于“PRIMARY KEY”约束。 “NOT NULL”约束无效。

根据http://www.sqlite.org/lang_conflict.html

  

对于INSERT和UPDATE命令,关键字“ON CONFLICT”是   替换为“OR”,以便语法更自然地读取。例如,   而不是“INSERT ON CONFLICT IGNORE”,我们有“INSERT OR IGNORE”。 ......   ON CONFLICT子句适用于UNIQUE和NOT NULL约束(以及   对于本节而言,主要的约束条件是   与UNIQUE约束相同的事情。)

我期望的结果是:

(u'B1Jan', u'BUY', u'IBM', 1000.0, 45.0)
(u'D3Jan', u'SELL', u'IBM', 500.0, 53.0)
(u'C2Jan', u'BUY', u'MSFT', 1000.0, 72.0)

顺便说一句,我如何知道哪一行成功插入以及哪一行是在IGFLORED CONFLICT?

2 个答案:

答案 0 :(得分:1)

空字符串不计为NULL,而是计为0长度字符串。

如果您希望插入SQL None,请使用NULL

purchases = [('B1Jan', 'BUY', 'IBM', 1000, 45.00),
             ('C2Jan', 'BUY', 'MSFT', 1000, 72.00),
             ('D3Jan', 'SELL', 'IBM', 500, 53.00),
             ('d3jan', 'SELL', 'IBM', 500, 53.00),
             (None, 'SELL', 'IBM', 500, 53.00),
             ('E5Jan', 'SELL', None, 500, 53.00),
            ]

请参阅sqlit3文档的SQLite and Python types部分。

如果您需要知道是否已成功插入行,请逐个插入cursor.execute(),然后再检查cursor.rowcount; .rowcount反映受影响的行数,对于.executemany()调用NULL值,rowcount为3,没有关于哪些行成功以及哪些行失败的信息。

答案 1 :(得分:0)

''与NULL不同。将''替换为None

如果您想知道哪些行违反了约束条件,请移除OR IGNORE并处理sqlite3.IntegrityError。下面的代码示例逐个插入行并打印(可以修改为写入文件,记录错误表等),这样您就知道哪些值无法插入以及为什么:

import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('''CREATE TABLE stocks
             (transctionid text not null collate nocase primary key,
             trans text,
             symbol text not null,
             qty real,
             price real)''')
purchases = [('B1Jan', 'BUY', 'IBM', 1000, 45.00),
             ('C2Jan', 'BUY', 'MSFT', 1000, 72.00),
             ('D3Jan', 'SELL', 'IBM', 500, 53.00),
             ('d3jan', 'SELL', 'IBM', 500, 53.00),
             (None, 'SELL', 'IBM', 500, 53.00),
             ('E5Jan', 'SELL', None, 500, 53.00)]
for purchase in purchases:
    try:
        c.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', purchase)
    except sqlite3.IntegrityError as e:
        print "Couldn't insert row {}:\n {}".format(purchase, e)
        pass
conn.commit()
for row in c.execute('SELECT * FROM stocks ORDER BY price'):
    print row
conn.close()