Итак, конкретная ошибка, которую вы получаете, заключается в том, что вы не проверяете ввод, чтобы увидеть, существует ли на самом деле строка, переданная в @column
.Вы можете проверить его существование по представлению каталога метаданных sys.columns
, сделав что-то вроде этого:
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
Однако я был бы упущен, если бы не указал на две вещи.
Во-первых, это динамическая таблица динамических, где шаблон предложения очень плохая практика.Если это для тех, кто уже имеет доступ к базе данных, они могут просто запросить таблицы сами.И если это для внешнего пользователя, вы в основном дали им полный доступ для чтения базы данных с помощью этой процедуры.Конечно, есть некоторые редкие случаи, когда этот шаблон необходим, так что, если вы не можете использовать динамический sql, это подводит меня к следующему пункту.
Код, который вы используетенаписанный уязвим для атаки SQL-инъекцией.Каждый раз, когда вы используете динамический SQL, вы должны быть ОЧЕНЬ осторожны с его конструкцией.Скажем, я передал имя столбца ; drop database [admin]--
Предполагая, что у вас есть такая база данных, моя команда могла бы успешно выполниться, и ваша база данных исчезла бы.
Как обеспечить безопасность динамического SQL - сложная тема, но если выЕсли вы хотите узнать больше об этом, это, вероятно, одна из лучших статей, которые вы можете найти.http://www.sommarskog.se/dynamic_sql.html
Путем параметризации вашего запроса и использования quotename()
для таблицы и столбца я изменил его так, чтобы он выглядел следующим образом.Это все равно выдаст странные ошибки, если кто-то попытается сделать инъекционную атаку, но, по крайней мере, он не выполнит свой код.
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