Faaala pessoal!!
Nesse post eu gostaria de abordar um assunto muito comum no dia a dia do DBA, que é o schema padrão dos usuários no banco de dados, que pode ser ou não, diferente do padrão (dbo), conforme definição da TI.
O que é schema no SQL Server? Para que serve?
Clique aqui para visualizar o conteúdo desse tópicoComo identificar usuários com schema padrão igual a nome de usuário
No dia a dia do DBA, é comum encontrar ambientes onde o schema padrão de alguns usuários com autenticação Windows não foi definido na criação, sendo atribuindo assim, um novo schema igual ao nome desse usuário. Como resultado, usuários que não tem tanto conhecimento de banco de dados acabam criando vários objetos privados no ambiente (sem saber) e reclamando com o DBA que outros processos e usuários não enxergam as tabelas que eles criam.
Para te ajudar nessa missão, vou disponibilizar um script simples para identificar qual o schema de cada usuário e quem é o owner desses schemas.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						SELECT      A.[name] AS username,     A.type,     A.[default_schema_name] AS [default_schema],     C.[name] AS [schema_owner] FROM     sys.database_principals A     LEFT JOIN sys.schemas B ON A.default_schema_name = B.[name]     LEFT JOIN sys.database_principals C ON B.principal_id = C.principal_id WHERE     A.[type] IN ('U', 'S', 'G')     AND A.principal_id > 4 ORDER BY     1  | 
					
E agora, como identificar os usuários com schema padrão diferente do padrão (dbo):
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						SELECT      A.[name] AS username,     A.type,     A.[default_schema_name] AS [default_schema],     C.[name] AS [schema_owner],     'ALTER USER [' + A.[name] + '] WITH DEFAULT_SCHEMA=[dbo]' AS change_schema,     'ALTER USER [' + A.[name] + '] WITH DEFAULT_SCHEMA=[' + A.[default_schema_name] + ']' AS current_schema FROM     sys.database_principals A     LEFT JOIN sys.schemas B ON A.default_schema_name = B.[name]     LEFT JOIN sys.database_principals C ON B.principal_id = C.principal_id WHERE     A.[type] IN ('U', 'S', 'G')     AND A.principal_id > 4     AND (B.[schema_id] IS NULL OR B.[name] NOT IN ('dbo', 'guest')) ORDER BY     1  | 
					
Como identificar usuários que são donos de algum schema
Outra terefa bem comum, é identificar schemas que são propriedades de determinados usuários. Esse cenário impede a exclusão de usuários, com a mensagem de erro abaixo:
Msg 15138, Level 16, State 1, Line 41
The database principal owns a schema in the database, and cannot be dropped.
Para conseguir excluir esse usuário, você terá que, antes disso, excluir os schemas onde ele é o owner ou migrar a propriedade destes schemas para outro usuário. O script abaixo vai te ajudar a identificar quais são esses schemas:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13  | 
						SELECT      B.[name] AS [schema],     A.[name] AS [schema_owner],     'DROP SCHEMA [' + B.[name] + '];' AS drop_schema,     'CREATE SCHEMA [' + B.[name] + ']; ALTER AUTHORIZATION ON SCHEMA::[' + B.[name] + '] TO [' + A.[name] + '];' AS create_schema FROM     sys.database_principals A     JOIN sys.schemas B ON A.principal_id = B.principal_id WHERE     A.[type] IN ('U', 'S', 'G')     AND A.principal_id > 4 ORDER BY     2  | 
					
