Obtener todos los permisos de un usuario SQL Server

Algunas veces (por temas de auditoría) es necesario saber cuáles son todos los permisos que se tienen dentro de una BD.

No he encontrado un script que me permita saber absolutamente todos los permisos que posee mi usuario (teniendo en cuenta que el permiso puede no estar asociado a mi directamente si no a mi rol), es por eso que elaboré éste script que cubre en parte ésta necesidad.

El script que se muestra a continuación obtiene todos los permisos que tiene nuestro Login a nivel de servidor y además todos los permisos que tiene el usuario relacionado a nuestro login en cada Base de Datos.

Indiqué que esto cubría la necesidad "en parte" debido a que un permiso puede ser asignado directamente hacia un objeto lo cual está fuera del alcance del presente Script.

De todas maneras trabajaré una versión un poco más completa que cubra totalmente lo que se busca.

El Script es el siguiente:

SELECT 'Login: ' + SYSTEM_USER AS Login_Usuario
 
SELECT permission_name AS 'Permisos a nivel de servidor:'
FROM fn_my_permissions(NULL, 'SERVER')
 
DECLARE @Texto AS NVARCHAR(MAX)
 
SET @Texto = '
USE [?]
IF((SELECT COUNT(1) FROM sys.database_principals WHERE name = CURRENT_USER)>0)
BEGIN
      BEGIN TRY
            SELECT permission_name AS ''Permisos a nivel de BD (?):''
            FROM fn_my_permissions(NULL, ''DATABASE'')
      END TRY
      BEGIN CATCH
            SELECT ''Ocurrió un error: '' + ERROR_MESSAGE() AS ''Permisos a nivel de BD (?):''
      END CATCH
END'
 
EXEC master.sys.sp_MSforeachdb @Texto

Consultas SQL más costosas

Algunas veces, sobre todo cuando tenemos entre manos un proceso de optimización, es necesario saber exactamente cuáles son las sentencias que tienen un costo o tiempo de ejecución mayor para poder enfocar nuestras fuerzas en ése punto.

Para suerte nuestra, en SQL se guarda un histórico de todas las veces que se ejecuta una sentencia, por lo que podemos consultar no sólo cuantas veces se ha ejecutado (en el caso de los procedimientos, la cantidad de veces se cuenta desde su última compilación) si no que podemos ver el tiempo y costo (de CPU) promedio de todas las ejecuciones, el tiempo y costo de la última ejecución entre otros datos más.

SELECT TOP 10
    DB_NAME(qt.dbid) 'Base de Datos',
    OBJECT_NAME(qt.objectid,qt.dbid)AS 'Nombre Objeto',
    SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
    WHEN -1 THEN DATALENGTH(qt.text)
    ELSE qs.statement_end_offset
    END - qs.statement_start_offset)/2)+1) AS 'Texto',
    qs.execution_count AS 'Veces ejecutado',
    qs.total_logical_reads AS 'Total lecturas lógicas',
    qs.last_logical_reads AS 'Lecturas lógicas del último proceso',
    qs.total_logical_writes AS 'Total escrituras lógicas',
    qs.last_logical_writes AS 'Escrituras lógicas del último proces',
    qs.total_worker_time AS 'Total tiempo CPU',
    qs.last_worker_time AS 'Tiempo CPU del último proceso',
    qs.min_worker_time AS 'Minimo tiempo CPU',
    qs.max_worker_time AS 'Maximo tiempo CPU',
    qs.total_elapsed_time/1000000 AS 'Total tiempo (en seg)',
    qs.last_elapsed_time/1000000 AS 'Tiempo del último proceso (en seg)',
    qs.min_elapsed_time/1000000 AS 'Tiempo mínimo (en seg)',
    qs.max_elapsed_time/1000000 AS 'Tiempo máximo (en seg)',
    qs.last_execution_time AS 'Ultima vez que se ejecutó',
    qp.query_plan AS 'Plan de ejecución'
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
--WHERE DB_NAME(qt.dbid) = 'NOMBRE_DE_BD'
ORDER BY qs.total_elapsed_time DESC

Siempre pueden listar más items (quitando el TOP 10), ordenar el resultado por otro factor (cambiando el ORDER BY) o restringiendo la búsqueda a una base de datos específica (descomentando la penúltima línea y cambiando NOMBRE_DE_BD por el nombre de su Base de Datos)