【问题标题】:Searching a Oracle table for a value在 Oracle 表中搜索值
【发布时间】:2017-01-12 21:36:30
【问题描述】:

我有一个包含近 15 万条记录和 65 列的 Oracle 表。我的客户要求他们需要使用单个搜索值搜索整个表,并且也可以是通配符搜索。

最糟糕的是,我正在使用 php 语言来做到这一点。

所以我构建了一个包含所有 65 列的查询来搜索单个字符串值。

示例查询:

SELECT * FROM <TABLE_NAME>
WHERE (col1 || col2 || col3 ... || col65) LIKE '%<SEARCH_VALUE>%'

查询正在为某些字段提供输出,如果我们传递一些与地址相关的字段,有时它会失败。

在某些情况下,尤其是通配符类型搜索并且输出超过 1000 行时。

我已经使用 php 语言完成了这些测试。但同时当我尝试使用 SQL Developer 执行查询时。它一直在给出结果。所以我很困惑。

除了我试图访问的 Oracle 服务器之外,还有一个外部服务器,它不在我们的环境中。

请建议我如何实现此功能或想法,我非常感谢您的助手。

【问题讨论】:

  • 如果您不使用通配符,我认为您可以使用WHERE :search IN (col1, col2, col3, ..., col65)。对于通配符,我认为您需要另一种方法。

标签: php sql oracle


【解决方案1】:

如果您使用的是 Oracle 11g,您可以在表中添加一个虚拟列

ALTER TABLE <TABLE_NAME> ADD
SEARCH_COLUMN GENERATED ALWAYS AS (col1 || ' ' || col2 || ' ' || col3 ... ||   col65);

然后在新创建的虚拟列上创建索引。该索引将存储所有 65 列的串联字符串值。您不必更改应用程序中的任何查询,因为 Oracle 会自动使用其他 65 列的值计算虚拟列的值。

然后您可以只使用索引虚拟列进行搜索

SELECT * FROM <TABLE_NAME>
WHERE SEARCH_COLUMN LIKE '%<SEARCH_VALUE>%'

【讨论】:

    【解决方案2】:

    这看起来是一个非常糟糕的设计。想到的一个问题如下例所示

    col1   col2
    ===========
    ABC    DEF
    CDX    ZZZ
    

    如果您的搜索条件是“CD”,则这两行都会匹配,因为您正在搜索所有列的串联。

    【讨论】:

      【解决方案3】:

      我正在使用这个技巧跨列搜索而且我知道解决方案很慢。

      create table test_example as  select * from user_objects where rownum <= 1000;
      
      select t2.* from 
       xmltable('for $i in ora:view("test_example")/ROW
                 where fn:exists($i/*[contains(.,$var_text_to_serach)])
                 return $i' passing 'change_here' as "var_text_to_serach" columns id varchar(100) path 'OBJECT_ID') t1
           join test_example t2 on t1.id  = t2. OBJECT_ID
      ;
      

      ora:view - 允许在 xquery 表达式中查询表。函数从表行创建 xml-s。

      xmltable - 允许将 xquery-xml 结果映射到关系模型。

      FLWOR expresion - 在 xmltable 中,我使用的是 FLWOR expresion,它是 FOR、LET、WHERE、ORDER、RETURN 的首字母缩写

      fn:exists($i/*[contains(.,$var_text_to_serach)]) - 检查是否有任何列包含模式。

      columns id varchar(100) path 'OBJECT_ID' 从 XML 中提取 id 列。在我的示例中,OBJECT_ID 是表中的唯一值。

      passing 'change_here' as "var_text_to_serach" - “change_here”是要搜索的文本

      要使用此示例,您必须将 test_example 更改为您的表,并注意连接条件和 .

      【讨论】:

        【解决方案4】:

        考虑使用用户定义的数据存储在所有列上创建文本索引,然后使用包含运算符进行搜索..

        这样的事情

         begin
           begin
             ctx_ddl.drop_preference('mymcds');
           exception
             when others then
             null;
          end;
          ctx_ddl.create_preference('mymcds', 'multi_column_datastore');
          ctx_ddl.set_attribute('mymcds', 'columns', 'NAME, POI_STREET_NAME,    
                                                      POI_CITY, POI_POSTCODE, ACTUAL_ADDRESS');
        end;
        /
        create index ADDRESS_SEARCH_IDX 
                 on MAP_POI(NAME)
                    indextype is ctxsys.context
                    parameters ('datastore mymcds section group     ctxsys.auto_section_group')
        /
        

        使用 contains(NAME,'Foo') 的搜索应该搜索所有被索引的列。

        【讨论】:

          猜你喜欢
          • 2020-08-21
          • 1970-01-01
          • 1970-01-01
          • 2021-10-13
          • 2018-07-11
          • 1970-01-01
          • 2021-07-23
          相关资源
          最近更新 更多