2017-03-04 68 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.沒有完全運行代碼,只是讓它回答問題 –