首页 > 解决方案 > UPDATE PERMISSION 没有 ALTER 许可

问题描述

我有一个存储过程,它将一些数据插入到表中。最后,我想更新该表上的统计信息。正在执行该过程的用户没有足够的权限来运行 UPDATE STATITICS。现在,我的想法是创建一个存储过程,它以所有者身份执行(具有足够的权限)并授予用户对该存储过程的执行权限。到目前为止它有效,但如果我执行该过程

EXEC dwh.sp_UpdateStatistics @schemaName = 'dwh', @tableName = 'dim_Assets;SELECT 123;'

它返回 123。

我已阅读有关 SQL 注入的信息,但我不知道如何解决此问题。

这是程序:

CREATE PROCEDURE dwh.sp_UpdateStatistics @schemaName VARCHAR(10) = NULL, @tableName VARCHAR(50) = NULL
WITH EXECUTE AS owner
AS

DECLARE @updateStatistics NVARCHAR(MAX);

SET @updateStatistics = N'UPDATE STATISTICS ' + @schemaName + '.' + @tableName;

EXEC sp_executesql @updateStatistics;

您能否帮助我找到一种方法来更新统计信息,而无需授予更多权限,也没有 SQL 注入的风险。(不是他们期望的,完全是内部的,只是为了睡个好觉和“做正确的方法”的感觉)谢谢!(我有 SQLServer2017,但我无法使用此标签创建帖子。)

标签: sql-serverstored-procedurespermissionssql-injection

解决方案


使用QUOTENAME. 我还建议对动态对象使用适当的数据类型:

CREATE PROCEDURE dwh.sp_UpdateStatistics @schemaName sysname, @tableName sysname
WITH EXECUTE AS owner
AS BEGIN

    DECLARE @updateStatistics NVARCHAR(MAX);

    SET @updateStatistics = N'UPDATE STATISTICS ' + QUOTENAME(@schemaName) + N'.' + QUOTENAME(@tableName) + N';';

    EXEC sp_executesql @updateStatistics;
END;

我还= NULL从参数中删除了 ,因为将它们设为可选是没有意义的(因为 的值@updateStatistics将是NULL)。

如果您想让它在对象不存在时代码不会运行,请使用以下内容进行检查INFORMATION_SCHEMA

CREATE PROCEDURE dwh.sp_UpdateStatistics @schemaName sysname, @tableName sysname
WITH EXECUTE AS owner
AS BEGIN

    DECLARE @updateStatistics NVARCHAR(MAX);

    SELECT @updateStatistics = N'UPDATE STATISTICS ' + QUOTENAME(T.TABLE_SCHEMA) + N'.' + QUOTENAME(T.TABLE_NAME) + N';'
    FROM INFORMATION_SCHEMA.TABLES T
    WHERE T.TABLE_SCHEMA = @schemaName
      AND T.TABLE_NAME = @tableName;

    EXEC sp_executesql @updateStatistics;
END;

这将导致对象不存在时@updateStatistics的值NULL,然后不会运行(动态)SQL。


推荐阅读