如何在存储过程中执行动态查询?
How execute a dynamic query in stored procedure?
我想从用户变量中获取:'Top' 子句的 num 和来自 northwind DB 的 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 的字符(,即带有 nvarchar(MAX)
的 1,073,741,824 个字符)以针对很容易遭受注入的语句。他们会 LITERALLY 能够在足够的时间(和权限)下做任何他们想做的事。请花时间阅读我在 Dos and Don'ts of Dynamic SQL and have a look at 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';
这将(正如评论者刚刚提醒我的那样)从 table 中给出 N 任意行(不是 "Top" 行,并且 tables 没有内置订单)。因此,没有 ORDER BY
的 TOP
意味着每次 查询 运行.
时返回的行可能不同
至于我对前缀的评论:Is the sp_ prefix still a no-no?
我想从用户变量中获取:'Top' 子句的 num 和来自 northwind DB 的 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 的字符(,即带有 nvarchar(MAX)
的 1,073,741,824 个字符)以针对很容易遭受注入的语句。他们会 LITERALLY 能够在足够的时间(和权限)下做任何他们想做的事。请花时间阅读我在 Dos and Don'ts of Dynamic SQL and have a look at 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';
这将(正如评论者刚刚提醒我的那样)从 table 中给出 N 任意行(不是 "Top" 行,并且 tables 没有内置订单)。因此,没有 ORDER BY
的 TOP
意味着每次 查询 运行.
至于我对前缀的评论:Is the sp_ prefix still a no-no?