2009-02-17 35 views
3

我在我的web應用程序中添加了「標記」功能。我的應用程序表結構如下:如何在SQL中編寫「標記」查詢?

Tag:

(TagId INT IDENTITY, TagName VARCHAR(60)) 

TaggedRecords:

(TaggedId INT IDENTITY, TagId, TaggedRecordId) 

現在,我要當有人增加了一個標籤,然後應該使用一個SQL查詢或使用存儲過程執行以下操作的任何記錄;

  • 該標籤已經存在於「標籤」表中嗎?
  • 如果該標籤存在,則插入行「TaggedRecords」表
  • 否則,如果標籤不存在,則首先將標籤中的「標籤」表,然後獲得新添加的標籤的ID和插入記錄在「TaggedRecord」表中

基本上,我更感興趣的是使用單個查詢或最大兩個sql查詢來完成這些操作。我不想在sql存儲過程中創建多個If-Else條件。

謝謝,

回答

1

這個怎麼樣...

CREATE PROC TagMe(@TagName VARCHAR(100),@TaggedRecordId INT) 
AS 

DECLARE @TagId INT 

SET @TagId = SELECT TagId FROM Tag WHERE TagName = @TagName 

IF @TagId IS NOT NULL 
    BEGIN 
    --Tag exists 
     INSERT INTO TaggedRecords (TagId, TaggedRecordId) VALUES(@TagId,@TaggedRecordId) 
    RETURN 
    END 
ELSE 
    -- New tag 
    BEGIN 
     INSERT INTO Tag (TagName) OUTPUT inserted.id INTO @TagId VALUES(@TagName) 
     INSERT INTO TaggedRecords (TagId, TaggedRecordId) VALUES(@TagId,@TaggedRecordId) 
    RETURN 
END 

沒有測試,但理論上應該是合理的:)

對於OUTPUT使用的另一個例子參見我的文章在this link

編輯

按低於這個評論版本使用EXISTS ...

CREATE PROC TagMe(@TagName VARCHAR(100),@TaggedRecordId INT) 
AS 

DECLARE @TagId INT 

IF EXISTS(SELECT TagId FROM Tag WHERE TagName = @TagName) 
    BEGIN 
    --Tag exists 
     SET @TagId = SELECT TagId FROM Tag WHERE TagName = @TagName 
     INSERT INTO TaggedRecords (TagId, TaggedRecordId) VALUES(@TagId,@TaggedRecordId) 
    RETURN 
    END 
ELSE 
    -- New tag 
    BEGIN 
     INSERT INTO Tag (TagName) OUTPUT inserted.id INTO @TagId VALUES(@TagName) 
     INSERT INTO TaggedRecords (TagId, TaggedRecordId) VALUES(@TagId,@TaggedRecordId) 
    RETURN 
END 

儘管我不確定(我相信我在這裏爭論自己,但這些東西有很多是「它取決於」的答案!)。這個例子實際上對於更多新標籤的使用效果最好,因爲它只會執行EXISTS一次,然後繼續執行,而對於現有的標籤,它將執行EXISTS然後執行SELECT。

嗯,你挑 - 或下音量:)

0

請問爲什麼? if/else有限制嗎? :)

看看你的情況,它看起來並不需要超過1個IF子句。

+0

你說得對是在使用了IF條款沒有限制,但實際上我看到了一個查詢的地方,它使用EXISTS子句做同樣的動作,我想做? http://www.techonthenet.com/sql/exists.php – Prashant 2009-02-17 17:28:43

+0

但條件是EXISTS子句將執行得更好然後如果或如果將執行更好。 – Prashant 2009-02-17 17:30:12

1

您已經基本掌握了它,但您可以通過更改順序使其更有效一些。下面是你的程序中一些僞-SQL代碼:

SELECT TagId FROM Tag WHERE TagName = @NewTag into @TagId 

IF @TagId IS NULL THEN 
    INSERT new tag, returning the new TagId into @TagId 

INSERT new record into TaggedRecords 

不知道爲什麼你這麼不利於使用if語句,但...


要獲得新生成的標籤識別到變量,我們有兩個選擇,因爲你正在使用MSSQL:

 INSERT INTO Tag (TagName) 
    OUTPUT Inserted.TagId INTO @TagId 
    VALUES (@NewTag);
  • 的標籤是唯一的,所以你應該能夠選擇它退了出來:
 INSERT INTO Tag (TagName) VALUES (@NewTag); 
    SELECT TagId FROM Tag WHERE TagName = @NewTag INTO @TagId;

如果您想選擇回來了,如果你使用的過程可能讀更好一個IF EXISTS條款,但基本上你做同樣的工作任何一種方式:

IF NOT EXISTS(SELECT TagId FROM Tag WHERE TagName = @NewTag) 
BEGIN 
    INSERT INTO Tag (TagName) VALUES (@NewTag); 
    SET @TagId = (SELECT TagId FROM Tag WHERE TagName = @NewTag); 
END 
ELSE 
BEGIN 
    SET @TagId = (SELECT TagId FROM Tag WHERE TagName = @NewTag); 
END 

INSERT new record into TaggedRecords 
+0

什麼「插入新標籤,將新TagId返回到@TagId」這意味着,我們將如何獲取@TagId變量中新生成的標識。 – Prashant 2009-02-17 17:26:49

0

您使用合併到您的標籤表格後插入到您的標記記錄表測試了這兩種方法。這是Oracle的語法,所以你必須調整它,但這個想法是一樣的:

MERGE INTO TAG 
USING (SELECT @tagname as TAGNAME FROM DUAL) RECORD 
ON (TAG.TAGNAME = RECORD.TAGNAME) 
WHEN NOT MATCHED THEN INSERT (TAG.TAGNAME) VALUES (@tagname); 

INSERT INTO TAGGEDRECORDS(TAGID) VALUES (SELECT TAGID FROM TAG WHERE [email protected]); 

我認爲SQL Server還支持MERGE語句中的一些功能更強大的功率,所以你很可能做一些與一個WHEN MATCHED(插入到taggedrecords表)子句。

退房 MSDN link