如何在存储过程中执行动态查询?

时间:2019-12-10 19:12:43

标签: sql sql-server stored-procedures dynamic-sql

我想从用户变量中获取:“ Top”子句的num和Northwind数据库中的Tbl名称, 并返回结果集前5名,我的脚本关闭了

create procedure sp_getTop5 
(
    @num int , 
    @tbl nvarchar(max)
)    
as       
    declare @res nvarchar(max);       
    set @res =  'select top '+str(@num)+' *   from '+@tbl

    exec @res   

---- check
exec sp_getTop5 5, employees

1 个答案:

答案 0 :(得分:4)

哇...除了那是我见过的最恐怖的动态陈述之一,我无话可说。从字面上看,您是在使恶意程序可以轻易注入的语句使恶意人员可以访问价值2GB的字符,以对其进行注入(即1,073,741,824个字符,并带有nvarchar(MAX) )。他们将 完全 能够在足够的时间(和权限)下完成他们想要的任何事情。请花时间阅读我在Dos and Don'ts of Dynamic SQL上的文章,并看看Little Bobby Tables来了解您所拥有的危险。

对于您的SQL,我不在乎您没有真正问过一个问题,您需要立即修复安全模型中的这个大漏洞:

CREATE PROC getTop5 @Num int, @schema sysname, @table sysname AS --Removed sp_ prefix, see after the answer
BEGIN
    DECLARE @SQL nvarchar(MAX);
    SELECT @SQL = N'SELECT TOP (@Num) FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + N';'
    FROM sys.schemas s
         JOIN sys.tables t ON s.schema_id = t.schema_id
    WHERE s.[name] = @schema
      AND t.[name] = @table;

    EXEC sp_executesql @SQL, N'@Num int', @Num;
END;
GO

然后您可以执行以下操作:

EXEC dbo.getTop5 5, N'dbo', N'YourTable';

这(作为评论者刚刚提醒我)将给表中的 N 个任意行(不是“ Top”行,并且表没有内置的顺序)。因此,没有TOP的{​​{1}}意味着每次运行查询时返回的行可能会不同。

至于我对前缀Is the sp_ prefix still a no-no?

的评论