Skip to content

Delete Person Records

Source: David Turner [9 Embers]

Delete person records in bulk. Handles cleaning up date from all of the related tables.

This is primarily used to cleanup after a bot attack.

[!Danger] This will permanently delete data from Rock. Do not run this unless you are 100% confident that the SELECT statement is correct and you have made a backup.

Query

SET NOCOUNT ON
GO

-- Modify Query below to select people that should be deleted from databse.
CREATE TABLE #PersonTbl ( [Id] int, PRIMARY KEY ([Id]) )
INSERT INTO #PersonTbl
SELECT [Id]
FROM [Person]
WHERE [FirstName] LIKE '%Get BitCoin%'

-- Create Temp Person Alias Id Table
CREATE TABLE #PersonAliasTbl ( [Id] int, PRIMARY KEY ([Id]) )
INSERT INTO #PersonAliasTbl
SELECT [Id]
FROM [PersonAlias]
WHERE
    [AliasPersonId] IN ( SELECT [Id] FROM #PersonTbl )
    OR [PersonId] IN ( SELECT [Id] FROM #PersonTbl )

DECLARE @Msg varchar(200)
DECLARE @Rows int = 1
DECLARE @DeletedRows int = 0
DECLARE @PersonEntityTypeId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Name] = 'Rock.Model.Person' )

-- Delete Person Viewed Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) V
    FROM
        #PersonAliasTbl PA
        INNER JOIN [PersonViewed] V ON
            V.[TargetPersonAliasId] = PA.[Id]
            OR V.[ViewerPersonAliasId] = PA.[Id]

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Viewed records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Registrant Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) R
    FROM
        #PersonAliasTbl PA
        INNER JOIN [RegistrationRegistrant] R ON R.[PersonAliasId] = PA.[Id]

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Registrant records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Registration Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) R
    FROM
        #PersonAliasTbl PA
        INNER JOIN [Registration] R ON R.[PersonAliasId] = PA.[Id]

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Registration records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Interaction Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) I
    FROM
        #PersonAliasTbl PA
        INNER JOIN [Interaction] I ON I.[PersonAliasId] = PA.[Id] 

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Interaction records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person Search Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) S
    FROM
        #PersonAliasTbl PA
        INNER JOIN [PersonSearchKey] S ON S.[PersonAliasId] = PA.[Id] 

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Search Key records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person Duplicate Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) PD
    FROM
        #PersonAliasTbl PA
        INNER JOIN [PersonDuplicate] PD ON
            PD.[PersonAliasId] = PA.[Id]
            OR PD.[DuplicatePersonAliasId] = PA.[Id]

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Duplicate records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Audit Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) A
    FROM
        #PersonAliasTbl PA
        INNER JOIN [Audit] A ON A.[PersonAliasId] = PA.[Id] 

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Audit records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Personal Device Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) D
    FROM
        #PersonAliasTbl PA
        INNER JOIN [PersonalDevice] D ON D.[PersonAliasId] = PA.[Id] 

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Personal Device records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Communication Recipient Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) R
    FROM
        #PersonAliasTbl PA
        INNER JOIN [CommunicationRecipient] R ON R.[PersonAliasId] = PA.[Id] 

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Communication Recipient records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Update all ModifedByPersonAliasId and CreatedByPersonAliasId Field to NULL
RAISERROR( 'Updating all CreatedByPersonAliasId and ModifiedByPersonAliasId fileds to NULL', 0, 0 ) WITH NOWAIT
DECLARE @Sql varchar(max)
DECLARE ForeignKeyCursor INSENSITIVE CURSOR FOR
SELECT CONCAT (
    'UPDATE T',
    'SET [', tac.name, '] = NULL ',
    'FROM',
        ' [', tso.name, '] T ',
        'INNER JOIN #PersonAliasTbl PA ON PA.[Id] = T.[', tac.name, '] '
)
FROM sys.foreign_key_columns kc
    INNER JOIN sys.foreign_keys k ON kc.constraint_object_id = k.object_id
    INNER JOIN sys.all_objects so ON so.object_id = kc.referenced_object_id
    INNER JOIN sys.all_columns rac ON
        rac.column_id = kc.referenced_column_id
        AND rac.object_id = so.object_id
    INNER JOIN sys.all_objects tso ON tso.object_id = kc.parent_object_id
    INNER JOIN sys.all_columns tac ON
        tac.column_id = kc.parent_column_id
        AND tac.object_id = tso.object_id
WHERE so.name = 'PersonAlias'
    AND rac.name = 'Id'
    AND tac.name IN ( 'ModifiedByPersonAliasId', 'CreatedByPersonAliasId' )
OPEN ForeignKeyCursor

FETCH NEXT FROM ForeignKeyCursor INTO @Sql
WHILE (@@FETCH_STATUS <> -1)
BEGIN
    IF (@@FETCH_STATUS = 0)
    BEGIN
        EXEC(@Sql)
    END
    FETCH NEXT FROM ForeignKeyCursor INTO @Sql
END

CLOSE ForeignKeyCursor
DEALLOCATE ForeignKeyCursor

-- Delete Person Alias Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [PersonAlias]
    WHERE [Id] IN ( SELECT [Id] FROM #PersonAliasTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Alias records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

DROP TABLE #PersonAliasTbl

-- Delete Login Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [UserLogin]
    WHERE [PersonId] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' User Login records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Save the groups that these people are members of
CREATE TABLE #GroupTbl ( [Id] int, PRIMARY KEY ([Id]) )
INSERT INTO #GroupTbl
SELECT DISTINCT [GroupId]
FROM [GroupMember]
WHERE [PersonId] IN ( SELECT [Id] FROM #PersonTbl )

-- Delete Group Member Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [GroupMember]
    WHERE [PersonId] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Group Member records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [Person]
    WHERE [Id] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person History Records
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [History]
    WHERE [EntityTypeId] = @PersonEntityTypeId
    AND [EntityId] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person History records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person Attribute Values
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) V
    FROM
        [Attribute] A
        INNER JOIN [AttributeValue] V ON V.[AttributeId] = A.[Id]
    WHERE
        A.[EntityTypeId] = @PersonEntityTypeId
        AND V.[EntityId] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Attribute Value records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Person Notes
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000) N
    FROM
        [NoteType] T
        INNER JOIN [Note] N ON N.[NoteTypeId] = T.[Id]
    WHERE
        T.[EntityTypeId] = @PersonEntityTypeId
        AND N.[EntityId] IN ( SELECT [Id] FROM #PersonTbl )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Person Note records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

-- Delete Groups that people were in that no longer have any group members
SELECT @Rows = 1, @DeletedRows = 0
WHILE ( @Rows > 0 )
BEGIN
    DELETE TOP (10000)
    FROM [Group]
    WHERE
        [Id] IN ( SELECT [Id] FROM #GroupTbl )
        AND [Id] NOT IN ( SELECT [GroupId] FROM [GroupMember] )

    SET @Rows = @@ROWCOUNT
    SET @DeletedRows = @DeletedRows + @Rows
    SET @Msg = CONCAT( FORMAT( @DeletedRows, 'N0'), ' Group records deleted' )
    IF @Rows > 0 RAISERROR( @Msg, 0, 0 ) WITH NOWAIT
END

DROP TABLE #GroupTbl
DROP TABLE #PersonTbl

SET NOCOUNT OFF
GO