views:

30

answers:

3

Like this:

select * from foo where @nameofdbcolumnprovidedbyparam = 1 ?

Whenever I attempt this with sqldatasource or in ado I get errors such as:

Syntax error converting the nvarchar value 'foo' to a column of data type int.

A: 

I think in this case you would need to generate the SQL dynamically without parameter binding. Parameter binding is generally for data-input sanitation and not for customizing query structure.

-- edit --

this logic might fit your needs

SELECT *
FROM Line
WHERE ( @foo = 'monTotal' AND monTotal IS NULL)
    OR (@foo = 'monUnitPrice' AND monUnitPrice IS NULL)
Hassan Syed
Thanks, could you possibly give me an example of how to dynamically generate sql?
Phil
just use string operations. x + y + z where y is your dynamic SQL. just make sure your strings are hard-coded in the application (to protect yourself from SQL-injection)
Hassan Syed
oh thanks very much! it was much simpler than i envisaged.
Phil
@Phil, most things usually are. If it seems really complicated and it's not something that involves writing code to talk to a piece of hardware, then you're probably overcomplicating it. That's my #1 rule whenever something seems that way! ;)
Rob
Ive selected you as the correct answer, although the correct answer came from your comment. Thanks Hassan
Phil
A: 

Change your SQL to (in your code):

 string sqlToExecute = "EXEC ('SELECT * from foo WHERE ' + @nameofdbcolumnprovidedbyparam + ' =1')";

Now Sql Server will execute your query and substitute in the parameter into the SQL, so if you passed it in as "Column1", the actual Sql executed would be:

 "EXEC('SELECT * from foo WHERE Column1 =1')";

The "EXEC('')" bit allows Sql to execute a piece of dynamically constructed Sql


This isn't ideal as it leaves you more vulnerable to Sql Injection attacks which are not good, so it would be better if you could construct the Sql to be executed by limiting the number of selectable columns to a controlled list and switching the statement being executed depending on this. If that's not possible then the other solution would be to use a Stored Procedure that takes nullable parameters, such as:

CREATE PROCEDURE dbo.MyProc
 @param1 VARCHAR(10),
 @param2 VARCHAR(10)
 @param3 VARCHAR(10)
AS
BEGIN
SELECT *
FROM dbo.foo
WHERE ISNULL(@param1, column1) = column1
AND ISNULL(@param2, column2) = column2
AND ISNULL(@param3, column3) = column3
END

By calling this procedure and passing in NULL for the columns that you don't care about, only records from the table "foo" that match on the column you're after will be returned.

Rob
The exec should really be a last resort -- AFAIK the engine cannot remember (cache + stats) anything to do with an exec.
Hassan Syed
I believe this is the only way to use SQL parameterisation, while still leaving yourself open to SQL Injection Attacks.
Meff
@Hassan Syed, Sql Server is a lot better at caching execution plans for pretty much anything it does in more recent versions, so that's no longer a worry. My sole concern would the the Sql Injection risk inherent to that approach. That said, the same applies to plain string concatenation without heavily sanitising the user input.
Rob
@Meff, I called that out in the answer and pointed out a "better" way. Just because an approach is a bad one in general, it doesn't make it not an answer, and possibly the solution in a tightly scoped set of circumstances.
Rob
A: 

You can do it with a case

WHERE ( 
CASE @macolumn 
WHEN 'toto' THEN toto
WHEN 'tutu' THEN tutu
WHEN 'titi' THEN titi
ELSE null END
) = 1

It's a little bite ugly but it works and you don't have to do dynamic sql.

remi bourgarel