我想从用户变量中获取:'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
哇...我无话可说,这是我见过的最恐怖的动态陈述之一。从字面上看,您是在使恶意程序可以轻易注入的语句使恶意人员可以访问价值2GB的字符以注入([1,073,741,824个字符,并带有nvarchar(MAX)
)。他们将LITERALLY能够在足够的时间(和权限)下完成他们想要的任何事情。请花些时间阅读我在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
的ORDER BY
意味着每一次]运行查询的返回行可能不同。关于我对前缀Is the sp_ prefix still a no-no?的评论