我有一个存储过程,该过程将一些数据插入表中。最后,我要在该表上更新STATISTICS。执行该过程的用户没有足够的权限来运行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,但无法使用此标签创建帖子。)
答案 0 :(得分:1)
使用backup retention period
。我还建议为动态对象使用适当的数据类型:
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
,然后将不运行(动态)SQL。