Как написать безопасное сравнение с нулем “<=>” в чистом SQL?
Вопрос
В Mysql есть оператор сравнения, который является безопасным с нулевым значением:<=>.Я использую это в своей Java-программе при создании подготовленных операторов, подобных этому:
String routerAddress = getSomeValue();
String sql = "SELECT * FROM ROUTERS WHERE ROUTER_ADDRESS <=> ? ";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, routerAddress);
Теперь я хотел бы переключиться на базу данных H2.Как мне написать <=> оператор в чистом SQL (используя, например, значение NULL и НЕ является NULL)?Я бы хотел использовать только операцию stmt.setString однажды.Это нормально - написать название столбца несколько раз.
Связанный с этим вопрос заключается в следующем Получаем null == null в SQL.Но этот ответ требует, чтобы значение поиска было записано 2 раза (то есть:2 вопросительных знака в моем подготовленном заявлении)!?
Ссылка:http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_equal-to
Решение
Связанный с этим вопрос - Get null == null в SQL.Но этот ответ требует, чтобы значение поиска было записано 2 раза (то есть:2 вопросительных знака в моем подготовленном заявлении)!?
Ответы со вторым рейтингом и последующие ответы дают способ сделать это без привязки значения поиска дважды:
SELECT * FROM ROUTERS
WHERE coalesce(ROUTER_ADDRESS, '') = coalesce( ?, '');
Обратите внимание, что для этого требуется фиктивное значение, которое никогда не может быть допустимым значением столбца (это "вне диапазона").;Я использую пустую строку.Если у вас нет такого значения, вам придется смириться с двойной привязкой значения:
SELECT * FROM ROUTERS
WHERE ROUTER_ADDRESS = ? or (ROUTER_ADDRESS is null and ? is null);
Другие советы
Стандартными операторами равенства, защищенными от нуля, в SQL являются IS DISTINCT FROM
и IS NOT DISTINCT FROM
.
В SQL значение NULL не равно самому себе.Так что вы можете либо:
1 - Замените его фиктивным значением и сравните их, как в:
SELECT * FROM ROUTERS WHERE ISNULL(ROUTER_ADDRESS,'xxx') <=> ISNULL(?,'xxx')
или
2 - Замените его более сложным логическим тестом, как в:
SELECT *
FROM ROUTERS
WHERE (
(ROUTER_ADDRESS IS NULL AND ? IS NOT NULL)
OR
(ROUTER_ADDRESS IS NOT NULL AND ? IS NULL)
OR
(ROUTER_ADDRESS IS NOT NULL AND ? IS NOT NULL AND ROUTER_ADDRESS <> ?
)
Если вам нужны МАРШРУТИЗАТОРЫ, где ROUTER_ADDRESS равен нулю, когда?равно нулю, тогда, возможно, это могло бы сработать:
SELECT *
FROM ROUTERS
WHERE ROUTER_ADDRESS = (case when ROUTER_ADDRESS is null and ? is null then null
else ? end)