2012-11-22 57 views
1

我有表保存用戶訪問權限:內部程序TSQL添加或刪除行基於選擇

Id | UserId | SectionId 
    --------------------------- 
    1 | 1  | 1 
    2 | 1  | 2 
    3 | 2  | 1 
    4 | 1  | 3 

使用此代碼:

CREATE FUNCTION dbo.Split (@List NVARCHAR(2000), 
         @SplitOn NVARCHAR(5)) 
returns @RtnValue TABLE ( 
    id INT IDENTITY(1, 1), 
    value NVARCHAR(100)) 
AS 
BEGIN 
    WHILE (Charindex(@SplitOn, @List) > 0) 
    BEGIN 
     INSERT INTO @RtnValue 
        (value) 
     SELECT Value = Ltrim(Rtrim(Substring(@List, 1, Charindex(@SplitOn, 
                 @List) 
                 - 1))) 

     SET @List = Substring(@List, Charindex(@SplitOn, @List) + Len( 
            @SplitOn 
            ), 
        Len 
        (@List)) 
    END 

    INSERT INTO @RtnValue 
       (value) 
    SELECT Value = Ltrim(Rtrim(@List)) 

    RETURN 
END 

我創建的返回(現在所有的功能記錄爲特定的用戶和部分):

CREATE PROCEDURE UpdateSettings(@UserId int, @NewSettings nvarchar(255)) 
AS 
BEGIN 
    SELECT * 
    FROM settings 
    WHERE 
    UserId = @UserId AND 
    SectionId IN (SELECT convert(int,Value) FROM dbo.Split(@NewSettings,',')) 
END; 

這是可用於測試在http://sqlfiddle.com/#!3/79de7/4

我想修改此程序,以便刪除存在的項目並添加新的項目。

這裏是一個例子。我想改變這一點:

Id | UserId | SectionId 
    --------------------------- 
    1 | 1  | 1 
    2 | 1  | 2 
    3 | 2  | 1 
    4 | 1  | 3 

分爲:

Id | UserId | SectionId 
    --------------------------- 
    1 | 1  | 1 
    3 | 2  | 1 
    4 | 1  | 3 
    5 | 1  | 4 

這應該通過調用來完成:

EXEC UpdateSettings @UserId=1, @NewSettings='2,4' 

因爲有一行用戶ID = 1和SectionId = 2程序應刪除它,因爲對於userId = 1和SectionId = 4行不存在我想創建它。

我的第一個想法是爲NewSettings創建一個遊標,然後檢查該行是否存在,如果是,刪除它,如果沒有添加它。

二的想法是刪除所有已經存在的行,像這樣:

CREATE PROCEDURE UpdateSettings(@UserId int, @NewSettings nvarchar(255)) 
AS 
BEGIN 
    DELETE 
    FROM settings 
    WHERE 
    UserId = @UserId AND 
    SectionId IN (SELECT convert(int,Value) FROM dbo.Split(@NewSettings,',')) 
    END; 

這樣我就可以刪除現有的記錄,但不知道怎樣在我的例子中添加新的(像我必須刪除表中的一行,並添加一個新的)

我想避免光標,也許做一些類型的JOIN,但我不知道如何做到這一點。

回答

0

如果我這樣做,我會保持它的簡單:

  1. 刪除所有現有的數據爲用戶
  2. 插入該用戶的所有新數據

的好處是:

  • 易碼
  • 易於理解
  • 你希望達到最優化可能是如此的渺小,不值得麻煩
+0

是的,我明白,這將是最簡單的方法。我的程序從asp頁面調用。我有一個非常大的表格和複選框,並儘量減少請求我只發送更改到服務器。如果我有1000個複選框(只是一個示例),並且用戶只更改一個,然後單擊保存按鈕,我只想更新該設置 - 刪除該行或添加新記錄。我認爲這比刪除1000行並添加1000個新的更好。 – Misiu

0

在SQL Server2005中

CREATE PROCEDURE UpdateSettings(@UserId int, @NewSettings nvarchar(255)) 
AS 
BEGIN 
    DECLARE @tmp TABLE(UserId int, SectionId int) 
    DELETE s 
    OUTPUT DELETED.UserId, DELETED.SectionId INTO @tmp 
    FROM settings s JOIN (
         SELECT @UserId AS UserId, CONVERT(int, Value) AS SectionId 
         FROM dbo.Split(@NewSettings, ',') 
         ) d ON s.UserId = d.UserId AND s.SectionId = d.SectionId 
    INSERT settings(UserId, SectionId) 
    SELECT @UserId AS UserId, CONVERT(int,Value) AS SectionId 
    FROM dbo.Split(@NewSettings, ',') d LEFT JOIN @tmp t ON CONVERT(int, d.Value) = t.SectionId 
             LEFT JOIN settings s ON @UserId = s.UserId AND CONVERT(int, d.Value) = s.SectionId 
    WHERE t.UserId IS NULL AND s.UserId IS NULL 
END 

在SQLServer的2008年

CREATE PROCEDURE UpdateSettings(@UserId int, @NewSettings nvarchar(255)) 
AS 
BEGIN 
    MERGE settings AS target 
    USING (
     SELECT id, @UserID AS UserId, value AS SectionId 
     FROM dbo.Split(@NewSettings,',') 
     ) AS source 
    ON (target.UserId = source.UserId AND target.SectionId = source.SectionID) 
    WHEN MATCHED 
    THEN DELETE 
    WHEN NOT MATCHED 
    THEN INSERT (
       UserId, 
       SectionId 
       ) 
     VALUES (
       source.UserId, 
       source.SectionId 
       ); 
END 
+0

2008看起來好多了,這是一種恥辱,我不能使用它...感謝您的重播,我會立即檢查它:) – Misiu

+0

我同意你和MERGE的權力;) –