Olá pessoal,
Boa tarde!
Neste post vou demonstrar como resolver um problema comum no desenvolvimento de bibliotecas CLR que ocorre quando você faz o restore de um database CLR vindo de outro servidor. Apesar da solução sem bem simples, quando se depara com esse problema pela primeira vez, você pode demorar um pouco para resolver.
Identificando o problema e entendendo porque isso acontece
Após você realizar o restore do database CLR no servidor de destino, ao tentar executar qualquer procedure ou function, ocorre a seguinte mensagem de erro:
The database owner SID recorded in the master database differs from the database owner SID recorded in database ‘CLR’. You should correct this situation by resetting the owner of database ‘CLR’ using the ALTER AUTHORIZATION statement.
Esse erro pode ocorrer quando o SID do owner desse database restaurado não está presente na lista de owners do database master da sua instância.
A solução é bem simples e basta redefinir o owner do database restaurado (pode alterar para um outro owner e voltar pro owner de mesmo nome que existe na instância). Isso pode ser feito pela interface do SQL Server Management Studio, utilizando a sp master.dbo.sp_chagedbowner ou com o comando ALTER AUTHORIZATION.
Alterando o owner pela interface do SQL Server Management Studio
Para alterar o owner do database, basta clicar com o botão direito sobre o database na tela “Object Explorer” e selecionar a opção “Properties”. Após isso, selecione o menu “Files” e então você poderá alterar o owner do banco e confirmar.
Alterando o owner com o sp_changedbowner
Uma forma de alterar o owner utilizando T-SQL é utilizando a procedure sp_changedbowner, disponÃvel da versão 2008 até a 2014 e está marcada como descontinuada em futuras versões do SQL Server.
Exemplo:
1 2 3 4 5 6 7 8 |
USE [CLR] GO ALTER DATABASE [CLR] SET TRUSTWORTHY ON GO EXEC dbo.sp_changedbowner 'usuario' GO |
Restaurando o SID do database de forma automática:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
USE [CLR] GO DECLARE @Comando VARCHAR(MAX) SELECT @Comando = 'EXEC dbo.sp_changedbowner ' + QUOTENAME(B.name) FROM sys.databases A JOIN sys.server_principals B ON B.sid = A.owner_sid WHERE A.name = DB_NAME() PRINT @Comando EXEC(@Comando) |
Alterando o owner com o ALTER AUTHORIZATION
Uma outra forma de alterar o owner de um database no SQL Server via T-SQL é utilizando o comando ALTER AUTHORIZATION no database de destino, conforme exemplo abaixo.
A vantagem dessa solução para a utilizando a sp_changedbowner é que o comando ALTER AUTHORIZATION está disponÃvel desde a versão 2008 (assim como a SP), mas não está marcada como descontinuada, ou seja, estará disponÃvel em futuras versões do SQL Server.
Exemplo:
1 2 3 4 5 6 7 8 |
USE [CLR] GO ALTER DATABASE [CLR] SET TRUSTWORTHY ON GO ALTER AUTHORIZATION ON DATABASE::[CLR] TO [usuario] GO |
Restaurando o SID do database de forma automática:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
USE [CLR] GO DECLARE @Comando VARCHAR(MAX) = 'ALTER AUTHORIZATION ON DATABASE::<<DatabaseName>> TO <<LoginName>>', @Usuario VARCHAR(MAX) = ( SELECT TOP 1 name FROM sys.server_principals WHERE type_desc = 'SQL_LOGIN' AND is_disabled = 'false' ORDER BY principal_id ASC) SELECT @Comando = REPLACE(REPLACE(@Comando, '<<DatabaseName>>', QUOTENAME(A.name)), '<<LoginName>>', QUOTENAME(COALESCE(B.name, @Usuario))) FROM sys.databases A LEFT JOIN sys.server_principals B ON B.sid = A.owner_sid WHERE A.name = DB_NAME() PRINT @Comando EXEC(@Comando) |
É isso aÃ, pessoal. Após adotar uma das soluções listadas acima, suas rotinas e funções no database CLR restaurado já estão funcionando corretamente.
Qualquer dúvida, é só deixar nos comentários.
Abraço!