SQL 服务器中的词典顺序比较
Lexicographical comparison in SQL SERVER
我必须对 select 行执行查询,其中复合键按字典顺序小于或大于某些给定的值元组:
SELECT TOP 100
*
FROM PALISBSD
WHERE (recbsd_key_bsd_key_bsd1_bsd_jar < '03'
OR (recbsd_key_bsd_key_bsd1_bsd_jar = '03'
AND (recbsd_key_bsd_key_bsd1_bsd_pro < 'L'
OR (recbsd_key_bsd_key_bsd1_bsd_pro = 'L'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst < 'C'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl < '00017004'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004'
AND (recbsd_key_bsd_key_bsd1_bsd_linr < '0001'
OR (recbsd_key_bsd_key_bsd1_bsd_linr = '0001'
AND (recbsd_key_bsd_key_bsd1r_bsd_sa < 'D'
OR (recbsd_key_bsd_key_bsd1r_bsd_sa = 'D'
AND (recbsd_key_bsd_key_bsd1r_bsd_an < 'PTZ')))))))))))))
ORDER BY recbsd_key_bsd_key_bsd1_bsd_jar DESC,
recbsd_key_bsd_key_bsd1_bsd_pro DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl DESC,
recbsd_key_bsd_key_bsd1_bsd_linr DESC,
recbsd_key_bsd_key_bsd1r_bsd_sa DESC,
recbsd_key_bsd_key_bsd1r_bsd_an DESC;
存在一个聚集索引,其中包含此处命名的所有列,顺序完全相同。然而,它通常不用于执行搜索。事实上,我可以通过提供 WITH (FORCESEEK)
提示或在 where 术语前加上诸如 recbsd_key_bsd_key_bsd1_bsd_jar <= '03' AND
.
之类的东西来加速很多,但不是我所有的查询
我的问题是:是否有更好的方式来表达字典序比较,这样 MS SQL 服务器将更好地利用索引进行比较? 在 Postgres 中,这会通过元组比较 (col1, col2) < ('FOO', 'BAR')
表达,但 MS SQL 服务器中不存在此功能。
编辑:我无法创建串联计算列,因为键也可能包含非字符字段。
使用 Statements 而不是 PreparedStatements 并将过滤器重新排列为如下所示,与我问题中的形式相反,实际上似乎使 SQL 服务器使用索引:
SELECT TOP 100 * FROM PALISBSD
WHERE
(recbsd_key_bsd_key_bsd1_bsd_jar < '03') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro < 'L') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst < 'C') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl < '00017004') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr < '0001') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr = '0001' AND recbsd_key_bsd_key_bsd1r_bsd_sa < 'D') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr = '0001' AND recbsd_key_bsd_key_bsd1r_bsd_sa = 'D' AND recbsd_key_bsd_key_bsd1r_bsd_an < 'PTZ')
ORDER BY
recbsd_key_bsd_key_bsd1_bsd_jar DESC,
recbsd_key_bsd_key_bsd1_bsd_pro DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl DESC,
recbsd_key_bsd_key_bsd1_bsd_linr DESC,
recbsd_key_bsd_key_bsd1r_bsd_sa DESC,
recbsd_key_bsd_key_bsd1r_bsd_an DESC;
我知道 SQL 注射,我正在以其他方式阻止它们。
我必须对 select 行执行查询,其中复合键按字典顺序小于或大于某些给定的值元组:
SELECT TOP 100
*
FROM PALISBSD
WHERE (recbsd_key_bsd_key_bsd1_bsd_jar < '03'
OR (recbsd_key_bsd_key_bsd1_bsd_jar = '03'
AND (recbsd_key_bsd_key_bsd1_bsd_pro < 'L'
OR (recbsd_key_bsd_key_bsd1_bsd_pro = 'L'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst < 'C'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl < '00017004'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004'
AND (recbsd_key_bsd_key_bsd1_bsd_linr < '0001'
OR (recbsd_key_bsd_key_bsd1_bsd_linr = '0001'
AND (recbsd_key_bsd_key_bsd1r_bsd_sa < 'D'
OR (recbsd_key_bsd_key_bsd1r_bsd_sa = 'D'
AND (recbsd_key_bsd_key_bsd1r_bsd_an < 'PTZ')))))))))))))
ORDER BY recbsd_key_bsd_key_bsd1_bsd_jar DESC,
recbsd_key_bsd_key_bsd1_bsd_pro DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl DESC,
recbsd_key_bsd_key_bsd1_bsd_linr DESC,
recbsd_key_bsd_key_bsd1r_bsd_sa DESC,
recbsd_key_bsd_key_bsd1r_bsd_an DESC;
存在一个聚集索引,其中包含此处命名的所有列,顺序完全相同。然而,它通常不用于执行搜索。事实上,我可以通过提供 WITH (FORCESEEK)
提示或在 where 术语前加上诸如 recbsd_key_bsd_key_bsd1_bsd_jar <= '03' AND
.
我的问题是:是否有更好的方式来表达字典序比较,这样 MS SQL 服务器将更好地利用索引进行比较? 在 Postgres 中,这会通过元组比较 (col1, col2) < ('FOO', 'BAR')
表达,但 MS SQL 服务器中不存在此功能。
编辑:我无法创建串联计算列,因为键也可能包含非字符字段。
使用 Statements 而不是 PreparedStatements 并将过滤器重新排列为如下所示,与我问题中的形式相反,实际上似乎使 SQL 服务器使用索引:
SELECT TOP 100 * FROM PALISBSD
WHERE
(recbsd_key_bsd_key_bsd1_bsd_jar < '03') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro < 'L') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst < 'C') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl < '00017004') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr < '0001') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr = '0001' AND recbsd_key_bsd_key_bsd1r_bsd_sa < 'D') OR
(recbsd_key_bsd_key_bsd1_bsd_jar = '03' AND recbsd_key_bsd_key_bsd1_bsd_pro = 'L' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C' AND recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004' AND recbsd_key_bsd_key_bsd1_bsd_linr = '0001' AND recbsd_key_bsd_key_bsd1r_bsd_sa = 'D' AND recbsd_key_bsd_key_bsd1r_bsd_an < 'PTZ')
ORDER BY
recbsd_key_bsd_key_bsd1_bsd_jar DESC,
recbsd_key_bsd_key_bsd1_bsd_pro DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl DESC,
recbsd_key_bsd_key_bsd1_bsd_linr DESC,
recbsd_key_bsd_key_bsd1r_bsd_sa DESC,
recbsd_key_bsd_key_bsd1r_bsd_an DESC;
我知道 SQL 注射,我正在以其他方式阻止它们。