2017-03-04 58 views
0

我使用SQLite和有一个表,看起来像这样:得到一个主键的ID的INSERT后或忽略

CREATE TABLE IF NOT EXISTS dirnames (dirnameid INTEGER PRIMARY KEY, 
            dirname TEXT NOT NULL UNIQUE); 
CREATE INDEX IF NOT EXISTS dirnames_idx1 ON dirnames(dirnameid); 
CREATE INDEX IF NOT EXISTS dirnames_idx2 ON dirnames(dirname); 

我想获得一个任意目录的dirnameid,所以正确的我现在做的事情是这样的:

INSERT or IGNORE INTO dirnames (dirname) VALUE (?) 
SELECT dirnameid from dirnames where dirname=? 

?取代有我的目录名。

有没有做到这一点

回答

1

更有效的方式有没有办法对任何进一步优化此查询,因为它需要在SQLite的,做这个动作的指令 - 它不存在。

但是,有一种方法可以'优化':您可以尝试使用LBYL tatics,因此如果该目录已经存在,您将'保存'往返。

伪代码(因为我不知道你的代码的样子):

import sqlite3 

#(...) 

connection = sqlite3.connect(':memory:') 
cursor = connection.cursor() 

dirname = 'foo' 
dirnameid = None 

cursor.execute("SELECT dirnameid from dirnames where dirname=?;", (dirname,)) 
dirnameid = cursor.fetchone()[0] 

if not dirnameid: 
    cursor.execute("INSERT or IGNORE INTO dirnames (dirname) VALUES (?);", (dirname,)) 

    # WARNING: The following line should be used if, and ONLY if the access to the sqlite is not concurrent (AKA: Only one connection inserting to the table) 
    dirnameid = cursor.lastrowid 

    # Otherwise, use this: 
    cursor.execute("SELECT dirnameid from dirnames where dirname=?;", (dirname,)) 
    dirnameid = cursor.fetchone()[0] 

connection.close() 

可悲的是,这种代码将再增加往返,如果这是不是唯一的程序/线程在桌子上工作。

但是我必须警告你,这似乎是一个不成熟的优化,应该不惜一切代价避免! (https://softwareengineering.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil

+0

谢谢。是的,在该项目不在表格中的情况下,您的伪代码会生成3条语句。嗯。好的。谢谢! – vy32

+0

如果代码不是并发的,它可能会使用3,否则它只会使用2.没有完全运行代码,只是让它回答问题 –