Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.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
如何基于模式拆分文本值,并使用TSQL在表中返回结果_Sql_Sql Server_Tsql - Fatal编程技术网

如何基于模式拆分文本值,并使用TSQL在表中返回结果

如何基于模式拆分文本值,并使用TSQL在表中返回结果,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有这个字符串,它存储在一个文本字段中。此后,存储此信息的过程发生了变化,但我需要这些遗留信息 23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1. 05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off. 05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off

我有这个字符串,它存储在一个文本字段中。此后,存储此信息的过程发生了变化,但我需要这些遗留信息

23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
如何按日期字段将文本拆分为结果表,以便为每个新日期显示包含日期的新行。那么在上面的例子中,会有6行吗

这就是我提出的概念证明:

DECLARE @MEMO VARCHAR(MAX)
    SET @MEMO = '23.06.17 test 1 24.06.17 test 2 25.06.17 test 3'

DECLARE @COUNTER INT
    SET @COUNTER=0

DECLARE @WORD VARCHAR(40)
    SET @WORD = ''

DECLARE @DATE VARCHAR(10)
    SET @DATE = ''

DECLARE @LINE VARCHAR(500)
    SET @LINE = ''

WHILE @COUNTER <= LEN(@MEMO)+1 BEGIN
    IF SUBSTRING(@MEMO, @COUNTER, 1) != ' ' BEGIN
        --Builds each character into a string.
        SET @WORD = @WORD + SUBSTRING(@MEMO, @COUNTER, 1)
        -- When we come across a space, assume the previous character is now a whole word.
    END ELSE IF SUBSTRING(@MEMO, @COUNTER, 1) = ' ' BEGIN
        IF @WORD NOT LIKE '[0-9][0-9].[0-9][0-9].[0-9][0-9]' BEGIN
            SET @LINE = @LINE + ' ' + @WORD
            SET @WORD = ''
        --If that word is a date string format then save it and reset.
        END ELSE IF @WORD LIKE '[0-9][0-9].[0-9][0-9].[0-9][0-9]' BEGIN
            SET @DATE = @WORD
            SET @LINE = ''
            SET @WORD = ''
            PRINT 'DATE: ' + @DATE
        END 
        IF LTRIM(@LINE) != '' BEGIN
            PRINT 'LINE: ' + LTRIM(@LINE)
        END
    END
    SET @COUNTER = @COUNTER + 1
END
例如,最终目标基本上就是这样

╔═══╦════════════╦═════════════╗
║   ║ Date       ║ Value       ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 2017-06-23 ║ Test 1      ║
║ 2 ║ 2017-06-24 ║ Test 2      ║
║ 3 ║ 2017-06-25 ║ Test 3      ║
╚═══╩════════════╩═════════════╝
编辑-已更正输入错误

一种方法是将字符串解析为单词,然后重新构造

我使用了一个表值函数来分割字符串,但很容易转换为一种无需自定义项的内嵌方法

范例

返回

解析/拆分UDF(如果感兴趣)


此解决方案基于基于递归CTE的专门构建iTVF

功能代码:

