WHERE语句中的SQL Using参数

时间:2018-10-25 08:33:04

标签: sql sql-server

我想我确实遗漏了一些明显的东西,但是我想在where语句中使用一个参数,但是当我这样做时,出现以下错误(如果有任何区别,它将作为存储过程运行)

  

无效的列名“ John”

有问题的where语句

keyof T

参数@Name声明为VARCHAR(20)

不要太想它,必须查找并替换表名,列名和东西以确保允许我发布它。

对真实事物的选择也带来了更多领域,但对此问题并不太担心

为了强调这是哪里语句出了问题,其余的查询仍然有效,而当我不使用任何参数时,所有这些都可以正常工作

4 个答案:

答案 0 :(得分:4)

我将其发布为答案,因为评论不足以解释,但是,这里的细节太少,无法真正回答OP的问题。

首先,使用他们提供的少量SQL不可能获得OP出现的错误。如果将其扩展为完整的伪SQL查询,则会得到:

SELECT {Columns}
FROM Customer
WHERE Customer.Name = (' + @Name + ');

这将返回Customer表中的行,其中Name具有文字字符串值' + @Name + '。不太可能。

我怀疑OP只需要做:

SELECT {Columns}
FROM Customer
WHERE Customer.Name = @Name;

但是,OP变得越来越强大的错误意味着他们正在使用动态SQL。这意味着他们有这样的查询:

DECLARE @SQL nvarchar(MAX);
DECLARE @Name varchar(20) = 'John';
SET @SQL = N'SELECT {Columns} FROM Customer WHERE Customer.Name = (' + @Name + ');';
EXEC (@SQL);

这里的问题是转换为SQL:

SELECT {Columns} FROM Customer WHERE Customer.Name = (John);

注意,John周围没有引号,以及为什么出错。

但是,您在这里所做的是一个非常不好的主意。像这样的原始字符串连接使您的SQL易于进行注入(SQL injection)。参数化您的SQL:

DECLARE @SQL nvarchar(MAX);
DECLARE @Name varchar(20) = 'John';
SET @SQL = N'SELECT {Columns} FROM Customer WHERE Customer.Name = @dName;'
EXEC sp_executesql @SQL, N'@dName varchar(20)',@dName = @Name;`

编辑:好的,OP向我们提供了他们的查询。老实说,这真是一团糟,更糟的是我想要做到这一点。就像我之前说的那样,原始字符串连接是一个糟糕的主意,它使您可以进行注入。您无法摆脱动态对象的并置,但可以使用QUOTENAME,这使代码更安全(r)。

您还缺少FROM;不知道那是什么,所以我把它留为伪SQL。 RIGHT JOIN也很混乱,但是我不知道您要在那实现什么。

无论如何,这需要替换您的EXEC命令。阅读下面的内容,理解下面的内容,并且不要犯错误,即在动态SQL中串联原始字符串:

DECLARE @SQL nvarchar(MAX)

SET @SQL = N' USE ' + QUOTENAME(@Database) + N';' + NCHAR(10) +
           N'SELECT Customer.Name,'  + NCHAR(10) +
           N'       [Product Categories].[Product Number]' + NCHAR(10) +
           --where is your FROM?
           N'FROM {Something}' + NCHAR(10) + --This needs fixing
           N'     RIGHT JOIN((' + QUOTENAME(@Schema) + N'.Customer' + NCHAR(10) + --This whole thing is messy, but i'm not fixing it, as I have no data
           N'                 INNER JOIN ' + QUOTENAME(@Schema) + N'.Client ON Customer.Name = Client.Name)' + NCHAR(10) +
           N'                 LEFT JOIN ' + QUOTENAME(@Schema) + N'.Product ON Client.Name = Product.Client)ON [Product Categories].[Product Number] = Client.Product' + NCHAR(10) +
           N'WHERE (Customer.Name = @dName' + NCHAR(10) +
           N'   AND Customer.[Order] = ''Y'')' + NCHAR(10) +
           N'   OR (Client.Name = @dName' + NCHAR(10) +
           N'   AND Customer.[Order] = ''Y'');';

EXEC sp_executesql @SQL, N'@dName varchar(20)', @dName = @Name;

答案 1 :(得分:0)

如果您直接用sql编写,则可以按以下方式使用

 WHERE Customer.Name = @Name  

答案 2 :(得分:0)

您正在使用动态SQL,并且如果您打印查询,它将像

WHERE Customer.Name = (John)

那是错误的,你可以做

EXECUTE sp_executesql N' ..WHERE Customer.Name = @CName', 
N'@CName VARCHAR(20)', 
@CName = 'John';

甚至

--@Name should be declared and has 'John' value
EXECUTE sp_executesql N' ..WHERE Customer.Name = @CName', 
N'@Name VARCHAR(20)', 
@Name = @Name;
  

为什么SQL认为参数是一列而不是纯文本?

好吧,正如您之前看到的那样,您传递的参数将是John而不是'John',因此SQL Server会认为它是列名。

答案 3 :(得分:0)

尝试在where子句中使用单引号

WHERE (Customer.Name = ''' + @Name + ''' AND Customer.Order = ''Y'') 
   OR (Client.Name = ''' + @Name + ''' AND Customer.Order = ''Y'');