views:

34

answers:

1

Hello all,

I have a web based program which chooses some records from a database using a checkboxlist. (my check box list sends parameters to a stored procedure and I use the result of stored procedure).

Here how my check box list looks like

Overflow              [] (sends param1)
Open Records          [] (sends param2)
Records with 4 groups [] (sends param3)

Here how my stored procedure looks like,

SELECT * FROM myRecordsTable WHERE
        (Overflow LIKE '%O%' OR @param1= 'No')
        AND (OpenClose= 'Open' OR @param2= 'No')
        AND (4orMore = '4orMore' OR @param3 = 'No')

So as you can see, my check box lists works like "And" procedure, in other words, when I check Overflow and Open records in my checkboxlist, my stored procedure will return (Open records which has Overflow)

What I like to do is I want my check box list to work like "Or", in other words, I want to be able to get (Open records "OR" records which has Overflow)

Important PS: I can't have two stored procedures (1 for OR and 1 for AND) since my procedures are not that short like the example above, because once I change something in one procedure I will have to do the exact same changes in the second one and that is not good coding.

Important PS2: I don't want to corrupt the structure of the stored procedure. I want to use my stored procedure as "AND" or "OR" whenever I want (using another parameter maybe), and the way I tried to do this was using dynamic sql as in the link below

http://stackoverflow.com/questions/3194696/sql-server-can-a-t-sql-operator-be-used-like-a-variable-or-something-like-that/3194710#3194710

but I couldn't manage to solve it.

Thanks for helps.

Edit: Here I will give an example to show the problem more clearly

Below code, nothing is selected in checkboxlist, returns 42703 (Remember this number) rows

declare @op varchar(3)
set @op = 'AND'

declare @query nvarchar(4000)
set @query = 
'
SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
'
set @query = @query + '(ASIM LIKE ''%S%'' OR ''No''=''No'') '+@op+' ' 

set @query = @query + '(SonGrup LIKE ''Son Grup'' OR ''No''=''No'') '+@op+' '

set @query = @query + '(DortUzeri LIKE ''Dört ve Üzeri'' OR ''No''=''No'') '
exec(@query)

Below code ASIM is selected, returns 9349 rows

declare @op varchar(3)
set @op = 'AND'

declare @query nvarchar(4000)
set @query = 
'
SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
'
set @query = @query + '(ASIM LIKE ''%S%'' OR ''Yes''=''No'') '+@op+' ' 

set @query = @query + '(SonGrup LIKE ''Son Grup'' OR ''No''=''No'') '+@op+' '

set @query = @query + '(DortUzeri LIKE ''Dört ve Üzeri'' OR ''No''=''No'') '
exec(@query)

I won't give the same code anymore, because the logic is same, the "No" turns into "Yes" when the checkbox list is selected, and this is the structure of the code.

ASIM and SonGrup is selected returns 5885 rows ASIM and SonGrup and DortUzeri is selected returns 1385 rows

The above code works perfectly with AND, so when I wanted to use OR Operator I should get the result 37696 , which is the result of the below code

SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
ASIM LIKE '%S%' OR SonGrup LIKE 'Son Grup' OR DortUzeri LIKE 'Dört ve Üzeri'

So I executed the code with OR operator where the three checkbox list components is selected, the code is below and it returns 37696 , which is correct.

declare @op varchar(3)
set @op = 'OR'

declare @query nvarchar(4000)
set @query = 
'
SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
'
set @query = @query + '(ASIM LIKE ''%S%'' OR ''Yes''=''No'') '+@op+' ' 

set @query = @query + '(SonGrup LIKE ''Son Grup'' OR ''Yes''=''No'') '+@op+' '

set @query = @query + '(DortUzeri LIKE ''Dört ve Üzeri'' OR ''Yes''=''No'') '
exec(@query)

The problem arises when one of the checklist components is not checked, here is the 3rd component is not checked version of the code,

declare @op varchar(3)
set @op = 'OR'

declare @query nvarchar(4000)
set @query = 
'
SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
'
set @query = @query + '(ASIM LIKE ''%S%'' OR ''Yes''=''No'') '+@op+' ' 

set @query = @query + '(SonGrup LIKE ''Son Grup'' OR ''Yes''=''No'') '+@op+' '

set @query = @query + '(DortUzeri LIKE ''Dört ve Üzeri'' OR ''No''=''No'') '
exec(@query)

The above code should have returned 34613 which I found using the following

SELECT ASIM, SonGrup, DortUzeri FROM CacheOPERASYONELRawKayitlar WHERE
ASIM LIKE '%S%' OR SonGrup LIKE 'Son Grup'

However it returns 42703 (The number which I wanted you to remember caused because of ''No''=''No'') , that is where my problem arises. Here I couldn't find the solution.

+2  A: 

You should use dynamic sql - as well as the syntax being easier on the eye it will also give your query a better chance of performing.

If you can, then I would probably construct the dynamic sql in your application rather than in the stored procedure, however if you really have to call a stored procedure then that also works:

Disclaimer: I never usually write dynamic SQL inside a stored procedure, and I also don't have SQL server installed on this machine to make sure that the following works, however hopefully this should be of some help:

declare @op varchar(3)

IF @operator = "AND"
    set @op = "AND"
ELSE
    set @op = "OR"

declare @query varchar(max)
set @query = "select * from myRecordsTable WHERE" +

IF @param1 <> "No"
    set @query = @query + " Overflow LIKE '%O%' " + @op
IF @param2 <> ' No'
    set @query = " OpenClose = 'Open' " + @op

IF @operator = "AND"
    set @query = @query + " 1=1"
IF @operator = "OR"
    set @query = @query + " 1=0"

exec(@query)

Important parts to note:

  • I test the value of @operator explicitly to avoid SQL injection (never trust your caller)
  • I use 1=1 and 1=0 to avoid complicated logic with operators due to not knowing which of my conditions will be the first or the last. SQL server optimiser will optimise this away as a tautology early in the optimisation process.
Kragen
How come you did that without a compiler, is that experience ? :)
stckvrflw