如果类似尚不存在,则插入记录时出现问题

时间:2010-12-11 19:27:39

标签: python mysql select

我正在尝试检查数据库中是否已存在记录(通过类似标题),如果没有则插入。我已经尝试了两种方法,但两种方式都没有用。

更优雅的方式(?)使用IF NOT EXISTS

if mode=="update":
    #check if book is already present in the system
    cursor.execute('IF NOT EXISTS (SELECT * FROM book WHERE TITLE LIKE "%s") INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s") END IF;' % (title,title,author,isbn))
    cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title))
    bookID = cursor.fetchall()
    print('found the bookid %s' % (bookID))
    #cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work

有了这个,我在IF NOT EXISTS查询中得到一个错误,说“作者”没有定义(虽然它是)。

使用匹配记录计数的优雅方式

if mode=="update":
    #check if book is already present in the system
    cursor.execute('SELECT COUNT(*) FROM book WHERE title LIKE "%s";' % (title))
    anyresults = cursor.fetchall()
    print('anyresults looks like %s' % (anyresults))
    if anyresults[0] == 0: # if we didn't find a bookID
        print("I'm in the loop for adding a book")
        cursor.execute('INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s");' % (title,author,isbn))
    cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title))
    bookID = cursor.fetchall()
    print('found the bookid %s' % (bookID))
    #cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work

在这个版本中,anyresults是一个看起来像(0L,)的元组,但我找不到匹配它的方法,这让我进入“添加书籍的循环”。 if anyresults [0] == 0,0L,'0','0L' - 这些似乎都没有让我进入循环。

我想我可能没有正确使用IF NOT EXISTS - 我发现的例子是针对单独的程序,这些程序并不属于这个小项目的范围。

此外: 我认为unutbu的代码工作得很好,但是我仍然会得到这个愚蠢的NameError,说作者是未定义的,这会阻止INSERT被尝试,即使我肯定将其传入。

if form.has_key("title"): 
    title = form['title'].value
    mode = "update"
if form.has_key("author"): 
    author = form['author'].value
    mode = "update"
    print("I'm in here")
if form.has_key("isbn"):
    isbn = form['isbn'].value
    mode = "update"

它永远不会打印出“我在这里”的测试声明。什么会阻止它进入那里?它似乎很明显 - 我一直在检查我的缩进,我在命令行上测试它并明确指定所有三个参数。

2 个答案:

答案 0 :(得分:0)

这不能回答你的问题,因为它是针对Postgresql而不是MySQL,但我想我会把它放在那里搜索他们的人。

在Postgres中,如果项目不存在,您可以批量插入项目:

CREATE TABLE book (title TEXT, author TEXT, isbn TEXT);

# Create a row of test data:
INSERT INTO book (title,author,isbn) VALUES ('a', 'b', 'c');

# Do the real batch insert:
INSERT INTO book
SELECT add.* FROM (VALUES
 ('a', 'b', 'c'),
 ('d', 'e', 'f'),
 ('g', 'h', 'i'),
) AS add (title, author, isbn)
LEFT JOIN book ON (book.title = add.title)
WHERE book.title IS NULL;       

这很简单。它选择新行就像它们是一个表一样,然后将它们与现有数据连接起来。尚不存在的行将连接到NULL行;然后我们过滤掉已经存在的那些(book.title不是NULL)。这非常快:它只需要一个数据库事务就可以执行大批插入,并且让数据库后端进行批量连接,这非常擅长。

顺便说一句,你真的需要直接停止格式化你的SQL查询(除非你真的必须并且真的知道你正在做什么,而你不在这里)。使用查询替换,例如。 cur.execute("SELECT * FROM table WHERE title=? and isbn=?", (title, isbn))

答案 1 :(得分:0)

如果在book上设置UNIQUE索引,则插入唯一行很容易。

例如,

mysql> ALTER IGNORE TABLE book ADD UNIQUE INDEX book_index (title,author);

警告:如果存在具有非唯一(标题,作者)对的行,则除了一行之外的所有行都将被删除。

如果您只希望author字段是唯一的,则只需将(title,author)更改为(author)即可。

根据桌子的大小,这可能需要一段时间......

现在,要插入唯一记录,

sql='INSERT IGNORE INTO book (title,author,isbn) VALUES (%s, %s, %s)'
cursor.execute(sql,[title,author,isbn])

如果(title,author)是唯一的,则会将三元组(title,author,isbn)插入book表中。

如果(title,author)不唯一,则忽略INSERT命令。

注意,cursor.execute的第二个参数。以这种方式传递参数有助于防止SQL注入。