So the specific error you're getting is because you're not checking the input to see if the string being passed into @column
actually exists. You can check for it's existence against the metadata catalog view sys.columns
doing something like this:
if not exists
(
select 1
from sys.columns
where object_id = object_id(@table)
and name = @column
)
begin
raiserror('Column %s does not exist in table %t', 16, 1, @column, @table)
return
end
However I would be remiss if I didn't point out two things.
First, this dynamic table dynamic where clause pattern is very bad practice. If it's for someone who already has database access, they can simply query the tables themselves. And if it's for an external user, well, you've basically given them full database read access through this procedure. Of course there are some rare occasions where this pattern is needed, so if you're dead set on using dynamic sql, that leads me to my next point.
The code you've written is vulnerable to a SQL injection attack. Any time you use dynamic SQL you must be VERY careful how it's constructed. Say I passed in the column name ; drop database [admin]--
Assuming you had such a database, my could would happily be executed and your database would disappear.
How to make dynamic SQL safe is a complex topic, but if you're serious about learning more about it, this is probably one of the best articles you can find. http://www.sommarskog.se/dynamic_sql.html
By parameterizing your query and using quotename()
on the table and column, I modified it to look like this. This will still throw weird errors if someone tries to do an injection attack, but at least it wont actually execute their code.
create procedure [dbo].[userDetailsDisplay]
@table nvarchar(30),
@column nvarchar(30),
@searchBySomething nvarchar(30)
as
begin
declare
@sql nvarchar(max),
@params nvarchar(1000)
if not exists
(
select 1
from sys.columns
where object_id = object_id(@table)
and name = @column
)
begin
raiserror('Column %s does not exist in table %t', 16, 1, @column, @table)
return
end
select @sql = '
select *
from ' + quotename(@table) + ' WHERE ' + quotename(@column) + ' = @searchBySomething'
execute sp_executesql
@stmt = @sql,
@params = '@searchBySomething nvarchar(30)',
@searchBySomething = @searchBySomething
end