【问题标题】:Compare Strings in Oracle在 Oracle 中比较字符串
【发布时间】:2010-09-28 05:17:16
【问题描述】:

我需要在一个表中查询给定字符串的值。该表区分大小写,但我想在比较中执行 ToLower()。

假设我有一个包含以下数据的类表。

class    teacher
-----------------
Mat101   Smith
MAT101   Jones
mat101   Abram
ENG102   Smith

我的查询应该是这样的

Select teacher From classes where lower(class) = 'math101'

这是进行比较的最佳方式吗?

更新

我无法控制数据库或数据。我是只读消费者。

【问题讨论】:

    标签: sql oracle comparison


    【解决方案1】:

    您所说的这种查询的缺点是它不能在类上使用索引(作为索引查找,也就是说,它仍然可以用于索引的快速全扫描)。

    不过,在现代版本的 Oracle 中,您可以在 LOWER(class) 上创建一个索引,然后该查询可以使用该索引。

    【讨论】:

      【解决方案2】:

      这里是关于基于函数的索引的更多信息(Dave 上面提到的):

      【讨论】:

        【解决方案3】:

        没有;改进数据会更好:创建一个数字 ID 来表示这些看似无意义的类变体(可能还有一个关联的查找表来获取 ID)。在 where 子句中使用 ID 列,您应该会点击索引数字列。

        如果这不是一个选项,请考虑在 lower(class) 上使用基于函数的索引。

        如果这不是一个选项,并且“最佳”问题与性能严格相关,请考虑非规范化并添加一个包含 lower(class) 的列,可能填充有触发器。

        如果这不是一个选项,请更新数据,使其全部为小写(并采取措施仅插入/更新小写类数据)。

        如果你不能像那样更新数据,那么答案是“也许”。

        无论如何,如果您还没有测试过列的索引,就不能称之为最佳。

        【讨论】:

          【解决方案4】:

          此方法要求您运行 10gr2 或更高版本。

          更改会话之前:

          SQL> WITH LETTERS AS
            2  (SELECT 'a' LETTER FROM DUAL UNION ALL
            3   SELECT 'b' LETTER FROM DUAL UNION ALL
            4   SELECT 'A' LETTER FROM DUAL UNION ALL
            5   SELECT 'B' LETTER FROM DUAL) 
            6  SELECT LETTER FROM LETTERS 
            7  WHERE LETTER = 'A';
          
          L
          -
          A
          
          SQL> 
          

          如果您能够更改会话,则可以执行以下操作:

          SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;
          
          Session altered.
          
          SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;
          
          Session altered.
          
          SQL> WITH LETTERS AS
            2  (SELECT 'a' LETTER FROM DUAL UNION ALL
            3   SELECT 'b' LETTER FROM DUAL UNION ALL
            4   SELECT 'A' LETTER FROM DUAL UNION ALL
            5   SELECT 'B' LETTER FROM DUAL) 
            6  SELECT LETTER FROM LETTERS 
            7  WHERE LETTER = 'A';
          
          L
          -
          a
          A
          

          如上所述更改会话会导致数据库对相同字母的大写和小写版本作为等效对象进行排序和比较。更多信息请见http://www.orafaq.com/node/91

          HTH, 加布

          【讨论】:

          【解决方案5】:

          如果变体(Mat101、MAT101、mat101)引用相同的东西,它们应该具有相同的标识符。

          根据数据量、更新频率、查询等,您可以考虑将数据复制到您通过复制中内置的清理/标准化阶段控制的数据库中。

          虽然您说“我无法控制数据库”,但如果您可以查询,您将对数据库产生影响。有人控制了数据库,可能值得通过电子邮件/电话说,如果他们向该列添加 lower() 索引,那么它将减少您的查询对数据库的影响。

          最后,如果变体足够简单,那么您可以尝试

          Select teacher From classes where class in (lower('mat101'), upper('mat101'), initcap('mat1010')). 
          

          【讨论】:

            【解决方案6】:

            由于您添加了您是数据库的只读用户,因此最佳方法与您开始使用的方法接近:

            Select teacher From classes where lower(class) = LOWER('math101')
            

            请注意,我在输入参数中添加了 LOWER(),只是为了确保它也是小写的。有些人可能称之为“腰带和吊带”(又名redudant);我称之为良好的防御性编程。

            【讨论】:

              猜你喜欢
              • 2015-06-17
              • 2015-11-19
              • 2017-06-05
              • 1970-01-01
              • 2023-03-10
              • 2013-10-24
              • 1970-01-01
              • 1970-01-01
              • 2010-12-04
              相关资源
              最近更新 更多