Sql server SQLServer从匹配模式的字符串特定单词中进行选择
我有一个小问题: 具有类似于id、标题、文本的表格以及类似于2132-12-42垃圾箱2130-10-21垃圾箱等的文本数据 我试图实现的是仅从文本列中选择日期,即:Sql server SQLServer从匹配模式的字符串特定单词中进行选择,sql-server,regex,Sql Server,Regex,我有一个小问题: 具有类似于id、标题、文本的表格以及类似于2132-12-42垃圾箱2130-10-21垃圾箱等的文本数据 我试图实现的是仅从文本列中选择日期,即: [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 到目前为止,我成功地列出了没有剩余字符串的日期。。但只有第一次约会: SELECT *, SUBSTRING([text],NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
到目前为止,我成功地列出了没有剩余字符串的日期。。但只有第一次约会:
SELECT *,
SUBSTRING([text],NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', [text]),0),10) AS [date]
FROM table
因此,在[date]列中提供的示例中,它将显示2132-12-42,但不会显示2130-10-21
有没有办法选择所有匹配模式的单词而不仅仅是第一个
我正在使用Sql Server 2012。此代码根据您的模式从给定字符串中选择所有日期:
DECLARE @IND INT
DECLARE @Str NVARCHAR(MAX)
SET @Str = '2132-12-42 trash trash 2130-10-21 trash trash'
SET @IND = PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Str)
WHILE(@IND > 0)
BEGIN
SELECT SUBSTRING(@Str, @IND, 10)
SET @Str = SUBSTRING(@Str, @IND+11, LEN(@Str))
SET @IND = PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Str)
END
下面是一个使用递归公共表表达式从所有行中获取所有日期的示例:
DECLARE @table TABLE(id INT, title NVARCHAR(255), [text] NVARCHAR(MAX))
INSERT @table
( id, title, [text] ) VALUES
( 1, 'test_1', '2132-12-22 blah blah blah some thing else 2130-10-21 something else etc 2010-05-06'),
( 2, 'test_2', 'blasdasdasdasda asdasdasd asdasdasd'),
( 3, 'test_3', 'blasdasdasdasda 2013-06-07 2015-01-01 asdasdasd asdasdasd')
;WITH cte AS
(
SELECT id, title, [text],
SUBSTRING([text],NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', [text]),0),10) AS [date],
SUBSTRING([text],NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', [text]),0)+10,LEN([text])) AS [rest],
1 AS dateNum
FROM @table
WHERE PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', [text]) > 0
UNION ALL
SELECT id, title, [text],
SUBSTRING(rest,NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', rest),0),10) AS [date],
SUBSTRING(rest,NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', rest),0)+10,LEN(rest)) AS [rest],
dateNum + 1 AS dateNum
FROM cte
WHERE PATINDEX('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', rest) > 0
)
SELECT id, title , [date], dateNum, [text] FROM cte
正如您可以看到的,它几乎是您的原始查询,但它只是跟踪每个迭代的剩余部分,以及剩余部分中的查询
就我所知,似乎工作正常
结果:
id title date dateNum text
1 test_1 2132-12-22 1 2132-12-22 blah blah blah some thing else 2130-10-21 something else etc 2010-05-06
3 test_3 2013-06-07 1 blasdasdasdasda 2013-06-07 2015-01-01 asdasdasd asdasdasd
3 test_3 2015-01-01 2 blasdasdasdasda 2013-06-07 2015-01-01 asdasdasd asdasdasd
1 test_1 2130-10-21 2 2132-12-22 blah blah blah some thing else 2130-10-21 something else etc 2010-05-06
1 test_1 2010-05-06 3 2132-12-22 blah blah blah some thing else 2130-10-21 something else etc 2010-05-06
在您的子字符串中,您要求从模式的开头仅选择10个符号。是的,它确实工作得很好,谢谢,但是有没有办法修改它,以便它从表中的行中获取数据而不是定义的字符串?从表文章和列[文本]例如,使用动态SQL,例如SET@Str=SELECT text FROM articles WHERE expression您可能可以通过使用递归公共表表达式从表中选择所有日期。虽然尝试过,但子字符串和PATINDEX中的@Str似乎需要是标量变量,因为它似乎无法直接通过变量传递多行将它更改为表变量,因此它可以实际保存更多行。您可以考虑从代码中创建存储过程,并在选择语句中为每一行调用它。