遇到特定Error_Number时执行脚本/存储过程

问题描述 投票:0回答:1

我创建了一个存储过程 (

proc_dropUser
) 来循环遍历所有数据库并删除用户。

但是很多时候当用户拥有架构时我会遇到错误 15138。

因此,我创建了另一个过程(

proc_altAuthorization
)来更改数据库用户拥有的模式的授权。

我想做的是,每当我在执行

proc_dropUser
时遇到特定错误时,就执行
proc_altAuthorization
,然后返回到第一个程序并继续。

类似:

CREATE proc_dropUser
    @userName

    --Cursor to DROP USER from each @dbName
   IF ERROR_NUMBER() = 15138
       EXEC proc_altAuthorization @userName, @dbName

   FETCH NEXT FROM cursor INTO @user
GO

并且

proc_altAuthorization
将接受参数并更改授权。

CREATE proc_altAuthorization
    @userName, @dbName

--build dynamic sql query
SET @dsql = N'USE ' + @dbName + N'
ALTER AUTHORIZATION ON SCHEMA:: '+@schema + ' TO dbo'
EXEC(@dsql)
RETURN --not sure!

我想可以使用 TRY CATCH 块,但不知道如何使用。

sql-server stored-procedures error-handling
1个回答
0
投票

我已经有一段时间找到问题的解决方案了,但意识到我从未将其发布在这里。这是我找到的解决方案。它实现了我在问题中提到的 TRY-CATCH 相同逻辑,但不具备如何实现的技术知识。

CREATE PROCEDURE proc_dropUser
    @userName NVARCHAR(128)
AS
BEGIN
    DECLARE @dbName NVARCHAR(128)
    DECLARE @sql NVARCHAR(MAX)
    DECLARE @schema NVARCHAR(128)
    
    -- Declare a cursor for iterating through all databases
    DECLARE db_cursor CURSOR FOR
    SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb')
    
    OPEN db_cursor
    FETCH NEXT FROM db_cursor INTO @dbName
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        BEGIN TRY
            -- Build the dynamic SQL to drop the user from each database
            SET @sql = N'USE ' + QUOTENAME(@dbName) + N';
                        IF EXISTS (SELECT * FROM sys.database_principals WHERE name = @userName)
                        BEGIN
                            DROP USER ' + QUOTENAME(@userName) + N';
                        END'
            EXEC proc_executesql @sql, N'@userName NVARCHAR(128)', @userName
            
        END TRY
        BEGIN CATCH
            -- Check if the error is 15138 (user owns a schema)
            IF ERROR_NUMBER() = 15138
            BEGIN
                -- Execute proc_altAuthorization to alter the schema ownership
                EXEC proc_altAuthorization @userName, @dbName
                -- Retry dropping the user after the schema ownership is changed
                SET @sql = N'USE ' + QUOTENAME(@dbName) + N';
                            DROP USER ' + QUOTENAME(@userName) + N';'
                EXEC proc_executesql @sql
            END
        END CATCH
        
        -- Fetch the next database
        FETCH NEXT FROM db_cursor INTO @dbName
    END
    
    CLOSE db_cursor
    DEALLOCATE db_cursor
END

希望这可以帮助遇到类似需求的其他人。干杯!

© www.soinside.com 2019 - 2024. All rights reserved.