Como alterar o schema padrão em todos os databases
Para aplicar o script anterior em todos os databases, vamos recorrer à conhecida sp_MSforeachdb:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39  | 
						IF (OBJECT_ID('tempdb..#Dados') IS NOT NULL) DROP TABLE #Dados CREATE TABLE #Dados (     [database] NVARCHAR(128),     [username] NVARCHAR(128),     [type] CHAR(1),     [default_schema] NVARCHAR(128),     [schema_owner] NVARCHAR(128),     [change_schema] NVARCHAR(MAX),     [current_schema] NVARCHAR(MAX) ) INSERT INTO #Dados EXEC master.dbo.sp_MSforeachdb ' IF (''?'' NOT IN (''master'', ''msdb'', ''model'', ''tempdb'')) BEGIN     SELECT          ''?'' AS [database],         A.[name] AS username,         A.type,         A.[default_schema_name] AS [default_schema],         C.[name] AS [schema_owner],         ''USE [?]; ALTER USER ['' + A.[name] + ''] WITH DEFAULT_SCHEMA=[dbo]'' AS change_schema,         ''USE [?]; ALTER USER ['' + A.[name] + ''] WITH DEFAULT_SCHEMA=['' + A.[default_schema_name] + '']'' AS current_schema     FROM         [?].sys.database_principals A         LEFT JOIN [?].sys.schemas B ON A.default_schema_name = B.[name]         LEFT JOIN [?].sys.database_principals C ON B.principal_id = C.principal_id     WHERE         A.[type] IN (''U'', ''S'', ''G'')         AND A.principal_id > 4         AND (B.[schema_id] IS NULL OR B.[name] NOT IN (''dbo'', ''guest'')) END' SELECT * FROM #Dados  | 
					
Como identificar objetos criados em schemas diferentes do padrão
Outra tarefa comum no dia a dia do DBA é identificar objetos que foram criados em schemas de usuários e movê-los para o schema dbo (ou outro qualquer), quando necessário. Para isso, vou disponibilizar o script abaixo:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | 
						SELECT     A.[name] AS [object],     A.[type_desc],     A.create_date,     A.modify_date,     A.[default_schema_name] AS [schema_name],     C.[type_desc] AS [user_type],     'ALTER SCHEMA [dbo] TRANSFER [' + B.[name] + '].[' + A.[name] + '];' AS [to_default_schema] FROM     sys.objects A     JOIN sys.schemas B ON B.[schema_id] = A.[schema_id]     JOIN sys.database_principals C ON B.[name] = C.[name] WHERE     C.[type] IN (''U'', ''S'', ''G'')     AND C.principal_id > 4     AND C.is_fixed_role = 0 ORDER BY     1  | 
					
E se eu quiser mover os objetos de um schema para outro ?
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						DECLARE     @schema_origem VARCHAR(128) = 'dirceu.resende',     @schema_destino VARCHAR(128) = 'clientes' SELECT      A.[name] AS [object],     A.[type_desc],     A.create_date,     A.modify_date,     B.[name] AS [schema_name],     C.[type_desc] AS [user_type],     'ALTER SCHEMA [' + @schema_destino + '] TRANSFER [' + B.[name] + '].[' + A.[name] + '];' AS [to_default_schema] FROM     sys.objects A     JOIN sys.schemas B ON B.[schema_id] = A.[schema_id]     JOIN sys.database_principals C ON B.[name] = C.[name] WHERE     B.[name] = @schema_origem ORDER BY     1  | 
					
