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 注射,我正在以其他方式阻止它们。