简体   繁体   中英

AND/OR based on variable value in stored procedures

I would like to use AND/OR between the conditions in a stored procedure, and the decision is dependent on the parameter value whether it was 0 (AND) or 1 (OR)

Can anyone help me with this please, i guess this is an easy thing to do but i can't seem to figure it out. Thanks

The easiest way (on first glance) would be to concatenate the query string using dynamic SQL, but dynamic SQL has its issues.
See The Curse and Blessings of Dynamic SQL for an in-depth explanation.

So I would try to avoid dynamic SQL, which is no big deal if your queries are not too complex.
The easiest way is just to fire two different queries depending on the parameter value:

CREATE PROCEDURE spTest
    @AndOr bit
AS
BEGIN

    if @AndOr = 0 begin 

        select * from YourTable where foo = 1 and bar = 2

    end
    else begin

        select * from YourTable where foo = 1 or bar = 2

    end

END

This is of course an example with a very simple query.
If you have lots of queries, or if your queries are very complex, this might not be the best solution because it forces you to duplicate all queries...but as always, it depends :-)

You can implement your logic on a CASE statement. Something like this:

CREATE PROCEDURE dbo.MySP @OrAnd BIT
AS 
BEGIN
    SELECT *
    FROM MyTable
    WHERE   CASE WHEN Condition1 AND Condition2 AND @OrAnd = 0 THEN 1
            WHEN (Condition1 OR Condition2) AND @OrAnd = 1 THEN 1 ELSE 0 END = 1
END

If you convert the simple conditions' boolean results into numeric ones ( 0 or 1 ), you will be able to use your parameter in the following way:

(
  (CASE WHEN condition1 THEN 1 ELSE 0 END ^ @AndOr)
  &
  (CASE WHEN condition2 THEN 1 ELSE 0 END ^ @AndOr)
) ^ @AndOr = 1

Here @AndOr is your parameter, ^ is the Transact-SQL bitwise exclusive OR operator, & stands for the bitwise AND in Transact-SQL, and the CASE expressions are used to convert the boolean results into 0 or 1 .

If @AndOr = 0 (which means we want AND between the conditions), the above expression effectively boils down to this:

case1 & case2 = 1

because X XOR 0 yields X and so neither individual values of case1 and case2 nor the entire result of the & operator are not affected by the ^ operators. So, when @AndOr is 0 , the result of the original expression would be equivalent to the result of condition1 AND condition2 .

Now, if @AndOr = 1 (ie OR ), then every ^ operator in the expression returns the inverted value of its left operand, in other words, negates the left operand, since 1 XOR 1 = 0 and 0 XOR 1 = 1 . Therefore, the original expression would essentially be equivalent to the following:

¬ (¬ case1 & ¬ case2) = 1

where ¬ means negation. Or, converting it back to the booleans, it would be this:

NOT (NOT condition1 AND NOT condition2)

According to one of De Morgan's laws ,

(NOT A) AND (NOT B) = NOT (A OR B)

Applying it to the above condition, we get:

NOT (NOT condition1 AND NOT condition2) = NOT (NOT (condition1 OR condition2)) =
= condition1 OR condition2

So, when @AndOr is 1 , the expression given in the beginning of my answer is equivalent to condition1 OR condition2 . Thus, it works like expected based on the value of @AndOr .

Having the input parameter you can use a IF clause to make different selects .

If input parameter = 0 make the AND conditions , otherwise make the OR conditions .

I can't see any particular elegant way to do it. So here's the straightforward approach

create function myfun (@parm1 int, @parm2 int, @andor int) returns int
begin
if (@andor = 0 AND  @parm1 = 99 AND @parm2 = 99) return 1
else if (@andor = 1 AND (@parm1 = 99 OR @parm2 = 99)) return 1
return 0
end
go
select dbo.myfun(99,98,0) -- AND condition should return 0
select dbo.myfun(99,98,1) -- OR condition should return 1
select dbo.myfun(98,98,0) -- AND condition should return 0
select dbo.myfun(98,98,1) -- OR condition shoujld return 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM