【问题标题】:Split string to columns and rows将字符串拆分为列和行
【发布时间】:2013-08-12 10:27:58
【问题描述】:

我有一个要拆分的字符串;它的格式如下:

---------------------------------------------------------
HEADING DETAILS HERE:
~
INVOICE1^VALUE1^VALUE2^
INVOICE2^VALUE1^VALUE2^
INVOICE3^VALUE1^VALUE2^
TOTAL^OFVALUE1^OFVALUE2^
~
FOOTER DETAILS HERE
---------------------------------------------------------

我的输出应该是一个包含 3 列的表格:

|    INVOICE    |    VALUE1    |    VALUE2    |
INVOICE 1---------- VALUE1  ---------- VALUE2 
INVOICE 2---------- VALUE1  ---------- VALUE2 
INVOICE 3---------- VALUE1  ---------- VALUE2 

我的想法是用第一个分隔符分割~ 并用分隔符分割 2 ^

我做了一个分割函数,这是我第一次用分隔符分割的结果~

ROW 1   HEADER DETAILS HERE:

ROW 2   INVOICE1^VALUE1^VALUE2^ INVOICE2^VALUE1^VALUE2^ INVOICE3^VALUE1^VALUE2^

ROW 3   FOOTER DETAILS HERE

但是,我需要做的是将结果放入列而不是行。另外,我需要获取第 2 行的结果并再次拆分并将其放在这样的列中:

INVOICE column -    VALUE1 column   - VALUE2 column
INVOICE 1---------- VALUE1  ---------- VALUE2 
INVOICE 2---------- VALUE1  ---------- VALUE2 
INVOICE 3---------- VALUE1  ---------- VALUE2

我希望有人能够阅读这个问题并帮助我编写 TSQL。

跟进问题:2013 年 8 月 13 日
我试图把 Rs 的代码改成这样……

