在 Oracle IN 子句中使用 LIKE

发布于 2024-11-08 06:13:34 字数 562 浏览 0 评论 0 原文

我知道我可以编写一个查询,该查询将返回给定列中包含任意数量值的所有行,如下所示:

Select * from tbl where my_col in (val1, val2, val3,... valn)

但是,例如,如果 val1 可以出现在 my_col 中的任何位置code>,其数据类型为 varchar(300),我可能会写:

select * from tbl where my_col LIKE '%val1%'

有没有办法结合这两种技术。我需要搜索大约 30 个可能出现在该列的自由格式文本中任何位置的值。

通过以下方式组合这两个语句似乎不起作用:

select * from tbl where my_col LIKE ('%val1%', '%val2%', 'val3%',....) 

select * from tbl where my_col in ('%val1%', '%val2%', 'val3%',....)

I know I can write a query that will return all rows that contain any number of values in a given column, like so:

Select * from tbl where my_col in (val1, val2, val3,... valn)

but if val1, for example, can appear anywhere in my_col, which has datatype varchar(300), I might instead write:

select * from tbl where my_col LIKE '%val1%'

Is there a way of combing these two techniques. I need to search for some 30 possible values that may appear anywhere in the free-form text of the column.

Combining these two statements in the following ways does not seem to work:

select * from tbl where my_col LIKE ('%val1%', '%val2%', 'val3%',....) 

select * from tbl where my_col in ('%val1%', '%val2%', 'val3%',....)

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

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

发布评论

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

