Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQLServer从匹配模式的字符串特定单词中进行选择_Sql Server_Regex - Fatal编程技术网

Sql server SQLServer从匹配模式的字符串特定单词中进行选择

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]

我有一个小问题:

具有类似于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]%', [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似乎需要是标量变量,因为它似乎无法直接通过变量传递多行将它更改为表变量,因此它可以实际保存更多行。您可以考虑从代码中创建存储过程,并在选择语句中为每一行调用它。