PostgreSQL中的模式匹配和正则表达式 - Das


在本文中,我将讨论 PostgreSQL 中的模式匹配和正则表达式。
编写查询的一个重要方面是用户应该能够过滤和选择系统需要访问的数据。额外的或不必要的数据会增加带宽并降低查询的性能。因此,SQL 提供了一个过滤谓词“WHERE”,用户可以使用它过滤查询并选择仅匹配过滤谓词的结果。
 
PostgreSQL 中的正则表达式
在正常的 SQL 操作的情况下,LIKE 运算符很好,但是在过滤大型数据库时,LIKE 运算符似乎存在一些性能问题。此外,使用 LIKE 运算符的过滤条件仅限于通过包含通配符 (%) 来查找模式。
为了克服这个问题,PostgreSQL 提供了一种使用正则表达式进行模式匹配的高级方法。长期以来,正则表达式在编程语言中被大量使用,然而,在 SQL 语句中使用这些正则表达式,使得查询高度动态化,并且在大型数据库中表现更好。
PostgreSQL 中的正则表达式是使用 TILDE ( ~ ) 运算符实现的,并使用 '.* ”作为通配符运算符。

SELECT * from GreaterManchesterCrime WHERE CrimeID = '^.*$';

正如你看到的,我们在PostgreSQL中使用了正则表达式,使用了TILDE(~)运算符和通配符'.*'。这个查询将从GreaterManchesterCrime表中选择所有具有有效CrimeID的记录。由于模式条件只是通配符,它将从表中获取所有记录。
另外,在PostgreSQL中编写正则表达式时需要注意的另一点是,模式匹配语句总是以"^"运算符开始,以"$"符号结束。这两个运算符标志着正则表达式语句的开始和结束。总结一下图,在使用通配符过滤所有记录时,表达式可以实现为"^.*$"。
 
正则表达式 - 以数字或字符开头的字符串
在上一节中,我们已经学会了如何通过使用通配符来实现正则表达式。现在,我们将向前迈进一步,尝试为列CrimeID获取以字符或数字开头的记录。
在PostgreSQL中,可以使用"[a-z]"或"[A-Z]"模式来匹配字母数字字符,这取决于我们试图匹配的情况。这里需要注意的一点是,由于PostgreSQL是区分大小写的,因此,必须在模式中指定我们要匹配的确切大小写。
同样地,对于匹配数字,我们可以使用"[0-9]"或"/d"。现在我们对使用Regex过滤字符和数字有了一些了解,让我们继续在数据库中实现它。
对于匹配的字符 -
SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[AZ].*$'

CrimeID 字段已被过滤,仅包含 ID 以大写字母开头的记录。请注意这里再次使用通配符“ .* ”来表示 SQL 语句中第一个字符之后的任何内容。
要过滤语句中的数字,我们可以简单地编写如下查询:

SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[0–9].*$'

只有以数字开头的CrimeID的记录被过滤以匹配正则表达式条件。
 
 

正则表达式——以重复数字或字符开头的字符串
在本文的前一节中,我们已经了解了如何在 PostgreSQL 中使用正则表达式语法编写 SQL 查询,以及如何在被过滤的字符串的第一个位置过滤字符和数字。
现在,让我们为要求添加一些更复杂的内容,并过滤开头以多个字符或数字开头的记录。PostgreSQL 只需在花括号内提供计数,就可以非常容易地指定重复次数。或者,您也可以多次重复相同的字符模式匹配以匹配您的条件。例如,我们想过滤所有以两个字符开头的记录。这个查询可以写成如下。
SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[AZ] [AZ].*$'

或者

SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[AZ] {2}.*$'

我们使用花括号中的数字来表示在列中查找模式的次数。这使得查询非常动态,因为您可以指定要在查询中搜索的任意数量的字符,您将获得结果。
同样,您也可以为重复数值实现相同的逻辑。在这种情况下,查询可以编写如下。

SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[0–9]{2}.*$'

这展示了在过滤重复数值的同时使用正则表达式进行模式匹配的实现。
 
正则表达式——以字符和数字开头的字符串
在本文的最后一部分中,我们将结合到目前为止所看到的内容。我们将构建查询并匹配将过滤以字符开头并后跟数字的记录的模式。要形成本规范的查询,您可以在正则表达式中组合字母和数字字符的条件。SQL 语句可以写成如下。
SELECT * FROM GreaterManchesterCrime WHERE CrimeID ~ '^[AZ][0–9].*$'