2012-06-15 31 views
1

我有一個應用程序允許用戶上傳大數據文件,然後解析並將數據存儲在SQL Server 2008 R2數據庫中。當調用用戶沒有ALTER TABLE時,從存儲過程調用UPDATE STATISTICS

我想在導入數據的表上自動運行UPDATE STATISTICS,因爲用戶可以運行關於數據的報告並且數據量非常大。

數據訪問是通過存儲過程完成的,並且用戶對錶沒有權限,只能在存儲過程上執行。

我寫了一個存儲過程來獲取表名,並使用sp_Executesql在傳入的表名上運行UPDATE STATISTICS。存儲過程和表均由dbo擁有。我收到一個錯誤,說'找不到對象'表「,因爲它不存在或者您沒有權限。'如果我向用戶授予對錶的更改,那麼它可以正常工作,但我想避免這樣做。我認爲如果表和存儲過程屬於同一個擁有者,那麼用戶的權限將被忽略。

是否有可能在沒有alter table權限的情況下以某種方式運行UPDATE STATISTICS?

+0

這聽起來像個壞主意。爲什麼不讓數據庫更新統計信息。通常情況下,如果你做大數據更新。 – JohnFx

回答

6

如果您使用sp_executesql,則不能忽略用戶的權限。除非你讓程序在其他人的環境中執行。而不是選擇另一個用戶,我寧願創建一個沒有登錄的用戶。因此,讓我們假設你有一個名爲dbo.farb表中,用戶foobarblat不能ALTERDENY是沒有必要的,但它確實證明了這一點):

USE master; 
GO 
CREATE LOGIN foobarblat WITH PASSWORD = 'foobarblat', CHECK_POLICY = OFF; 
GO 
USE YourDatabase; 
GO 
CREATE USER foobarblat FROM LOGIN foobarblat; 
GO 
CREATE TABLE dbo.farb(id INT); 
GO 
DENY ALTER ON dbo.farb to foobarblat; 
GO 

現在讓我們創建一個隱藏的用戶 - 我們可以給該用戶的所有在世界上的權限,因爲沒有人可以真正身份登錄該用戶,但在這個例子中,我們可以只授予ALTER我們的餐桌上):

CREATE USER SuperSecret WITHOUT LOGIN; 
GO 
GRANT ALTER ON dbo.farb TO SuperSecret; 
GO 

現在我們可以寫在上下文中執行存儲過程我們SuperSecret用戶,但可以由0執行:

CREATE PROCEDURE dbo.UpdateStats 
    @tablename NVARCHAR(511) 
WITH EXECUTE AS 'SuperSecret' 
AS 
BEGIN 
    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N'UPDATE STATISTICS ' + @tablename; 
    EXEC sp_executesql @sql; 
END 
GO 
GRANT EXEC ON dbo.UpdateStats TO foobarblat; 

使用foobarblat在新窗口中現在連接 - 你應該能夠執行這個沒有問題:

EXEC dbo.UpdateStats 'dbo.farb'; 
5

除了什麼阿龍貝特朗說,我會添加另一種解決方案混合:模塊簽名。所需的步驟(簡單地說):

  • 創建證書
  • 將其導入到SQL Server的
  • 從證書
  • 創建登錄從登錄創建用戶
  • 授予權限用戶(在這種情況下,更改表)
  • 使用證書對存儲過程進行簽名
  • 將存儲過程的exec權限授予whome r需要運行它

我看到的好處是當程序運行時,你會看到誰在實際運行它。缺點是對存儲過程的任何更改都需要您重新簽名(即簽名不會在更改中持續存在)以及一些初始設置。亞倫的方法具有相反的優點。

+0

+1不錯的選擇 –