SQL:如果不存在则更新,否则为DELETE

时间:2013-01-25 11:49:36

标签: sql sql-server sql-update not-exists sql-delete

我目前正在尝试编写一个脚本,将用户的角色更改为另一个,而不会在SQL Server数据库中创建重复项。

例如:

User_ID      Role_ID
---------------------
A            X
A            Z
B            Y
C            X
C            Y
D            Y

用户可能有多个角色。

我想更改它,以便角色Y中的所有用户现在都是角色X的成员,角色Y将不再存在:

User_ID      Role_ID
---------------------
A            X
A            Z
B            X
C            X
D            X

通过将所有Y角色更新为X,这可能会创建重复值;因此,我只需要更新新值是否已经存在,否则只需删除此值

4 个答案:

答案 0 :(得分:2)

试试这个(SQL DEMO

--Delete records with X if same user has Y 
delete t1
from userRoles t1 join (
    select * from userRoles t2 where t2.role_id = 'y') t3
    on t1.user_id = t3.user_Id
where t1.role_id = 'x'

--Update all Y records to X
update userRoles set role_id = 'X'
where role_id = 'y'

select * from userRoles
--RESULTS
USER_ID ROLE_ID
A         X
A         Z
B         X
C         X
D         X

答案 1 :(得分:2)

您可以在一个MERGE语句中执行此操作(它提供了优化锁定):

MERGE   tbl2
USING   (
                -- Create the desired data (together with duplicates)
        SELECT  User_ID, 
                CASE WHEN Role_ID = 'Y' THEN 'X' ELSE Role_ID END Role_ID
        FROM    tbl2
) new ON tbl2.User_ID = new.User_ID AND tbl2.Role_ID = new.Role_ID
WHEN NOT MATCHED THEN
                -- Insert the updated data
        INSERT(User_ID, Role_ID) VALUES(User_ID, Role_ID)
WHEN NOT MATCHED BY SOURCE THEN
                -- Filter out the 'X'-s
        DELETE;

这是 SQL Fiddle

答案 2 :(得分:1)

可以使用MERGE

完成此操作
DECLARE @T TABLE (User_ID CHAR(1), Role_ID CHAR(1));
INSERT @T (User_ID, Role_ID)
VALUES ('A', 'X'), ('A', 'Z'), ('B', 'Y'), ('C', 'X'), ('C', 'Y'), ('D', 'Y');

SELECT  *
FROM    @T;

WITH Y AS
(   SELECT  *,
            [d] = COUNT(*) OVER(PARTITION BY User_ID)
    FROM    @T
    WHERE   Role_ID IN ('Y', 'X')
), X AS 
(   SELECT  *
    FROM    @T
    WHERE   Role_ID = 'X'
)
MERGE INTO Y 
USING X ON X.User_ID = Y.User_ID
WHEN MATCHED AND Y.Role_ID = 'Y' AND d > 1 THEN DELETE
WHEN NOT MATCHED BY SOURCE THEN UPDATE
    SET Role_ID = 'X';

SELECT  *
FROM    @T;

答案 3 :(得分:0)

首先必须清理你的桌子:

DECLARE
  @originalRole char(1) = 'Y',
  @newRole char(1) = 'X'

DELETE [r1] 
FROM [Roles] [r1]
WHERE [r1].[Role_ID] = @originalRole
  AND EXISTS(SELECT *
             FROM [Roles] [r2]
             WHERE [r2].[User_ID] = [r1].[User_ID] AND [r2].[Role_ID] = @newRole)

然后,更新剩下的行,如果有的话:

UPDATE [Roles]
SET [Role_ID] = @newRole
WHERE [Role_ID] = @originalRole

这是the Fiddle