如何编写空安全比较“<=>” 在纯 SQL 中?

发布于 2024-07-18 09:20:10 字数 829 浏览 7 评论 0 原文

在Mysql中有一个比较运算符是空安全的:<=>。 我在 Java 程序中创建如下准备语句时使用它:

String routerAddress = getSomeValue();
String sql = "SELECT * FROM ROUTERS WHERE ROUTER_ADDRESS <=> ? ";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, routerAddress);

现在我想切换到 H2 数据库。 如何写<=> 纯 SQL 中的运算符(例如使用 IS NULL 和 IS NOT NULL)? 我只想使用 stmt.setString 操作一次。 列名多写几次就可以了。

相关问题是Get null == null in SQL。 但是这个答案需要将搜索值写入2次(即:我的PreparedStatement中的2个问号)!?

参考: http://dev.mysql.com/ doc/refman/5.0/en/comparison-operators.html#operator_equal-to

In Mysql there is a compare operator that is a null safe: <=>. I use this in my Java program when creating prepared statements like this:

String routerAddress = getSomeValue();
String sql = "SELECT * FROM ROUTERS WHERE ROUTER_ADDRESS <=> ? ";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, routerAddress);

Now I would like to switch to the H2 database. How do I write the <=> operator in pure SQL (using for example IS NULL and IS NOT NULL)? I would like use the stmt.setString operation only once. It is okay to write the column name several times.

Related question is Get null == null in SQL. But that answer requires the search value to be written 2 times (that is: 2 question marks in my PreparedStatement)!?

Reference:
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_equal-to

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烟酉 2024-07-25 09:20:10

相关问题是 Get null == null in SQL。 但是这个答案需要将搜索值写入两次(即:我的PreparedStatement中的2个问号)!?

排名第二和后续的答案给出了一种方法来执行此操作,而无需两次绑定搜索值:

SELECT * FROM ROUTERS 
WHERE coalesce(ROUTER_ADDRESS, '') = coalesce( ?, '');

请注意,这需要一个永远不能是有效列值的虚拟值(即“带外”); 我正在使用空字符串。 如果你没有任何这样的值,你将不得不忍受两次绑定该值:

SELECT * FROM ROUTERS 
WHERE ROUTER_ADDRESS = ? or (ROUTER_ADDRESS is null and ? is null);

Related question is Get null == null in SQL. But that answer requires the search value to be written 2 times (that is: 2 question marks in my PreparedStatement)!?

The second-ranked and subsequent answers give a method to do this without binding the search value twice:

SELECT * FROM ROUTERS 
WHERE coalesce(ROUTER_ADDRESS, '') = coalesce( ?, '');

Note that this requires a dummy value that can never be valid column value (that's "out of band"); I'm using the empty string. If you don't have any such value, you'll have to put up with binding the value twice:

SELECT * FROM ROUTERS 
WHERE ROUTER_ADDRESS = ? or (ROUTER_ADDRESS is null and ? is null);
绮烟 2024-07-25 09:20:10

SQL 中标准的 NULL 安全相等运算符是 IS DISTINCT FROMIS NOT DISTINCT FROM

The standard NULL-safe equality operators in SQL are IS DISTINCT FROM and IS NOT DISTINCT FROM.

久伴你 2024-07-25 09:20:10

在 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 <> ?
      )

In SQL, NULL is not equal to itself. So you can either:

1 - Replace it with a dummy value and compare those, as in:

SELECT * FROM ROUTERS WHERE ISNULL(ROUTER_ADDRESS,'xxx') <=> ISNULL(?,'xxx')

or

2 - Replace it with a more elaborate logical test, as in:

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 <> ?
      )
格子衫的從容 2024-07-25 09:20:10

如果您想要 ROUTERS,其中 ROUTER_ADDRESS 何时为空? 为 null 那么这可能有效:

SELECT * 
FROM ROUTERS 
WHERE ROUTER_ADDRESS = (case when ROUTER_ADDRESS is null and ? is null then null 
                             else ? end)

If you want ROUTERS where ROUTER_ADDRESS is null when ? is null then possibly this could work:

SELECT * 
FROM ROUTERS 
WHERE ROUTER_ADDRESS = (case when ROUTER_ADDRESS is null and ? is null then null 
                             else ? end)
内心荒芜 2024-07-25 09:20:10

重写<=>的正确答案是 在纯 SQL 中(因为您没有使用 MySQL)是

“IS NOT DISTINCT FROM”,

假设您的数据库引擎支持它。 (MySQL 没有,但许多其他数据库系统有)

如果做不到这一点,许多其他数据库系统都有自己的专有技巧。

如果两者都没有,则需要合并到 where 子句内的无效数据。

COALESCE (a, "__NULL__") 

应该适用于字符或文本字段。 (我的意思是确切的字符串,它永远不应该显示在真实数据中)。 非文本字段比较棘手,因为 sql 喜欢进行隐式转换,这使得合并到带外数据变得非常困难。 如果字段仅包含过去的日期,您可以将空值合并到遥远的未来。 如果字段仅包含特定日期之后的日期,则可以合并到遥远的过去。 对于无符号数字,您可以将它们合并为 -1(即使该字段不能包含负 1,该比较仍然有效)。

如果这不是一个选择,你就必须进行非常愚蠢的长检查。

如果您实际上不需要将 null 与空不同地考虑,您可以合并到它,但这仅适用于文本/字符。

The correct answer for rewriting <=> in pure SQL (because you aren't using MySQL) is

"IS NOT DISTINCT FROM"

assuming that your database engine supports it. (MySQL does NOT, but many others do)

Failing that, many other database systems have their own proprietary tricks.

If you have neither, you need to coalesce to invalid data inside of the where clause.

COALESCE (a, "__NULL__") 

should work for char or text fields. (and i mean that exact string, which should never show in real data). non text fields are trickier, because sql likes to do implicit conversions, which make it very difficult to coalesce to out of band data. if a field contains only past dates, you can coalesce nulls to the far future. if a field contains only dates after a certain one, you can coalesce to the far past. For unsigned numbers, you can coalesce them to -1 (the comparison will still work, even though the field can't contain negative 1).

If that's not an option, you have to make really stupidly long checks.

If you don't actually need to consider null differently from empty, you can coalesce to that instead, but that only works for text/char.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文