检查WHERE子句中的条件

时间:2018-10-11 12:30:40

标签: sql-server conditional where-clause mybatis

我在XML映射中处于动态WHERE以下的情况,并且工作正常:

WHERE
    IncomingFlightId=#{flightId}
    <if test="screenFunction == 'MAIL'.toString()">
        and ContentCode = 'M'
    </if>
    <if test="screenFunction == 'CARGO'.toString()">
        and ContentCode Not IN('M')
    </if>
    order by ContentCode ASC

我正在尝试在IDE中的查询下面运行,但不幸的是它无法正常工作。

有人可以解释我在做什么错吗?

WHERE
   IncomingFlightId = 2568648 
   AND (IF 'MAIL' = 'MAIL'
   BEGIN
        SELECT 'and ContentCode = "M"'
   END ELSE BEGIN
        SELECT 'and ContentCode Not IN("M")'
   END)
   order by ContentCode ASC

2 个答案:

答案 0 :(得分:1)

您不能在直接SQL语句中使用IF,而应使用CASE WHEN test THEN returniftrue ELSE valueiffalse END(如果必须使用条件逻辑)

也就是说,如果您执行以下操作,则可以避免:

WHERE
  (somecolumn = 'MAIL' AND ContentCode = 'M') OR
  (somecolumn <> 'MAIL' and ContentCode <> 'M')

直接SQL中的条件逻辑示例:

SELECT * FROM table
WHERE
  CASE WHEN col > 0 THEN 1 ELSE 0 END = 1

运行测试并返回值时的情况。您总是必须将返回值与其他值进行比较。您不能做不返回值的事情。

但是,这有点愚蠢,因为您可以直接在where子句的事实中更简单,更易于理解地表达案件时的真实情况。

SELECT * FROM table
WHERE
  CASE WHEN type = 'x'
    THEN (SELECT count(*) FROM x) 
    ELSE (SELECT count(*) FROM y) 
  END = 1

SELECT * FROM table
WHERE
  (type = 'x' AND (SELECT count(*) FROM x) = 1) OR
   type <> 'x' AND (SELECT count(*) FROM y) = 1)  

尽管如此,它对于这样的事情还是很有用的:

SELECT 
  bustourname, 
  SUM(CASE WHEN age > 60 THEN 1 ELSE 0 END) as count_of_old_people
FROM table 
GROUP BY bustourname

如果您希望编写一个有条件地构建SQL的存储过程,那么可以确定...

DECLARE @sql VARCAHR(max) = 'SELECT * FROM TABLE WHERE';
IF blah SET @sql = CONCAT(@sql, 'somecolumn = 1')
IF otherblah SET @sql = CONCAT(@sql, 'othercolumn = 1')
EXEC @sql...

但这仅在存储过程或类似过程的sql脚本中,在此过程中,它会构建一个类似于SQL的字符串,然后动态执行它。您不能在普通的SELECT语句中使用IF

答案 1 :(得分:1)

您正在运行的查询(除了语法上不正确的SQL)与mybatis生成和使用的查询无关。

您需要了解mybatis映射器中if的工作方式。 if元素在生成SQL查询文本的阶段在执行查询之前求值。如果test的值为true,则if元素的内容将包含在结果查询中。在您的情况下,取决于传递给mybatis映射器方法的screenFunction参数,将生成以下三个条件之一。

如果screenFunction的值为MAIL,则:

WHERE
IncomingFlightId=#{flightId}
    and ContentCode = 'M'
order by ContentCode ASC

如果screenFunction的值为CARGO,则:

WHERE
IncomingFlightId=#{flightId}
    and ContentCode Not IN('M')
order by ContentCode ASC

否则(如果screenFunction的值不是MAIL也不是CARGO

WHERE
IncomingFlightId=#{flightId}
order by ContentCode ASC

仅在生成查询文本之后,才对数据库通过JDBC执行查询文本。

因此,如果要手动运行查询,则需要尝试以下查询之一。

您可能想做的一件事是简化enable logging传递给它们的SQL查询和参数,以便您更轻松地重新运行它们。