Проверьте условие в предложении WHERE - PullRequest
0 голосов
/ 11 октября 2018

У меня ниже динамическое WHERE условие в сопоставлении XML, которое работает нормально:

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 голосов
/ 11 октября 2018

Вы выполняете запрос, который (кроме синтаксически некорректного SQL) не имеет ничего общего с запросом, сгенерированным и используемым mybatis.

Вам необходимо понять, как работает if в mybatis mapper.Элемент if оценивается до выполнения запроса на этапе генерации текста запроса SQL.Если значение test равно true, содержимое элемента if включается в результирующий запрос.В вашем случае, в зависимости от параметра screenFunction, передаваемого методу mybatis mapper, генерируется одно из трех условий.

Если значение 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 для базы данных.

Поэтому, если вы хотите выполнить запрос вручную, вам нужно попробовать один из этих запросов.

Одна вещь, которую вы можете сделать, чтобы упростить ее, - это включить ведение журнала запросов SQL ипараметры, переданные им, так что вы можете легко их перезапустить.

0 голосов
/ 11 октября 2018

Вы не можете использовать IF в прямом SQL-выражении, вместо этого используйте 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

Versus

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, а затем выполняет его динамически.Вы не можете использовать IF в простом выражении SELECT

...