未经 ALTER 许可更新许可

UPDATE PERMISSION without ALTER permission

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

执行该过程
EXEC dwh.sp_UpdateStatistics @schemaName = 'dwh', @tableName = 'dim_Assets;SELECT 123;'

它returns 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 注入的风险。 (不是意料之中,完全是inhouse,只是单纯为了睡个好觉和"doing it the correct way"的感觉) 谢谢! (我有 SQLServer2017,但我无法使用此标签创建 post。)

使用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 将是 运行。