2011-09-06 46 views
1

我有AA過程,從我的數據庫中刪除用戶:調用列中每個值的過程?

CREATE PROCEDURE [dbo].[sp_removeUser] 
    @UserId  uniqueidentifier  
    ,@result  int OUT 
AS 
BEGIN 
SET NOCOUNT ON  
    SET @Result=0 

    -- whether User exists 
    IF NOT EXISTS(SELECT 1 FROM [dbo].[Users] (nolock) WHERE UserId = @UserId) 
     RETURN 

    -- Prevent to remove admin 
    IF EXISTS(SELECT 1 FROM [dbo].[aspnet_Users] (nolock) WHERE UserId= @UserId AND UserName = 'admin') 
     RETURN 


    BEGIN TRAN 

    -- Remove User Addresses 
    DELETE FROM [dbo].[AddressesUserAccess] WHERE AddressId IN (SELECT AddressId FROM Addresses WHERE UserId = @UserId) 
    DELETE FROM [dbo].[AddressesInGroups] WHERE AddressId IN (SELECT AddressId FROM Addresses WHERE UserId = @UserId) 
    DELETE FROM [dbo].[Addresses] WHERE UserId = @UserId 

    -- Remove User Numbers 
    DELETE FROM [dbo].[NumbersUserAccess] WHERE NumberId IN (SELECT NumberId FROM Numbers WHERE UserId = @UserId) 
    DELETE FROM [dbo].[NumbersInGroups] WHERE NumberId IN (SELECT NumberId FROM Numbers WHERE UserId = @UserId) 
    DELETE FROM [dbo].[Numbers] WHERE UserId = @UserId 

... 
... and lots more below... 
... 

我要刪除一大堆的用戶,所以我首先想到的是讓所有我想刪除的用戶ID的一列,然後迭代,依次刪除每個用戶。

然而,在閱讀了一些關於SO的其他問題後,我知道這不是最好的方式,而應該尋找更多基於集合的解決方案。

那麼什麼是更好的方式來實現這個過程以更基於集合的方式工作?

+1

什麼版本的SQL Server?如果2008年你可以在TVP中傳遞一個用戶名單。 –

+0

我的開發機器是2008年,但我們的現場服務器是2005年,這是一種惱人的。 – Oliver

+0

[2005年在這裏還有其他一些傳遞值的方法](http://www.sommarskog.se/arrays-in-sql-2005.html) –

回答

1

您可以使用分割功能,例如

CREATE FUNCTION dbo.SplitGUIDs 
(
    @List  VARCHAR(MAX) 
) 
RETURNS TABLE 
AS 
    RETURN 
    (
     SELECT Item = CONVERT(UNIQUEIDENTIFIER, Item) 
     FROM 
     (
      SELECT Item = x.i.value('(./text())[1]', 'VARCHAR(36)') 
      FROM 
      (
       SELECT [XML] = CONVERT(XML, '<i>' 
        + REPLACE(@List, ',', '</i><i>') 
        + '</i>').query('.') 
      ) AS a 
      CROSS APPLY 
      [XML].nodes('i') AS x(i) 
     ) AS y 
     WHERE Item IS NOT NULL 
    ); 
GO 

那麼你的程序將只需要稍微改變(雖然我強烈建議反對以sp_前綴):

CREATE PROCEDURE dbo.RemoveUsers 
    @UserList VARCHAR(MAX) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @u TABLE(UserID UNIQUEIDENTIFIER PRIMARY KEY); 

    INSERT @u 
     SELECT DISTINCT i.Item 
     FROM dbo.SplitGUIDs(@UserList) AS i 
     INNER JOIN dbo.Users AS u 
     ON u.UserID = i.Item 
     WHERE NOT EXISTS 
     (
      SELECT 1 FROM dbo.aspnet_users 
      WHERE UserID = i.Item 
      AND Username = 'Admin' 
     ); 

    -- now all your delete statements can use IN instead of = 
    DELETE ... WHERE UserID IN (SELECT UserID FROM @u); 
END 
GO 

您可能需要從應用層構建的GUID的逗號分隔列表或其他地方,但你可以調用的程序是這樣的:

EXEC dbo.RemoveUsers 
@UserList = '89E31B4B-68B5-4B7B-B226-F51BE388F815,C947AE20-DEC1-4EBC-A838-CCCE033BD1FF' 

只要注意,它會彈,如果任何元素是不是有效的GUID。

+0

謝謝,這看起來很有用。我真的不知道sp_前綴是什麼,因爲我最近纔開始使用這個數據庫。所有的程序都使用它。 – Oliver

相關問題