Вызов sp_spaceused из хранимой процедуры - PullRequest
0 голосов
/ 23 июня 2011

В 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)

Этот SQL работает нормально, когда я выполняю хранимую процедуру из SQL Management Studio, используя учетную запись администратора. Однако, когда я пытаюсь выполнить хранимую процедуру из кода (который использует другой логин), sp_spaceused завершается неудачно с сообщением «Объект« MyTable »не существует в базе данных« MyDatabase »или недопустим для этой операции».

Есть ли способ заставить это работать для входа без прав администратора? Есть ли что-то еще, что я пропускаю при запуске процедуры в Management Studio по сравнению с кодом?

Ответы [ 4 ]

4 голосов
/ 23 июня 2011

Вы пытались использовать префикс объекта (например, EXEC sp_spaceused 'dbo.MyTable')?Это может произойти, если пользователь не имеет доступа к схеме объекта или имеет схему по умолчанию, отличную от dbo.

Вы пытались создать процедуру с помощью EXECUTE AS ?

Вместо этого, вместо того, чтобы вызывать эту хранимую процедуру снова и снова, почему бы не извлечь данные из sys.dm_db_partition_stats, где index_id IN (0,1)?Это число страниц, которые вы ищете (что позволяет легко получить ту же информацию), и не требует всех процедур выполнения процедуры для выгрузки данных в таблицу #temp.

1 голос
/ 23 июня 2011

Есть более простые способы.

Учитывая, что 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

Подробнее в моем ответе здесь: Самый быстрый способ подсчета точного количества строк в очень большой таблице?

1 голос
/ 23 июня 2011

Вы должны убедиться, что у вызывающего пользователя есть разрешения на таблицу, которую вы проверяете.Разрешения на чтение должны быть достаточными для того, что вы делаете, но я не проверял это.

Как уже говорили другие, вы также можете использовать EXECUTE AS, если данные в таблице имеют безопасный характер иВы не хотите, чтобы пользователь даже имел доступ для чтения к нему.

1 голос
/ 23 июня 2011

Вы уверены, что находитесь в правильной базе данных, когда работаете вне SSMS?

Хотя в документах говорится "Разрешение на выполнение sp_spaceused предоставлено публичной роли.", Чтокажется, противоречит тому, что вы видите.

Один из вариантов - поместить его в хранимую процедуру и использовать функцию EXECUTE AS , чтобы запустить ее в качестве администратора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...