2011-11-09 67 views
0

我試圖更新行,如果它存在,否則插入(在重複鍵更新)在MS Access,與答案來自這個問題SQL access query- Update row if exists, insert if does not與NOT IN子查詢

我插入查詢插入語句的形式爲:

INSERT INTO mytbl(id, title, notes) 
(SELECT 10, 'test', 'a' 
From mytbl 
WHERE 10 Not IN (select id from mytbl) 
) 

但我得到一個SQL語法錯誤。我在這裏錯過了什麼?

+2

你願意和我們分享這個錯誤? – zmilojko

+0

只是「INSERT INTO語句中的語法錯誤」 – Christine

+1

這可能是圍繞SELECT的括號。 – zmilojko

回答

2

你不需要外繞SELECT括號:

INSERT INTO mytbl(id, title, notes) 
SELECT TOP 1 10, 'test', 'a' 
FROM DummyTableWithExactlyOneRecord 
WHERE 10 Not IN (select id from mytbl) 

要處理重複密鑰錯誤,我添加了TOP 1子句。

您的查詢最初編寫的方式,如果10不是mytbl中的ID,那麼您的查詢的SELECT部分​​將返回mytbl中每個現有行的記錄。因爲您沒有引用表中的任何字段,它們都將是相同的行。例如,如果有在MYTBL四排,你會:

10 test a 
10 test a 
10 test a 
10 test a 

然後,它將嘗試爲每個返回的行執行插入。第一個會成功,其餘的會失敗並出現重複鍵錯誤。條款中的TOP 1表示只使用TOP 1記錄。在這種情況下訂單無關緊要。由於所有的字段都是文字,每一行都是相同的。

請注意,您可以通過將DISTINCT替換爲TOP 1來實現同樣的目的。不過,我認爲性能會更差,除非數據庫引擎足夠聰明才能認識到每行都是相同的。

編輯:DummyTableWithExactlyOneRecord是一個只有一條記錄的本地表。正如@onedaywhen在他的評論中指出的那樣,如果表格中沒有任何記錄,那麼您將不會插入任何記錄。

請注意,如果您可以保證您的虛擬表格總是隻有1條記錄,那麼TOP 1條款不是必需的。不過,我已經把它留了下來,因爲我認爲這讓讀者不知道虛擬表格的內容(我假設你將命名虛擬表格的內容比DummyTableWithExactlyOneRecord短)。

+0

現在我得到一個重複鍵錯誤,即使10真的不在mytbl中。但至少語法錯誤是固定的,謝謝! – Christine

+1

您正在獲取重複鍵錯誤,因爲如果10不是表中的ID值,則SELECT ... WHERE 10 Not IN(...)'返回每行「mytbl」的結果。 – mwolfe02

+0

啊,這很有道理。在TOP 1放入SELECT子句後,它現在正確插入。感謝您的幫助,這讓我瘋狂。 – Christine

0

我想ü正在尋找ID,而不是10

試試這個

WHERE id NOT IN (SELECT id FROM mytbl

+1

我試圖插入一個值到ID如果該值不是在mytbl,所以我很確定我需要爲NOT IN運算符指定一些值... – Christine

0

這裏有趣的是你試圖在表中插入常量值,同時驗證UNIQUE INDEX(或PK)不存在。因此,您的WHERE子句必須以這樣的方式構造,即它會產生FALSE條件,因此不會生成要插入的行。

你有沒有考慮下面的SQL:

INSERT INTO mytbl(id, title, notes) VALUES (10, 'test', 'a'); 

如果這是對於通過填充表與SQL傳遞一種形式的僞代碼:

INSERT INTO mytbl(id, title, notes) 
SELECT 10, 'test', 'a' 
From mytbl 
WHERE id NOT IN (SELECT id FROM mytbl WHERE id = 10) 

通常是恆定值,使用插入或者沿着這些線路,可能會更容易地捕獲PK違例的錯誤代碼並將錯誤報告給用戶。

希望這會有所幫助。

0

SQL DDL

CREATE PROCEDURE AddMyStuff 
(
:id CHAR(10), 
:title VARCHAR(15), 
:notes VARCHAR(100) = '{{NONE}}' 
) 
AS 
INSERT INTO mytbl (id, title, notes) 
SELECT :id, :title, :notes 
    FROM MySystemTableAlwaysHasExactlyOneRow 
WHERE :id NOT IN (SELECT id FROM mytbl); 

SQL DML

EXECUTE AddMyStuff 10, 'test', 'a';