ALTER FUNCTION dbo.ParseLegacyInfo
/* ===================================================================
Created to parse the text information from legacy system.
==================================================================== */
(
    @TextString VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
    WITH 
        cte_rSplit AS (
            SELECT 
                LineNum = 1,
                ParsedString = SUBSTRING(@TextString, 1, dl.DateLocation + 7),
                StringRemain = SUBSTRING(@TextString, dl.DateLocation + 8, 8000)
            FROM
                ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(@TextString, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
            UNION ALL
            SELECT 
                LineNum = rs.LineNum + 1,
                ParsedString = SUBSTRING(rs.StringRemain, 1, dl.DateLocation + 7),
                StringRemain = SUBSTRING(rs.StringRemain, dl.DateLocation + 8, 8000)
            FROM            
                cte_rSplit rs
                CROSS APPLY ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(rs.StringRemain, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
            WHERE 
                rs.StringRemain LIKE '%[0-9][0-9].[0-9][0-9].[0-9][0-9]%'
            )
    SELECT 
        rs.LineNum, 
        [Date] = CONVERT(DATE, LEFT(rs.ParsedString, 8), 4),
        TextValue = SUBSTRING(rs.ParsedString, 9, 8000)
    FROM
        cte_rSplit rs;
GO
一些测试数据

IF OBJECT_ID('tempdb..#LegacyInfo', 'U') IS NOT NULL 
DROP TABLE #LegacyInfo;

CREATE TABLE #LegacyInfo (
    id INT NOT NULL IDENTITY(1, 1),
    TextData VARCHAR(8000) NOT NULL 
    );
INSERT #LegacyInfo (TextData) VALUES 
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('31.12.17 - This is just a test...'),
('01.01.17 - Line 1
Some other text following line 1.
22.02.17 - Line 2
More stuff about line 2.');
最后一个查询

SELECT 
    li.id, LineNum, Date, TextValue
FROM
    #LegacyInfo li
    CROSS APPLY dbo.ParseLegacyInfo(li.TextData);
结果。。。注意:原来的甲壳返回和线饲料仍然在tact


我不会在数据库中处理这个问题,我会导出到Java或Perl之类的工具,然后在那里进行工作。结果将在crystal报表中使用,所以我要么在该程序中进行,要么在SQL中进行。不过,我的第一个解决方案是使用SQL。谢谢你你能保证在每个条目的开头都会有一个格式为nn.nn.nn的子字符串,其中n是一个数字字符吗?此外,每个条目是否应以表格nn.nn.nn-开头?在你的6个示例条目中,有4个也是以破折号开头的,但其他2个不是。是的,回答nn.nn.nn问题。后面的破折号可以视为文本。示例中的每个日期前是否有换行符?char13+char10或仅char10或仅char13
ALTER FUNCTION dbo.ParseLegacyInfo
/* ===================================================================
Created to parse the text information from legacy system.
==================================================================== */
(
    @TextString VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
    WITH 
        cte_rSplit AS (
            SELECT 
                LineNum = 1,
                ParsedString = SUBSTRING(@TextString, 1, dl.DateLocation + 7),
                StringRemain = SUBSTRING(@TextString, dl.DateLocation + 8, 8000)
            FROM
                ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(@TextString, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
            UNION ALL
            SELECT 
                LineNum = rs.LineNum + 1,
                ParsedString = SUBSTRING(rs.StringRemain, 1, dl.DateLocation + 7),
                StringRemain = SUBSTRING(rs.StringRemain, dl.DateLocation + 8, 8000)
            FROM            
                cte_rSplit rs
                CROSS APPLY ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(rs.StringRemain, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
            WHERE 
                rs.StringRemain LIKE '%[0-9][0-9].[0-9][0-9].[0-9][0-9]%'
            )
    SELECT 
        rs.LineNum, 
        [Date] = CONVERT(DATE, LEFT(rs.ParsedString, 8), 4),
        TextValue = SUBSTRING(rs.ParsedString, 9, 8000)
    FROM
        cte_rSplit rs;
GO
IF OBJECT_ID('tempdb..#LegacyInfo', 'U') IS NOT NULL 
DROP TABLE #LegacyInfo;

CREATE TABLE #LegacyInfo (
    id INT NOT NULL IDENTITY(1, 1),
    TextData VARCHAR(8000) NOT NULL 
    );
INSERT #LegacyInfo (TextData) VALUES 
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('31.12.17 - This is just a test...'),
('01.01.17 - Line 1
Some other text following line 1.
22.02.17 - Line 2
More stuff about line 2.');
SELECT 
    li.id, LineNum, Date, TextValue
FROM
    #LegacyInfo li
    CROSS APPLY dbo.ParseLegacyInfo(li.TextData);