我正在尝试检查数据库中是否已存在记录(通过类似标题),如果没有则插入。我已经尝试了两种方法,但两种方式都没有用。
更优雅的方式(?)使用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"
它永远不会打印出“我在这里”的测试声明。什么会阻止它进入那里?它似乎很明显 - 我一直在检查我的缩进,我在命令行上测试它并明确指定所有三个参数。
答案 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注入。