Stored Procedure para unificar schema padrão e objetos
Caso você esteja buscando uma solução bem prática para redefinir o schema padrão de todos os usuários para o padrão (dbo) e mover todos os objetos privados para o schema dbo também, utilize a Stored Procedure abaixo:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142  | 
						IF (OBJECT_ID('dbo.stpRedefine_Schema_Padrao') IS NULL) EXEC('CREATE PROCEDURE dbo.stpRedefine_Schema_Padrao AS SELECT 1') GO ALTER PROCEDURE dbo.stpRedefine_Schema_Padrao (     @Fl_Altera_Usuarios BIT = 1,     @Fl_Altera_Objetos BIT = 1,     @Fl_Debug BIT = 0 ) AS BEGIN     SET NOCOUNT ON     DECLARE @Comando VARCHAR(MAX)     IF (@Fl_Altera_Usuarios = 1)     BEGIN         IF (OBJECT_ID('tempdb..#Usuarios') IS NOT NULL) DROP TABLE #Usuarios         CREATE TABLE #Usuarios         (             [database] NVARCHAR(128),             [username] NVARCHAR(128),             [type] CHAR(1),             [default_schema] NVARCHAR(128),             [schema_owner] NVARCHAR(128),             [change_schema] NVARCHAR(MAX),             [current_schema] NVARCHAR(MAX)         )         INSERT INTO #Usuarios         EXEC master.dbo.sp_MSforeachdb '         IF (''?'' NOT IN (''master'', ''msdb'', ''model'', ''tempdb''))         BEGIN             SELECT                  ''?'' AS [database],                 A.[name] AS username,                 A.type,                 A.[default_schema_name] AS [default_schema],                 C.[name] AS [schema_owner],                 ''USE [?]; ALTER USER ['' + A.[name] + ''] WITH DEFAULT_SCHEMA=[dbo];'' AS change_schema,                 ''USE [?]; ALTER USER ['' + A.[name] + ''] WITH DEFAULT_SCHEMA=['' + A.[default_schema_name] + ''];'' AS current_schema             FROM                 [?].sys.database_principals A                 LEFT JOIN [?].sys.schemas B ON A.default_schema_name = B.[name]                 LEFT JOIN [?].sys.database_principals C ON B.principal_id = C.principal_id             WHERE                 A.[type] IN (''U'', ''S'', ''G'')                 AND A.principal_id > 4                 AND (B.[schema_id] IS NULL OR B.[name] NOT IN (''dbo'', ''guest''))         END'         SET @Comando = ''         SELECT @Comando += change_schema + CHAR(10)         FROM #Usuarios         ORDER BY [database], username         IF (@Fl_Debug = 1)         BEGIN             PRINT '------------------- Alterando o schema padrão dos usuários -------------------'             PRINT ''             PRINT @Comando         END         ELSE             EXEC(@Comando)     END     IF (@Fl_Altera_Objetos = 1)     BEGIN         IF (OBJECT_ID('tempdb..#Objetos') IS NOT NULL) DROP TABLE #Objetos         CREATE TABLE #Objetos         (             [database] NVARCHAR(128),             [object] NVARCHAR(128),             [type] VARCHAR(30),             [schema_name] NVARCHAR(128),             [schema_owner] NVARCHAR(128),             [change_schema] NVARCHAR(MAX)         )         INSERT INTO #Objetos         EXEC master.sys.sp_MSforeachdb '         IF (''?'' NOT IN (''master'', ''msdb'', ''model'', ''tempdb''))         BEGIN             SELECT                  ''?'' AS [database],                 A.[name] AS [object],                 A.[type_desc],                 A.[default_schema_name] AS [schema_name],                 C.[type_desc] AS [user_type],                 ''USE [?]; ALTER SCHEMA [dbo] TRANSFER ['' + B.[name] + ''].['' + A.[name] + ''];'' AS [to_default_schema]             FROM                 [?].sys.objects A                 JOIN [?].sys.schemas B ON B.[schema_id] = A.[schema_id]                 JOIN [?].sys.database_principals C ON B.[name] = C.[name]             WHERE                 C.[type] IN (''U'', ''S'', ''G'')                 AND C.principal_id > 4                 AND C.is_fixed_role = 0         END'         SET @Comando = ''         SELECT @Comando += change_schema + CHAR(10)         FROM #Objetos         ORDER BY [database], [object]         IF (@Fl_Debug = 1)         BEGIN             PRINT '------------------- Alterando o schema padrão dos objetos -------------------'             PRINT ''             PRINT @Comando         END         ELSE             EXEC(@Comando)     END END  | 
					
Exemplo de uso:
| 
					 1 2 3 4  | 
						EXEC dbo.stpRedefine_Schema_Padrao     @Fl_Altera_Usuarios = 1, -- bit     @Fl_Altera_Objetos = 1, -- bit     @Fl_Debug = 1 -- bit  | 
					
References
– https://pt.stackoverflow.com/questions/21031/o-que-s%C3%A3o-schemas-quais-as-vantagens-de-us%C3%A1-lo
– https://www.devmedia.com.br/schemas-no-sql-server/24328
– http://www.informit.com/articles/article.aspx?p=1216889&seqNum=2
– https://blog.sqlauthority.com/2009/09/07/sql-server-importance-of-database-schemas-in-sql-server/
– https://www.quackit.com/sql_server/sql_server_2008/tutorial/sql_server_database_schemas.cfm













																								
																								
Obrigado Dirceu por explicar detalhes de schemas no SQLServer! Show!