我有一个存储过程,它将表的名称作为参数,并使用动态sql来执行select。我试图将@TableName作为参数传递并使用sp_executesql但是引发了错误。我决定使用直接动态sql而不使用sp_executesql。
我还有什么办法来保护@TableName参数以避免sql注入攻击吗?
以下存储过程:
CREATE PROCEDURE dbo.SP_GetRecords
(
@TableName VARCHAR(128) = NULL
)
AS
BEGIN
/* Secure the @TableName Parameter */
SET @TableName = REPLACE(@TableName, ' ','')
SET @TableName = REPLACE(@TableName, ';','')
SET @TableName = REPLACE(@TableName, '''','')
DECLARE @query NVARCHAR(MAX)
/* Validation */
IF @TableName IS NULL
BEGIN
RETURN -1
END
SET @query = 'SELECT * FROM ' + @TableName
EXEC(@query)
END
使用sp_executesql时失败:
SET @query = 'SELECT * FROM @TableName'
EXEC sp_executesql @query, N'@TableName VARCHAR(128)', @TableName
错误:必须声明表变量 “@tablename”。
答案 0 :(得分:3)
答案 1 :(得分:2)
你当然可以查看sysobjects表并确保它存在
Select id from sysobjects where xType = 'U' and [name] = @TableName
进一步(更完整的例子):
DECLARE @TableName nVarChar(255)
DECLARE @Query nVarChar(512)
SET @TableName = 'YourTable'
SET @Query = 'Select * from ' + @TableName
-- Check if @TableName is valid
IF NOT (Select id from sysobjects where xType = 'U' and [name] = @TableName) IS NULL
exec(@Query)