2012-02-26 90 views
7

好吧,這裏有一個快速的SQL問題(使用sql-server-2008)。SQL選擇或插入返回ID

我有一個映射表names有以下的列

IDDisplayName

我想要做的是首先 SELECT [ID] FROM [names] WHERE [DisplayName] = 'chuck';

但是,如果名稱爲「夾頭」不中不存在數據庫,我想創建它,並返回自動遞增的ID

我想知道SQL是否有一些簡單的方法構建,或者如果我必須走長路線?

長的路線是這樣的

SELECT COUNT(ID) AS count, ID FROM names WHERE DisplayName='chuck' 
IF(count > 0) 
    SELECT ID as ReturnID; 
ELSE 
    BEGIN 
    INSERT INTO names(DisplayName) values('chuck'); 
    SELECT scope_identity() as ReturnID; 
    END 

我沒有測試這一句,但我相信在很長的路將是類似的東西。如果沒有內置的方式,我會很感激,如果有人可以簡單地糾正該聲明(因爲我確信它不完全正確)。

+3

如果只支持200 * +,請使用[MERGE語法](http://technet.microsoft.com/en-us/library/bb510625.aspx) – 2012-02-26 22:15:03

+0

您能否提供示例?我試圖學習使用sql的更高級的方法。 – 2012-02-26 22:19:21

+0

@ kelton52:OMG Ponies文章的末尾有一些例子。你需要向下滾動一下。 – 2012-02-26 22:59:19

回答

4

你應該關心的交易,以及:

set XACT_ABORT on 
begin tran 

declare @ID int 

select @ID = ID from names with (holdlock, updlock) WHERE DisplayName='chuck' 

if @@rowcount = 0 
begin 
    INSERT INTO names(DisplayName) values('chuck'); 
    set @ID = scope_identity(); 
end 

select @ID as ReturnID; 

commit tran 

注表提示的使用 - HOLDLOCKUplock。它們阻止另一個線程執行完全相同的查詢並第二次創建該行。有關更多信息,請查看隔離,同步,死鎖和併發更新。

+0

好吧,所以跑了這個,現在桌子僵住了...有什麼想法? – 2012-02-26 22:50:03

+0

你也有從那裏兩次,假設不是故意的 – 2012-02-26 22:50:25

+0

也SQL不能識別xac_abort – 2012-02-26 22:50:40

0

我會做:

IF (NOT EXISTS(SELECT null from names where DisplayName='Chuck')) 
    INSERT INTO Names (DisplayName) Values ('Chuck') 

SELECT ID as ReturnID FROM Names where DisplayName='Chuck' 

不節省多少雖然

+0

這不是最多執行2個查詢,最差的是執行1個查詢? – crush 2015-06-29 21:47:31