2010-06-21 3 views
5

У меня есть SQL хранимой процедура формыPassing SQL хранимой процедура совокупность ИНЕК

SELECT [fields] FROM [table] WHERE @whereSql 

Я хочу, чтобы пройти процедуру аргумент (@whereSql), который определяет весь ИНЕКЕ, но следующее сообщение об ошибке :

An expression of non-boolean type specified in a context where a condition is expected 

Это можно сделать?

+5

Зачем вам это нужно? Вы не получаете ни одной из преимуществ хранимой процедуры со всей ценой. –

+0

Я думаю, что это не очень полезно для хранимой процедуры. Амир дает вам возможность, но в вашем случае я думаю, что буду использовать представление. – DomreiRoam

+0

Джоэл и Джефф рассказывают о параметризации SQL в подкасте 31. https://stackoverflow.fogbugz.com/default.asp?W26423 –

ответ

8

Короткий ответ: вы не можете сделать это так: SQL Server рассматривает содержимое переменной как VALUE. Он не динамически наращивает строку для выполнения (вот почему это правильно способ избежать атак SQL-инъекций).

Вы должны приложить все усилия, чтобы избежать динамического ГДЕ, как вы пытаетесь сделать, в основном по этой причине, но и ради эффективности. Вместо этого попытайтесь создать предложение WHERE, чтобы он закорочивал фрагменты с большим количеством OR, в зависимости от ситуации.

Если это не так, вы все равно можете построить строку из вашей собственной сборки из частей команды, а затем EXEC.

Таким образом, вы можете сделать это:

DECLARE @mywhere VARCHAR(500) 
DECLARE @mystmt VARCHAR(1000) 
SET @mywhere = ' WHERE MfgPartNumber LIKE ''a%'' ' 
SELECT @mystmt = 'SELECT TOP 100 * FROM Products.Product AS p ' + @mywhere + ';' 
EXEC(@mystmt) 

Но я рекомендую вместо того, что вы делаете это:

SELECT TOP 100 * 
    FROM Products.Product AS p 
    WHERE 
     (MfgPartNumber LIKE 'a%' AND ModeMfrPartNumStartsWith=1) 
    OR (CategoryID = 123 AND ModeCategory=1) 
+0

Блестящий ответ - я тоже шел по маршруту динамического SQL (из моих дней писал грязный VBA для доступа backend), но это показало мне более безопасную альтернативу с просто сдвигом в мышлении. – Katstevens

8

Я считаю, что это можно сделать с помощью динамического SQL. См. Ниже:

CREATE PROCEDURE [dbo].[myProc] 
@whereSql nvarchar(256) 

AS 
    EXEC('SELECT [fields] FROM [table] WHERE ' + @whereSql) 
GO 

Таким образом, вы должны провести серьезное исследование динамического SQL, прежде чем использовать его. Вот несколько ссылок, которые я наткнулся после быстрого поиска:

+0

Удалил мой ответ и дал +1. Это ссылка, которую я имел в своем сообщении: http://msdn.microsoft.com/en-us/library/ms188332.aspx – Amir

0

Dynamic SQL перечислены в некоторые из ответов, безусловно, решение. Однако, если нужно избегать динамического SQL, одним из решений, которые я предпочитаю, является использование табличных переменных (или временных таблиц) для хранения значения параметра, которое используется для сравнения в предложении WHERE.

Ниже приведен пример реализации хранимой процедуры.

CREATE PROCEDURE [dbo].[myStoredProc] 
@parameter1 varchar(50) 
AS 

declare @myTempTableVar Table(param1 varchar(50)) 
insert into @myTempTableVar values(@parameter1) 

select * from MyTable where MyColumn in (select param1 from @myTempTableVar) 

GO 

В случае, если вы хотите передать в несколько значений, то разделенные запятыми значения могут быть сохранены в виде строк в табличной переменной и используется таким же образом, для сравнения.

CREATE PROCEDURE [dbo].[myStoredProc] 
@parameter1 varchar(50) 
AS 

--Code Block to Convert Comma Seperated Parameter into Values of a Temporary Table Variable 
declare @myTempTableVar Table(param1 varchar(50)) 
declare @index int =0, @tempString varchar(10) 

if charindex(',',@parameter1) > 0 
begin 
set @index = charindex(',',@parameter1) 
while @index > 0 
    begin 
    set @tempString = SubString(@parameter1,1,@index-1) 
    insert into @myTempTableVar values (@tempString) 
    set @parameter1 = SubString(@parameter1,@index+1,len(@parameter1)[email protected]) 
    set @index = charindex(',',@parameter1) 
    end 

    set @tempString = @parameter1 
    insert into @myTempTableVar values (@tempString) 
end 
else 
insert into @myTempTableVar values (@parameter1) 

select * from MyTable where MyColumn in (select param1 from @myTempTableVar) 

GO 
Смежные вопросы