有没有办法做这样的事情?人是表的名字。
declare @placeholder varchar(20) = 'People'
select * from @placeholder
或者类似这样的表名称为People_Backup。
declare @placeholder varchar(20) = '_Backup'
select * from People@placeholder
有没有一种方法可以在动态sql中添加变量的值? 像这样的东西:
declare @placeholder nvarchar(20) = 'people'
declare @name nvarchar(30) = 'antony'
declare @query nvarchar(1000) = 'select * from ' + @placeholder + ' where
first_name=' + @name
exec sp_executesql @query
我的意思是:不这样做
exec sp_executesql @query, N'@name varchar(30)', @name
谢谢您的回答。
答案 0 :(得分:3)
不是没有动态SQL。
SQL中的参数是 data 的占位符,不能用作其他任何内容(包括 commands ,例如select
,update
的占位符等”和标识符,例如数据库名称,架构名称,表名称,列名称等)。
参数化表名的唯一方法是使用动态SQL-这意味着您必须构建一个包含要执行的SQL的字符串,然后执行它。
当心-动态SQL可能是SQL injection攻击的门户-因此您必须明智地做-这是一些基本规则:
始终将您的标识符列入白名单(使用系统表或视图,例如sys.Tables
或Information_schema.Columns
)
始终使用sysname
作为标识符的数据类型。
sysname
数据类型用于存储对象名称的表列,变量和存储过程参数。 sysname的确切定义与标识符规则有关。因此,它在SQL Server实例之间可能有所不同。
从不在参数中传递SQL命令或子句-set @placeholder = 'select a, b, c'
或set @placeholder = 'where x = y'
是安全隐患!
始终使用参数存储数据。切勿将参数串联到您的sql字符串中:set @sql = 'select * from table where x = '+ @x
是安全隐患。始终创建动态SQL以将参数用作参数:set @sql = 'select * from table where x = @x'
始终使用sp_executeSql
而不是EXEC(@SQL)
来执行动态SQL语句。
有关更多信息,请阅读Kimberly Tripp的EXEC and sp_executesql – how are they different?
始终用QUOTENAME()
包装标识符,以确保正确的查询,即使标识符包含诸如空格之类的字符
回顾一下-您要求的安全版本(带有一个动态的where子句来说明其他要点)是这样的:
@DECLARE @TableName sysname = 'People',
@ColumnName sysname = 'FirstName'
@Search varchar(10) = 'Zohar';
IF EXISTS(
SELECT 1
FROM Information_Schema.Columns
WHERE TABLE_NAME = @TableName
AND COLUMN_NAME = @ColumnName
)
BEGIN
DECLARE @Sql nvarchar(4000) =
'SELECT * FROM +' QUOTENAME(@TableName) +' WHERE '+ QUOTENAME(@ColumnName) +' LIKE ''%''+ @Search +''%'';'
EXEC sp_executesql @Sql, N'@Search varchar(10)', @Search
END
-- you might want to raise an error if not
直接编辑后回答您的问题:
我的意思是:不执行exec sp_executesql @query,N'@ name varchar(30)',@name
是的,您可以不使用sp_executeSql
来做到这一点,但这很危险-攻击者可以使用类似'';DROP TABLE People;--
的值作为{{1} },以便在执行sql时,您的@name
表将被删除。
为此,您需要将People
和@name
-
'
答案 1 :(得分:0)
我的意思是:如果不这样做,
exec sp_executesql @query, N'@name varchar(30)', @name
是的,您可以这样做
--Use MAX instead of 1000
DECLARE @SQL nvarchar(MAX) = N'SELECT * FROM ' + @placeholder + ' WHERE first_name = '''+@name +'''';
EXECUTE sp_executesql @SQL;