评论(11

离笑几人歌 2024-11-15 06:13:34

这里有用的是 a LIKE PostgreSQL 中可用的任何 谓词

SELECT * 
FROM tbl
WHERE my_col LIKE ANY (ARRAY['%val1%', '%val2%', '%val3%', ...])

不幸的是,该语法在 Oracle 中不可用。但是,您可以使用 OR 扩展量化比较谓词:

SELECT * 
FROM tbl
WHERE my_col LIKE '%val1%' OR my_col LIKE '%val2%' OR my_col LIKE '%val3%', ...

或者,使用 EXISTS 谓词和 辅助数组数据结构(详细信息请参阅此问题)

SELECT *
FROM tbl t
WHERE EXISTS (
  SELECT 1
  -- Alternatively, store those values in a temp table:
  FROM TABLE (sys.ora_mining_varchar2_nt('%val1%', '%val2%', '%val3%'/*, ...*/))
  WHERE t.my_col LIKE column_value
)

对于真正的全文搜索,您可能需要查看 Oracle Text:http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html< /a>

What would be useful here would be a LIKE ANY predicate as is available in PostgreSQL

SELECT * 
FROM tbl
WHERE my_col LIKE ANY (ARRAY['%val1%', '%val2%', '%val3%', ...])

Unfortunately, that syntax is not available in Oracle. You can expand the quantified comparison predicate using OR, however:

SELECT * 
FROM tbl
WHERE my_col LIKE '%val1%' OR my_col LIKE '%val2%' OR my_col LIKE '%val3%', ...

Or alternatively, create a semi join using an EXISTS predicate and an auxiliary array data structure (see this question for details):

SELECT *
FROM tbl t
WHERE EXISTS (
  SELECT 1
  -- Alternatively, store those values in a temp table:
  FROM TABLE (sys.ora_mining_varchar2_nt('%val1%', '%val2%', '%val3%'/*, ...*/))
  WHERE t.my_col LIKE column_value
)

For true full-text search, you might want to look at Oracle Text: http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html

渔村楼浪 2024-11-15 06:13:34

REGEXP_LIKE 将执行不区分大小写的正则表达式搜索。

select * from Users where Regexp_Like (User_Name, 'karl|anders|leif','i')

这将作为全表扫描执行 - 就像LIKE或解决方案一样,因此如果表不存在,性能将非常很糟糕小的。如果不经常使用的话可能还好。

如果您需要某种性能,则需要 Oracle Text(或某些外部索引器)。

要使用 Oracle Text 获取子字符串索引,您将需要 CONTEXT 索引。它有点复杂,因为它是为了使用大量智能来索引大型文档和文本而设计的。如果您有特殊需求,例如数字和所有单词中的子字符串搜索(包括“the”“an”“a”,空格等),您需要创建自定义词法分析器来删除一些智能内容...

如果您插入大量数据时,Oracle Text 不会使事情变得更快,特别是如果您需要在事务内更新索引而不是定期更新索引。

A REGEXP_LIKE will do a case-insensitive regexp search.

select * from Users where Regexp_Like (User_Name, 'karl|anders|leif','i')

This will be executed as a full table scan - just as the LIKE or solution, so the performance will be really bad if the table is not small. If it's not used often at all, it might be ok.

If you need some kind of performance, you will need Oracle Text (or some external indexer).

To get substring indexing with Oracle Text you will need a CONTEXT index. It's a bit involved as it's made for indexing large documents and text using a lot of smarts. If you have particular needs, such as substring searches in numbers and all words (including "the" "an" "a", spaces, etc) , you need to create custom lexers to remove some of the smart stuff...

If you insert a lot of data, Oracle Text will not make things faster, especially if you need the index to be updated within the transactions and not periodically.

海未深 2024-11-15 06:13:34

不,你不能这样做。 IN 子句中的值必须完全匹配。您可以这样修改选择:

SELECT *
  FROM tbl
 WHERE my_col LIKE %val1%
    OR my_col LIKE %val2%
    OR my_col LIKE %val3%
 ...

如果 val1、val2、val3...足够相似,您也许可以在 REGEXP_LIKE 运算符中使用正则表达式。

No, you cannot do this. The values in the IN clause must be exact matches. You could modify the select thusly:

SELECT *
  FROM tbl
 WHERE my_col LIKE %val1%
    OR my_col LIKE %val2%
    OR my_col LIKE %val3%
 ...

If the val1, val2, val3... are similar enough, you might be able to use regular expressions in the REGEXP_LIKE operator.

一百个冬季 2024-11-15 06:13:34

在 Oracle 中,您可以按如下方式使用 regexp_like:

select *
from   table_name
where  regexp_like (name, '^(value-1|value-2|value-3....)');

插入符 (^) 运算符表示行首字符 &
管道符(|) 表示OR 运算。

In Oracle you can use regexp_like as follows:

select *
from   table_name
where  regexp_like (name, '^(value-1|value-2|value-3....)');

The caret (^) operator to indicate a beginning-of-line character &
The pipe (|) operator to indicate OR operation.

时光倒影 2024-11-15 06:13:34

是的,您可以使用此查询(代替 'Specialist''Developer',输入您想要用逗号分隔的任何字符串,然后更改 employees表与您的表)

SELECT * FROM employees em
WHERE EXISTS (select 1 from  table(sys.dbms_debug_vc2coll('Specialist', 'Developer')) mt  
              where em.job like ('%' || mt.column_value || '%'));

为什么我的查询比接受的答案更好:您不需要 CREATE TABLE 权限来运行它。只需使用 SELECT 权限即可执行此操作。

Yes, you can use this query (Instead of 'Specialist' and 'Developer', type any strings you want separated by comma and change employees table with your table)

SELECT * FROM employees em
WHERE EXISTS (select 1 from  table(sys.dbms_debug_vc2coll('Specialist', 'Developer')) mt  
              where em.job like ('%' || mt.column_value || '%'));

Why my query is better than the accepted answer: You don't need a CREATE TABLE permission to run it. This can be executed with just SELECT permissions.

难如初 2024-11-15 06:13:34

这个速度相当快:

select * from listofvalue l 
inner join tbl on tbl.mycol like '%' || l.value || '%'

This one is pretty fast :

select * from listofvalue l 
inner join tbl on tbl.mycol like '%' || l.value || '%'
柠檬色的秋千 2024-11-15 06:13:34

只是添加@Lukas Eder 的答案。

避免创建表和插入值的改进
(我们可以使用 select from Dualunpivot 来“即时”实现相同的结果):

with all_likes as  
(select * from 
    (select '%val1%' like_1, '%val2%' like_2, '%val3%' like_3, '%val4%' as like_4, '%val5%' as like_5 from dual)
    unpivot (
     united_columns for subquery_column in ("LIKE_1", "LIKE_2", "LIKE_3", "LIKE_4", "LIKE_5"))
  )
    select * from tbl
    where exists (select 1 from all_likes where tbl.my_col like all_likes.united_columns)

Just to add on @Lukas Eder answer.

An improvement to avoid creating tables and inserting values
(we could use select from dual and unpivot to achieve the same result "on the fly"):

with all_likes as  
(select * from 
    (select '%val1%' like_1, '%val2%' like_2, '%val3%' like_3, '%val4%' as like_4, '%val5%' as like_5 from dual)
    unpivot (
     united_columns for subquery_column in ("LIKE_1", "LIKE_2", "LIKE_3", "LIKE_4", "LIKE_5"))
  )
    select * from tbl
    where exists (select 1 from all_likes where tbl.my_col like all_likes.united_columns)
澉约 2024-11-15 06:13:34

我更喜欢这个,

WHERE CASE WHEN my_col LIKE '%val1%' THEN 1    
           WHEN my_col LIKE '%val2%' THEN 1
           WHEN my_col LIKE '%val3%' THEN 1
           ELSE 0
           END = 1

我并不是说它是最佳的,但它有效并且很容易理解。我的大多数查询都是临时使用一次,因此性能对我来说通常不是问题。

I prefer this

WHERE CASE WHEN my_col LIKE '%val1%' THEN 1    
           WHEN my_col LIKE '%val2%' THEN 1
           WHEN my_col LIKE '%val3%' THEN 1
           ELSE 0
           END = 1

I'm not saying it's optimal but it works and it's easily understood. Most of my queries are adhoc used once so performance is generally not an issue for me.

命硬 2024-11-15 06:13:34

您可以将值放入 ODCIVARCHAR2LIST 中,然后将其作为常规表连接。

select tabl1.* FROM tabl1 LEFT JOIN 
(select column_value txt from table(sys.ODCIVARCHAR2LIST
('%val1%','%val2%','%val3%')
)) Vals ON tabl1.column LIKE Vals.txt WHERE Vals.txt IS NOT NULL

You can put your values in ODCIVARCHAR2LIST and then join it as a regular table.

select tabl1.* FROM tabl1 LEFT JOIN 
(select column_value txt from table(sys.ODCIVARCHAR2LIST
('%val1%','%val2%','%val3%')
)) Vals ON tabl1.column LIKE Vals.txt WHERE Vals.txt IS NOT NULL
爱人如己 2024-11-15 06:13:34
select * from tbl
 where exists (select 1 from all_likes where all_likes.value = substr(tbl.my_col,0, length(tbl.my_col)))
select * from tbl
 where exists (select 1 from all_likes where all_likes.value = substr(tbl.my_col,0, length(tbl.my_col)))
小…楫夜泊 2024-11-15 06:13:34

您不需要 https://stackoverflow.com/a/6074261/802058 中提到的集合类型。只需使用子查询:

SELECT *
FROM tbl t
WHERE EXISTS (
    SELECT 1
    FROM (
        SELECT 'val1%' AS val FROM dual
        UNION ALL
        SELECT 'val2%' AS val FROM dual
        -- ...
        -- or simply use an subquery here
    )
    WHERE t.my_col LIKE val
)

You don't need a collection type as mentioned in https://stackoverflow.com/a/6074261/802058. Just use an subquery:

SELECT *
FROM tbl t
WHERE EXISTS (
    SELECT 1
    FROM (
        SELECT 'val1%' AS val FROM dual
        UNION ALL
        SELECT 'val2%' AS val FROM dual
        -- ...
        -- or simply use an subquery here
    )
    WHERE t.my_col LIKE val
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文