当调用用户没有 ALTER TABLE 时从存储过程调用 UPDATE STATISTICS

Posted

技术标签:

【中文标题】当调用用户没有 ALTER TABLE 时从存储过程调用 UPDATE STATISTICS【英文标题】:Calling UPDATE STATISTICS from a stored procedure when the calling user doesn't have ALTER TABLE 【发布时间】:2012-06-18 01:48:46 【问题描述】:

我有一个应用程序,它允许用户上传大型数据文件,然后解析数据并将其存储在 SQL Server 2008 R2 数据库中。

我想在导入数据的表上自动运行 UPDATE STATISTICS,因为用户可以对数据运行报告并且数据量非常大。

数据访问是通过存储过程完成的,用户对表没有权限,只能对存储过程执行。

我编写了一个存储过程来获取表名并使用 sp_Executesql 对传入的表名运行 UPDATE STATISTICS。存储过程和表都归 dbo 所有。我收到一条错误消息,提示“找不到对象“表”,因为它不存在或您没有权限。”如果我将表上的更改授予用户,那么它可以正常工作,但我想避免这样做。我认为如果表和存储过程由同一所有者拥有,那么用户的权限将被忽略。

是否可以在没有更改表权限的情况下以某种方式运行 UPDATE STATISTICS?

【问题讨论】:

这听起来是个坏主意。为什么不让数据库更新统计信息。如果您进行大数据更新,通常会这样做。 【参考方案1】:

如果您使用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 用户的上下文中执行的存储过程,但可以由foobarblat 执行:

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';

【讨论】:

【参考方案2】:

除了 Aaron Bertrand 所说的之外,我还要添加另一个解决方案:模块签名。所需步骤(简而言之):

创建证书 将其导入 SQL Server 从证书创建登录 从登录创建用户 向用户授予权限(在本例中为更改表) 使用证书对存储过程进行签名 将存储过程的 exec 权限授予需要运行它的任何人

我看到的好处是,当程序运行时,你会看到谁在运行它。缺点是对存储过程的任何更改都需要您重新签名(即签名不会在更改中持续存在)和一些初始设置。 Aaron 的方法有相反的缺点/优点。

【讨论】:

以上是关于当调用用户没有 ALTER TABLE 时从存储过程调用 UPDATE STATISTICS的主要内容,如果未能解决你的问题,请参考以下文章

当用户单击按钮时从数组中删除对象

(Kivy/Python)当用户点击输入时从 textinput 小部件存储文本

ORACLE中通过SQL语句(alter table)来增加删除修改字段

当列名包含空格和特殊字符时从 data.table 包中读取?

Room Database Migration 无法正确处理 ALTER TABLE 迁移

MySQL--当mysqldump --single-transaction遇到alter table