2013-01-25 42 views
4

我目前正試圖編寫一個腳本,將用戶的角色更改爲另一個,而不會在SQL Server數據庫中創建重複項。SQL:更新如果不存在,否則刪除

例如:

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

用戶可以有多個角色。

我想改變它,這樣的角色Ÿ所有用戶現在的角色X的成員,角色ÿ將不復存在這樣:

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

通過更新所有的Y角色X,這可能會創建重複的值;因此,我需要的,如果新值不存在只更新,否則只是刪除此值

+0

爲什麼不只是執行更新並在之後擺脫重複?如果這不是一個選項:您使用哪種RDBMS? –

+0

你在這個表中有主鍵嗎? – Ankit

+0

這兩列都是外鍵。 – Viprus

回答

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 
+0

MERGE語句是否不處理?甚至是相關的子查詢? –

+0

@ ta.speot.is:這是一次性查詢並完成工作。我不確定關於合併或子查詢。你有一個例子嗎? – Kaf

+1

易於理解並做好工作。謝謝! – Viprus

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

+0

您缺少預期結果中的A - X。 – Kaf

+0

已更新的答案,試着做X> Y代替Y> X – Jacco

+0

小提琴也更新了。 – Jacco

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

+0

MERGE最後需要';'。 –

+0

它有一個它編譯,SQL小提琴即將推出... –

+0

啊我沒有看到嵌入的一個;)(你並不需要那個在開始雖然)。 –

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; 
相關問題