从存储过程调用sp_spaceused

时间:2011-06-23 17:23:02

标签: sql sql-server-2008 stored-procedures

在SQL Server 2008中,我正在尝试快速获取表的行计数,以便在存储过程中进行诊断。在存储过程中,我使用以下SQL来获取计数而不进行表扫描:

--Get row count using sp_spaceused
DECLARE @rowCount AS INT
DECLARE @spaceUsed TABLE(
    [Name] varchar(64), 
    [Rows] INT,
    [Reserved] VARCHAR(50),
    [Data] VARCHAR(50),
    [Index_Size] VARCHAR(50),
    [Unused] VARCHAR(50)
)
INSERT INTO @spaceUsed EXEC sp_spaceused 'MyTable'
SET @rowCount = (SELECT TOP 1 [Rows] FROM @spaceUsed)

当我使用Administrator帐户从SQL Management Studio执行存储过程时,此SQL工作正常。但是,当我尝试从代码执行存储过程时(使用不同的登录名)sp_spaceused失败,并显示消息“数据库'MyDatabase'中不存在对象'MyTable',或者此操作无效。”

有没有办法让这个非管理员登录?在管理工作室和代码中运行程序时,我还缺少其他的东西吗?

4 个答案:

答案 0 :(得分:4)

您是否尝试使用对象前缀(例如EXEC sp_spaceused'dbo.MyTable')?如果用户无权访问对象的架构或具有与dbo不同的默认架构,则会发生这种情况。

您是否尝试使用EXECUTE AS创建程序?

顺便说一下,为什么不一遍又一遍地调用这个存储过程,为什么不从sys.dm_db_partition_stats中提取数据,其中index_id为IN(0,1)?这有你想要的页面计数(这使得很容易得到相同的信息)并且不需要执行过程的所有脚手架将数据转储到#temp表中。

答案 1 :(得分:1)

当您在SSMS外部运行时,您确定自己位于正确的数据库中吗?

虽然the docs说“执行sp_spaceused的权限被授予公共角色。”,这似乎与你所看到的相矛盾。

一种选择是将其放入存储过程并使用EXECUTE AS功能让它以管理员身份执行。

答案 2 :(得分:1)

您需要确保调用用户对您正在检查的表具有权限。读取权限应该足以满足您的需求,但我还没有对其进行测试。

正如其他人所说,如果表中的数据具有安全性,并且您不希望用户拥有对它的读取权限,您也可以使用EXECUTE AS

答案 3 :(得分:1)

有更简单的方法。

鉴于sp_spaceused内部调用sys.dm_db_partition_stats,您可以运行:

SELECT
   @rowCount = SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
   object_name(object_id) = 'Mytable' AND (index_id < 2)

您可以使用udf隐藏权限

CREATE FUNCTION dbo.GetCounts (@tablename varchar(100))
RETURNS bigint
WITH EXECUTE AS OWNER
AS
BEGIN
    RETURN (
    SELECT
       SUM(st.row_count)
    FROM
       sys.dm_db_partition_stats st
    WHERE
       object_name(object_id) = @tablename AND (index_id < 2)
    )
END
GO

我在这里的回答更多:Fastest way to count exact number of rows in a very large table?