Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在动态SQL查询中设置表名?_Sql_Sql Server_Sql Server 2008_Parameters_Dynamicquery - Fatal编程技术网

如何在动态SQL查询中设置表名?

如何在动态SQL查询中设置表名?,sql,sql-server,sql-server-2008,parameters,dynamicquery,Sql,Sql Server,Sql Server 2008,Parameters,Dynamicquery,我想在动态SQL查询中设置表名。我已成功尝试以下参数: /* Using sp_executesql */ /* Build and Execute a Transact-SQL String with a single parameter value Using sp_executesql Command */ /* Variable Declaration */ DECLARE @EmpID AS SMALLINT DECLARE @SQLQuery AS NVARCHAR(500) D

我想在动态SQL查询中设置表名。我已成功尝试以下参数:

/* Using sp_executesql */
/* Build and Execute a Transact-SQL String with a single parameter 
value Using sp_executesql Command */

/* Variable Declaration */
DECLARE @EmpID AS SMALLINT
DECLARE @SQLQuery AS NVARCHAR(500)
DECLARE @ParameterDefinition AS NVARCHAR(100)
/* set the parameter value */
SET @EmpID = 1001
/* Build Transact-SQL String by including the parameter */
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = @EmpID' 
/* Specify Parameter Format */
SET @ParameterDefinition =  '@EmpID SMALLINT'
/* Execute Transact-SQL String */
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID
现在我想使用一个参数动态地获取表名,但我没有做到这一点。请引导我。

试试这个:

/* Variable Declaration */
DECLARE @EmpID AS SMALLINT
DECLARE @SQLQuery AS NVARCHAR(500)
DECLARE @ParameterDefinition AS NVARCHAR(100)
DECLARE @TableName AS NVARCHAR(100)
/* set the parameter value */
SET @EmpID = 1001
SET @TableName = 'tblEmployees'
/* Build Transact-SQL String by including the parameter */
SET @SQLQuery = 'SELECT * FROM ' + @TableName + ' WHERE EmployeeID = @EmpID' 
/* Specify Parameter Format */
SET @ParameterDefinition =  '@EmpID SMALLINT'
/* Execute Transact-SQL String */
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID

表名不能作为参数提供,因此您必须像下面这样手动构造SQL字符串:

SET @SQLQuery = 'SELECT * FROM ' + @TableName + ' WHERE EmployeeID = @EmpID' 

但是,请确保您的应用程序不允许用户直接输入@TableName的值,因为这会使您的查询容易受到SQL注入的影响。有关此问题的一个可能解决方案,请参阅。

为了帮助防范SQL注入,我通常会尽可能使用函数。在这种情况下,您可以执行以下操作:

...
SET @TableName = '<[db].><[schema].>tblEmployees'
SET @TableID   = OBJECT_ID(TableName) --won't resolve if malformed/injected.
...
SET @SQLQuery = 'SELECT * FROM ' + OBJECT_NAME(@TableID) + ' WHERE EmployeeID = @EmpID' 

这是动态获取模式并将其添加到数据库中不同表以动态获取其他信息的最佳方法

选择@sql='插入表从sys.tables中选择[+SCHEMA\u NAMEschema\u id+.+name+]作为SchemaTable

exec (@sql)

当然,tables是存储过程中的一个动态表

基于@user1172173先前的答案,该答案解决了SQL注入漏洞,请参见以下内容:

CREATE PROCEDURE [dbo].[spQ_SomeColumnByCustomerId](
@CustomerId int,
@SchemaName varchar(20),
@TableName nvarchar(200)) AS
SET Nocount ON
DECLARE @SQLQuery AS NVARCHAR(500)
DECLARE @ParameterDefinition AS NVARCHAR(100)
DECLARE @Table_ObjectId int;
DECLARE @Schema_ObjectId int;
DECLARE @Schema_Table_SecuredFromSqlInjection NVARCHAR(125)

SET @Table_ObjectId = OBJECT_ID(@TableName)
SET @Schema_ObjectId = SCHEMA_ID(@SchemaName)
SET @Schema_Table_SecuredFromSqlInjection = SCHEMA_NAME(@Schema_ObjectId) + '.' + OBJECT_NAME(@Table_ObjectId)

SET @SQLQuery = N'SELECT TOP 1 ' + @Schema_Table_SecuredFromSqlInjection + '.SomeColumn 
FROM dbo.Customer 
INNER JOIN ' + @Schema_Table_SecuredFromSqlInjection + ' 
ON dbo.Customer.Customerid = ' + @Schema_Table_SecuredFromSqlInjection + '.CustomerId 
WHERE dbo.Customer.CustomerID = @CustomerIdParam 
ORDER BY ' + @Schema_Table_SecuredFromSqlInjection + '.SomeColumn DESC' 
SET @ParameterDefinition =  N'@CustomerIdParam INT'

EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @CustomerIdParam = @CustomerId; RETURN

无法参数化表名。您只需在SET@SQLQuery步骤中手动执行即可。@MatBailie实际上,您可以将表名用作字符串,并使用字符串名的exec,它的行为与procedure@hellbaby-但仍然不能将表名作为参数提供给sp_executesql,这只能通过替换字符串来实现。这些是非常不同的。参数化允许进行类型检查、防止SQL注入攻击、执行计划重用等。将字符串替换为其他字符串不起任何作用,因此不是参数化。@MatBailie实际上您不需要“sp_executesql”命令,在mssql 2008+中,这样调用就足够了:exec@myqueryconcatedvariablewithtablename,您得到了答案;关于注射-也许你是对的,有技能的人可以打破它。所以这取决于他到底需要在哪里使用这个…@HellBaby-这是完全相同的机制-您只需将表名替换到字符串中,然后执行生成的字符串。在您的示例中,表名不是参数。谢谢,但无论如何,我真的不想要这个。无法将表名作为表名传递给sp_executesql:@Neo您应该能够使用sp_executesql,因为在设置SQL字符串时,您应该已经插入了正确的表名。这是为什么SQL字符串首先是手动构造的一个主要原因。另一个考虑因素是在变量周围也应用QuoteName。这将正确地用对象包装器包装表名,默认为方括号[…]这绝对是我想要的完整答案。太棒了!完美地解决了我的问题。打开SQL注入。您只需传递一个错误的@TableName参数,例如'sys.databaeses;Alter Server Role sysadmin添加成员[坏蛋];-'这就是你的系统。