我拥有保存用户访问权限的表:
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'
因为UserId = 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 :(得分:0)
如果我这样做,我会保持简单:
好处是:
答案 1 :(得分:0)
在SQL Server 2005中
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
在SQL Server 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