13

在我的 SQL 语句中,我必须从字符“_”处的字符串中提取子字符串。例如,字符串可以是“A_XXX”“AB_XXX”“ABC_XXXX”,因此提取的子字符串应该类似于“A”“AB”“ABC”。

在 Oracle 中,这很容易使用 substr() 和 instr() 函数:

select substr('AB_XXX', 1, instr('AB_XXX', '_')-1) as substring
from dual;

结果将是:

SUBSTRING
------------------------
AB

我需要这个查询来检查一个特定的子字符串是否在一个字符串数组中。

整个查询看起来像:

select 'AB_XXX' from dual
where (instr('ABC_AB_A', substr('AB_XXX', 1, instr('AB_XXX', '_')-1))>0);

有没有办法用 SQL 标准编写它?

在此先感谢您的帮助。

编辑:

如果 PostgreSQL 提供了替代功能,它也会有所帮助。其余的可以用例如 IN 来解决。真正重要的部分是获取子字符串。

4

3 回答 3

28

您的第二个示例有点令人困惑,因为您正在混合'ABC_AB_A'并且'AB_XXX'不确定这是否是错字。

但是,如果您只想要第一个之前的所有字符,_那么在 Postgres 中可以使用以下方法:

left(col, strpos(col, '_') - 1)

或使用正则表达式:

substring(col from '([A-Z]+)(_{1})')

您也可以在 Oracle 中使用正则表达式:

regexp_substr(col, '([A-Z]+)(_{1})', 1, 1, 'i', 1)

Postgres 的substring函数总是返回正则表达式的第一个捕获组,而在 Oracle 中,您可以指定所需的组:这是regexp_substr()函数的最后一个参数。

用于 Oracle 的 SQLFiddle:http
: //sqlfiddle.com/#!4/b138c/1 用于 Postgres的 SQLFiddle: http ://sqlfiddle.com/#!15/4b2bb/1

于 2015-04-27T13:15:21.663 回答
26

tl;博士

split_part专门为此而设计的用途:

split_part(string, '_', 1)

解释

引用此API 文档

SPLIT_PART()函数在指定的分隔符处拆分字符串并返回第 n 个子字符串。

3 个参数分别是要拆分的字符串、分隔符和要返回的部分/子字符串编号(从 1 开始)。

因此,如果您有一个名为的字段string,其中包含类似的内容AB_XXX,并且您想获取之前的所有内容_,那么您可以将其拆分并获取第一部分/子字符串:split_part(string, '_', 1)

于 2019-06-13T19:49:43.667 回答
4

标准 SQL 字符串函数在: SQL 字符串函数和运算符中进行了描述。

有一个substring函数可以直接提取内容,而无需嵌套函数调用。它在模式匹配中详细描述为:

具有三个参数的子字符串函数substring(string from pattern for escape-character)提供与 SQL 正则表达式模式匹配的子字符串的提取。与 SIMILAR TO 一样,指定的模式必须匹配整个数据字符串,否则函数将失败并返回 null。为了指示成功时应返回的模式部分,模式必须包含两次出现的转义字符,后跟双引号 (")。返回与这些标记之间的模式部分匹配的文本。

在你的情况下:

select substring('AB_XX' from '#"%#"#_%' for '#');

结果:

子串
------------
 AB
(1 行)

语法有点奇怪,特别是因为_它是单个字符的通配符,所以它必须被引用,但它是 SQL 标准。

对于更多人使用的语法,请考虑regexp_replace()使用 POSIX 正则表达式或类似的函数。

于 2015-04-27T13:24:11.360 回答