USE [test]
GO
/****** Object:  StoredProcedure [dbo].[SplitSP4]    Script Date: 8/13/2013 7:33:31 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[SplitSP4] 
    -- Add the parameters for the stored procedure here
    --<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>, 
    --<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
    @TABLE_id varchar(50)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    --SET NOCOUNT ON;

declare @string varchar(8000)
declare @stringXML xml
declare @NewLine char(2)
set @NewLine=char(13)+char(10)
set @string = (SELECT [dbo].[TABLE_NAME].[iam_string] FROM [dbo].[TABLE_NAME] WHERE [dbo].[TABLE_NAME].[id] = @TABLE_id)
--'HEADING DETAILS HERE:
--~
--INVOICE1^VALUE1^VALUE2^
--INVOICE2^VALUE1^VALUE2^
--INVOICE3^VALUE1^VALUE2^
--TOTAL^OFVALUE1^OFVALUE2^
--~
--FOOTER DETAILS HERE'

declare @table1 table(cols varchar(max))

--convert string to xml
SELECT @stringXML = CONVERT(xml,'<root><i>' + 
                    Replace(@string, @NewLine, '</i><i>') + '</i></root>')

--split xml string into different rows
insert into @table1 
select Cols = I.c.value('.', 'varchar(MAX)')
from @stringXML.nodes('/root/i') I(c)

--split invoice rows into columns
select     
    Inv.value('/Invoice[1]/Attribute[1]','varchar(50)') AS [Invoice],
    Inv.value('/Invoice[1]/Attribute[2]','varchar(50)') AS [Value1],
    Inv.value('/Invoice[1]/Attribute[3]','varchar(50)') AS [Value2]
from
    (
        select CONVERT(XML,'<Invoice><Attribute>' 
            + REPLACE([cols],'~', '</Attribute><Attribute>') 
            + '</Attribute></Invoice>') Inv 
            from @table1 where cols like '%^%'
    ) x

end

...让我能够为 CRYSTAL 报告制作一个存储程序。但似乎当我执行这个 STORED PROCEDURE 时它返回了这个错误。

消息 9421,级别 16,状态 1,过程 SplitSP4,第 34 行
XML 解析:第 1 行,字符 31,非法名称字符

我想知道如何修复我的代码以适应示例 XML 代码?

【问题讨论】:

  • 将值保存到文件中,然后将它们作为文本重新导入。这是迄今为止处理此类数据的最简单方法。
  • 实际上我正在为水晶报告做一个存储过程。我需要拆分的字符串字段格式与该格式类似。此处的标题详情:~ INVOICE1^VALUE1^VALUE2^ INVOICE2^VALUE1^VALUE2^ INVOICE3^VALUE1^VALUE2^ TOTAL^OFVALUE1^OFVALUE2^ ~ 页脚详情

标签: sql tsql split multiple-columns


【解决方案1】:

假设您的文本在每行末尾都有换行符,试试这个

declare @string varchar(4000)
declare @stringXML xml
declare @NewLine char(2)
set @NewLine=char(13)+char(10)
set @string = 'HEADING DETAILS HERE:
~
INVOICE1^VALUE1^VALUE2^
INVOICE2^VALUE1^VALUE2^
INVOICE3^VALUE1^VALUE2^
TOTAL^OFVALUE1^OFVALUE2^
~
FOOTER DETAILS HERE'

declare @table1 table(cols varchar(max))

--convert string to xml
SELECT @stringXML = CONVERT(xml,'<root><i>' + 
                    Replace(@string, @NewLine, '</i><i>') + '</i></root>')

--split xml string into different rows
insert into @table1 
select Cols = I.c.value('.', 'varchar(MAX)')
from @stringXML.nodes('/root/i') I(c)

--split invoice rows into columns
select     
    Inv.value('/Invoice[1]/Attribute[1]','varchar(50)') AS [Invoice],
    Inv.value('/Invoice[1]/Attribute[2]','varchar(50)') AS [Value1],
    Inv.value('/Invoice[1]/Attribute[3]','varchar(50)') AS [Value2]
from
    (
        select CONVERT(XML,'<Invoice><Attribute>' 
            + REPLACE([cols],'^', '</Attribute><Attribute>') 
            + '</Attribute></Invoice>') Inv 
            from @table1 where cols like '%^%'
    ) x

您已经编写了拆分函数,您可以使用上面的最后一个选择语句(--将发票行拆分为列)与您现有的拆分函数,将 row2 转换为 xml 并将第 2 行拆分为列

【讨论】:

  • 非常感谢,我将尝试执行您给定的代码。
  • 太棒了!您的代码非常有效。现在我需要做的是翻译这段代码,而不是“硬编码”字符串,我将从数据库中一个表的字段中获取字符串值。非常感谢。
  • RS,我试图更改您的代码,以便从中生成 CRYSTAL 报告的存储过程。但它似乎有一个错误......我更新了我的问题以便能够显示整个代码
【解决方案2】:

首先,将第一次拆分的结果存储到临时表中。然后,您可以在该临时表上使用游标并在行值中存在 ^ 时拆分行。

我已经使用上述查询为您创建了存储过程 -

IF OBJECT_ID(N'[dbo].[SplitSP4]', N'P') IS NOT NULL
 DROP PROCEDURE [dbo].[SplitSP4]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[SplitSP4]
    @table_id INT
AS

declare @stringXML xml
declare @NewLine char(2)
DECLARE @string VARCHAR(MAX)
set @NewLine=char(13)+char(10)

declare @table1 table(cols varchar(max))

SELECT @string = string_value FROM table_name WHERE id = @table_id

--convert string to xml
SELECT @stringXML = CONVERT(xml,'<root><i>' + 
                Replace(@string, @NewLine, '</i><i>') + '</i></root>')

--split xml string into different rows
insert into @table1 
select Cols = I.c.value('.', 'varchar(MAX)')
from @stringXML.nodes('/root/i') I(c)

--split invoice rows into columns
select     
    Inv.value('/Invoice[1]/Attribute[1]','varchar(50)') AS [Invoice],
    Inv.value('/Invoice[1]/Attribute[2]','varchar(50)') AS [Value1],
    Inv.value('/Invoice[1]/Attribute[3]','varchar(50)') AS [Value2]
from
(
    select CONVERT(XML,'<Invoice><Attribute>' 
        + REPLACE([cols],'^', '</Attribute><Attribute>') 
        + '</Attribute></Invoice>') Inv 
        from @table1 where cols like '%^%'
) x

然后这样称呼它

EXEC SplitSP4 1

【讨论】:

  • 我已经完成了第一步(将第一个拆分存储到临时表中),现在我在使用游标时遇到了麻烦。嗯.. 我的临时表中的行不再有插入符号 ^。顺便说一句,感谢您的响应 AgentSQL =)
  • 我真的很困惑我应该如何使用光标将这些行分成 3 列。我真的很感激可以用作我的模式的代码。这是我第一次为我的水晶报告所需的这个复杂字符串实际制作存储过程。再次感谢 AgentSQL!我会等你的回复
  • 抱歉回复晚了。您可以使用rs提到的上述方法。您的存储过程有问题。请参阅我在上面发布的那个。
猜你喜欢
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 1970-01-01
相关资源
最近更新 更多