I'm involved with managing an application with a large number of SQL Server 2014 databases and am extracting table and index sizes in order to track capacity. I'm using the following query:
select
db_name() as DBName,
object_schema_name(i.object_id) as SchemaName,
object_name(i.object_id) as TableName,
isnull(i.name,'(HEAP)') as IndexName,
ps.SizeInPages
from
sys.indexes i
inner join
(
select ps.object_id,ps.index_id,sum(ps.row_count) as IndexRows, sum(ps.used_page_count) as SizeInPages, count(*) as PartitionCount
from sys.dm_db_partition_stats ps
group by ps.object_id,ps.index_id
) ps on
ps.object_id = i.object_id and
ps.index_id = i.index_id
where
object_schema_name(i.object_id) not in ('cdc','sys')
Ideally I'd like to run this query from a SQL Login with the minimum required permissions, but so far it seems like the user needs VIEW SERVER STATE
and SELECT
permissions on all the tables. I've also tried putting the above query in a stored procedure and giving the user account EXECUTE
permissions on that, but sys.indexes
is still filtered based on what the user has select rights to.
Is there another way of doing this that I'm missing?
Best Answer
As far as i know, the minimal required permission set solution in this case is to create a store procedure thats executed within an impersonated context. Do this by:
see: (https://docs.microsoft.com/en-us/sql/t-sql/statements/execute-as-clause-transact-sql)
Then grant users execute on that stored procedure. This will allow the user to view that info w/o additional permissions (aside from EXECUTE on the SP).
to test:
By doing this, the stored procedure will execute with the permissions of either the designated user or (if set to OWNER) the creator/owner of the stored procedure, instead of the permissions of the user calling EXECUTE (this is default behavior, which is why sys.indexes is filtering by select permissions in your case).