在Oracle IN子句中使用LIKE

时间:2011-05-20 15:31:28

标签: sql oracle sql-like

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

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

但是,例如val1可以出现在my_col中的任何位置,其数据类型为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%',....)

11 个答案:

答案 0 :(得分:25)

select * from tbl 
where my_col like '%val1%' or my_col like'%val2%' or my_col like '%val3%', ...

但要注意,这可能会很慢......或者,您可以将所有可接受的值(包括%符号)插入表中并半连接该表:

select * from tbl
where exists (select 1 from all_likes where tbl.my_col like all_likes.value)

对于真正的全文搜索,您可能需要查看Oracle Text:

http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html

答案 1 :(得分:6)

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

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

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

答案 2 :(得分:4)

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

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

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

答案 3 :(得分:3)

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

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

这将作为全表扫描执行 - 就像LIKE or解决方案一样,如果表格不小,性能将真的不好。如果它根本不经常使用,那可能没问题。

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

要使用Oracle Text获取子字符串索引,您需要一个CONTEXT索引。它有点牵扯,因为它是使用大量智能索引大型文档和文本。如果您有特殊需求,例如子串搜索数字和所有单词(包括""""" a",空格等),您需要创建自定义词法分析器以删除一些聪明的东西...

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

答案 4 :(得分:1)

是的,您可以使用此查询:

  SELECT * FROM RandomTable rt 
    WHERE EXISTS (select 1 from table(sys.dbms_debug_vc2coll(//INSERT STRINGS SEPARATED BY COMMA HERE)) as MemoryTable mt where rt.name like mt.column_value);

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

答案 5 :(得分:1)

添加@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)

答案 6 :(得分:1)

我更喜欢这个

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

我并不是说它是最佳的,但它有效,而且很容易理解。我的大多数查询都是adhoc一次使用,所以性能通常不是我的问题。

答案 7 :(得分:1)

这个非常快:

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

答案 8 :(得分:1)

您可以将值放入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

答案 9 :(得分:0)

select * from tbl
 where exists (select 1 from all_likes where all_likes.value = substr(tbl.my_col,0, length(tbl.my_col)))

答案 10 :(得分:0)

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

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*

@Serializable(with = PacketSerializer::class)
data class Packet(val dataType: String, val payload: Any)

object PacketSerializer : KSerializer<Packet> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Packet") {
        element("dataType", serialDescriptor<String>())
        element("payload", buildClassSerialDescriptor("Any"))
    }

    @Suppress("UNCHECKED_CAST")
    private val dataTypeSerializers: Map<String, KSerializer<Any>> =
        mapOf(
            "String" to serializer<String>(),
            "Int" to serializer<Int>(),
            //list them all
        ).mapValues { (_, v) -> v as KSerializer<Any> }

    private fun getPayloadSerializer(dataType: String): KSerializer<Any> = dataTypeSerializers[dataType]
        ?: throw SerializationException("Serializer for class $dataType is not registered in PacketSerializer")

    override fun serialize(encoder: Encoder, value: Packet) {
        encoder.encodeStructure(descriptor) {
            encodeStringElement(descriptor, 0, value.dataType)
            encodeSerializableElement(descriptor, 1, getPayloadSerializer(value.dataType), value.payload)
        }
    }

    @ExperimentalSerializationApi
    override fun deserialize(decoder: Decoder): Packet = decoder.decodeStructure(descriptor) {
        if (decodeSequentially()) {
            val dataType = decodeStringElement(descriptor, 0)
            val payload = decodeSerializableElement(descriptor, 1, getPayloadSerializer(dataType))
            Packet(dataType, payload)
        } else {
            require(decodeElementIndex(descriptor) == 0) { "dataType field should precede payload field" }
            val dataType = decodeStringElement(descriptor, 0)
            val payload = when (val index = decodeElementIndex(descriptor)) {
                1 -> decodeSerializableElement(descriptor, 1, getPayloadSerializer(dataType))
                CompositeDecoder.DECODE_DONE -> throw SerializationException("payload field is missing")
                else -> error("Unexpected index: $index")
            }
            Packet(dataType, payload)
        }
    }
}