0

Think I am missing something really obvious but I want to use a parameter in a where statement but when I do I get the following error (This is being run as a stored procedure if that makes any difference)

Invalid column name 'John'

The where statement in question

   USE [Reports]
GO

/****** Object:  StoredProcedure [Reports].[Alarm_TestSignOffFull_Qry]    Script Date: 25/10/2018 08:56:26 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [Reports].[CustomerSearch]
    -- Add the parameters for the stored procedure here  

     @Database VARCHAR(20)
    ,@Schema VARCHAR(20)
    ,@Name VARCHAR(20)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    EXEC ('

            USE ' + @Database + '

            SELECT Customer.Name,
                   [Product Categories].[Product Number]

            RIGHT JOIN ((' + @Schema +'.Customer INNER JOIN ' + @Schema +'.Client ON Customer.Name = Client.Name) 
                LEFT JOIN ' + @Schema +'.Product ON Client.Name = Product.Client) 
            ON [Product Categories].[Product Number] = Client.Product

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

'           )
END
GO

The parameter @Name is declared as VARCHAR(20)

Dont think too much about it had to find and replace table names and column names and stuff to make sure I am allowed to post it.

The select on the real thing also brings through a lot more fields but not too worried about that for this question

To emphasize it is the where statements that are going wrong the rest of the query works and it all works when I do not use any parameters

10
  • 2
    That clearly isn't your full SQL. Is this dynamic SQL? If so, the last thing you should be doing is this type of string concatenation. Post your full query please. The SQL you have provided there would not provide the error you've given us, as it would filter the dataset to rows which have the literal string value ' + @Name +' in the column Customer.Name. Commented Oct 25, 2018 at 8:34
  • Also, the there is no string concatenation, it will use ' + @Name + ' as such Commented Oct 25, 2018 at 8:35
  • You might need to use WHERE Customer.Name = @Name Commented Oct 25, 2018 at 8:38
  • put full query here otherwise you will get answers that will distract you from actual solutions Commented Oct 25, 2018 at 8:41
  • Making some adjustments to be able to post the full query, cant really post it as it is Commented Oct 25, 2018 at 8:44

4 Answers 4

4

I'm posting this as answer, as the comments aren't enough to explain, however, there is far too little detail here to actually answer the OP's question.

Firstly, the error the OP is getting would be impossible to get with the tiny amount of SQL they have provided. If we expand it into a full Pseudo-SQL query, we get:

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

This would return rows in the Customer table, where Name has the literal string value ' + @Name + '. Very unlikely.

I suspect that the OP simply needs to do:

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

HOWEVER, the error the OP is getting strong implies they are using Dynamic SQL. This means they have a query like this:

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

The problem here is that translates into the SQL:

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

Notice, no quotes around John, and why the error.

What you are doing here, however, is a very bad idea. Raw string concatenation like that leaves your SQL wide open to injection(SQL injection). Parametrise your 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;`

Edit: Ok, the OP has provided us with their query. Honestly, it's a mess, far worse that I wanted it to be. Like i said before, raw string concatenation is an awful idea, it leaves you open to injection. You can't get rid of concatenation for dynamic objects, but you can use QUOTENAME, which makes the code safe(r).

You're also missing a FROM; no idea what that needs to be, so i've left that as pseudo-sql. That RIGHT JOIN is very messy too, but I've no idea what you're trying to achieve there.

Anyway, this need to replace your EXEC command. Read the below, understand the below, and don't make the mistake of concatenating raw strings in your dynamic 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;
Sign up to request clarification or add additional context in comments.

3 Comments

will give it a go and change my answer if it works, I don't SQL injection will be an issue though as this will only every be access from SSRS where the parameter will be set from a drop down so the user will have no opportunity to attempt to SQL unject
@JoshuaDavidson injection is always an issue. Just because you think the SP will only be run via SSRS doesn't mean it will be, or that someone couldn't manipulate the values in the drop down.
with a little bit of tweaking this is working and like you say it is more secure than how we were doing it. Thanks!
0

If you are directly write in sql then you can use as below

 WHERE Customer.Name = @Name  

1 Comment

@PLC is probably in the SQL that you haven't shown us
0

You are using a Dynamic SQL, and if you print your query it will be like

WHERE Customer.Name = (John)

And that's wrong, you can do like

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

Or even

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

Why does SQL think that the parameter is a column and not just plain text?

Well, as you can see before, the parameter you pass will be John not 'John', thus SQL Server will think it's a column name.

Comments

0

try giving single quotes in where clause

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

4 Comments

Wow that worked, knew it would be something simple, Thanks!
This is an awful idea. it's wide open to injection (not just with @name but also on @Database and @schema). @JoshuaDavidson I highly recommend you do not use this answer.
@Larnu I agree with your point however I was much concern about OP query here to complete it. when we talk about best practices it should not follow this
@AmeyaDeshpande it's not about best practice, it's that what you have there is simply a bad idea. A bad answer that solves an answer, is still a bad answer. Much like painting over a mouldy wall will solve the problem of seeing the mold, but it won't solve the problem of the damp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.