Faaala chicos!!
En este post me gustaría abordar un tema muy común en el día a día de un DBA, que es el esquema predeterminado de los usuarios en la base de datos, que puede o no ser diferente del predeterminado (dbo), tal como lo define TI.
¿Qué es el esquema en SQL Server? ¿Para qué es?
Haga clic aquí para ver el contenido de este tema.Cómo identificar usuarios con un esquema predeterminado igual al nombre de usuario
En el día a día de un DBA, es común encontrar entornos donde el esquema predeterminado de algunos usuarios con autenticación de Windows no estaba definido en el momento de su creación, asignando así un nuevo esquema igual al nombre de ese usuario. Como resultado, los usuarios que no tienen mucho conocimiento de bases de datos terminan creando varios objetos privados en el entorno (sin saberlo) y quejándose ante el DBA de que otros procesos y usuarios no ven las tablas que crean.
Para ayudarlo con esta misión, le proporcionaré un script simple para identificar qué esquema tiene cada usuario y quién es el propietario de estos esquemas.
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
Y ahora, cómo identificar usuarios con un esquema predeterminado distinto al predeterminado (dbo):
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
Cómo identificar a los usuarios que poseen un esquema
Otra tarea muy común es identificar esquemas que son propiedades de determinados usuarios. Este escenario evita que los usuarios sean eliminados, con el siguiente mensaje de error:
Mensaje 15138, Nivel 16, Estado 1, Línea 41
La base de datos principal posee un esquema en la base de datos y no se puede eliminar.
Para poder eliminar este usuario, primero deberá eliminar los esquemas de los que es propietario o migrar la propiedad de estos esquemas a otro usuario. El siguiente script le ayudará a identificar cuáles son estos esquemas:
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
Cómo cambiar el esquema predeterminado en todas las bases de datos
Para aplicar el script anterior a todas las bases de datos, usemos el conocido sp_MSforeachdb:
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
Cómo identificar objetos creados en esquemas distintos al predeterminado
Otra tarea común en la rutina diaria de un DBA es identificar objetos que se crearon en esquemas de usuario y moverlos al esquema dbo (o cualquier otro esquema), cuando sea necesario. Para hacer esto, proporcionaré el siguiente script:
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
¿Qué pasa si quiero mover objetos de un esquema a otro?
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
Procedimiento almacenado para unificar esquemas y objetos estándar
Si está buscando una solución muy práctica para restablecer el esquema predeterminado de todos los usuarios al predeterminado (dbo) y mover también todos los objetos privados al esquema dbo, utilice el procedimiento almacenado a continuación:
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
Ejemplo de uso:
EXEC dbo.stpRedefine_Schema_Padrao
@Fl_Altera_Usuarios = 1, -- bit
@Fl_Altera_Objetos = 1, -- bit
@Fl_Debug = 1 -- bit
Referencias
– 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












Comentários (0)
Carregando comentários…