Sql 在表上循环(不使用光标)以合并数据

Sql 在表上循环(不使用光标)以合并数据,sql,sql-server-2005,tsql,sql-server-2008,Sql,Sql Server 2005,Tsql,Sql Server 2008,请查看/运行以下脚本 DECLARE @Products Table ( PId int ) INSERT @Products SELECT 100 INSERT @Products SELECT 101 INSERT @Products SELECT 102 DECLARE @Stff Table ( Stid int, StaffName VARCHAR(20) ) INSERT @Stff SELECT 301, 'White' INSERT @Stff SELECT 302,

请查看/运行以下脚本

DECLARE @Products Table (   PId int )

INSERT @Products SELECT 100
INSERT @Products SELECT 101
INSERT @Products SELECT 102

DECLARE @Stff Table ( Stid int, StaffName VARCHAR(20) )

INSERT @Stff SELECT 301, 'White'
INSERT @Stff SELECT 302, 'Green'

DECLARE @Items Table
(
    ItemId int,
    PIdFK int,
    StIdFK int,
    CreatedDate DateTime,
    Notes varchar(100),
    NotesHistory varchar(2000)
)

INSERT INTO @Items SELECT 1, 100, 301, GETDATE(), Null, NULL
INSERT INTO @Items SELECT 2, 101, 301, GETDATE(), Null, NULL
INSERT INTO @Items SELECT 3, 101, 301, DATEADD(DD, 1, GETDATE()), 'Hello Dear', NULL
INSERT INTO @Items SELECT 4, 101, 301, DATEADD(DD, 2, GETDATE()), 'Did you get my msg?', NULL
INSERT INTO @Items SELECT 5, 102, 302, GETDATE(), Null, NULL
INSERT INTO @Items SELECT 6, 102, 302, DATEADD(DD, 1, GETDATE()), Null, NULL
INSERT INTO @Items SELECT 7, 102, 302, DATEADD(DD, 3, GETDATE()), 'How are you doing?', NULL
INSERT INTO @Items SELECT 8, 102, 302, DATEADD(DD, 4, GETDATE()), 'Your Items are ready.', NULL

SELECT * FROM @Items

DECLARE @ItemsHistory Table
(
    ItemHisotryId int,
    ItemIdFK int,
    StIdFK int,
    NotesHisotry varchar(200),
    CreatedDate DATETIME
)

INSERT INTO @ItemsHistory SELECT 1, 1, 301, NULL, GETDATE()
INSERT INTO @ItemsHistory SELECT 2, 2, 301, NULL, GETDATE()
INSERT INTO @ItemsHistory SELECT 3, 3, 301, 'Hello Dear', DATEADD(DD, 1, GETDATE())
INSERT INTO @ItemsHistory SELECT 4, 4, 301, 'Dimd you get my msg?', DATEADD(DD, 2, GETDATE())
INSERT INTO @ItemsHistory SELECT 5, 5, 302, NULL, GETDATE()
INSERT INTO @ItemsHistory SELECT 6, 6, 302, NULL, DATEADD(DD, 1, GETDATE())
INSERT INTO @ItemsHistory SELECT 7, 7, 302, 'How are you doing?', DATEADD(DD, 3, GETDATE())
INSERT INTO @ItemsHistory SELECT 8, 8, 302, 'Your Items are ready', DATEADD(DD, 4, GETDATE())
我想将Items表的
Notes
列和Items存储表的
NotsHistory
列中的所有数据合并为一个字符串,事实上我想用所有
Items表的
notesstory
列更新
PID

你能不能不用光标来帮我。我使用的是sql server 2008,所以CTE可以做到这一点,但我不知道如何实现这一点

结果字符串应该如下所示

<b>Items.CreaedDate - Items.StaffName: <b/> Items.Notes <br/><b>ItemsHisotryCreatedDate - ItemsHistory.StaffName <b> ItemsHistory.NotesHistory
Items.creedDate-Items.StaffName:Items.Notes
itemsIsotryCreatedDate-ItemsHistory.StaffName ItemsHistory.notestory
以下部分将从ItemsHistory表中添加到为唯一“PId”添加的每条记录上

<br/><b>ItemsHisotryCreatedDate - ItemsHistory.StaffName <b> ItemsHistory.NotesHistory

ItemsHisotryCreatedDate-ItemsHistory.StaffName ItemsHistory.NotesHistory

谢谢。

您可以通过如下方式连接,而无需循环;只需根据需要添加您自己的查询/联接等:

DECLARE @s varchar(max) = ''

SELECT @s = @s + '<br/><b>' + CONVERT(varchar(10), i.CreatedDate, 101) + '</b>' + ISNULL(i.Notes, '')
FROM @Items i

SELECT @s
DECLARE@s varchar(max)=”
选择@s=@s+'
'+CONVERT(varchar(10),i.CreatedDate,101)+''+ISNULL(i.Notes,'') 来自@Items i 选择@s
(您必须确保其中没有
NULL
s)

但不要这样做!
数据库不是构建html的地方;不仅如此,它为您打开了XSRF漏洞的大门。我会在UI层中这样做,适当地利用您使用的任何平台提供的html编码功能。盲目地将字符串连接为HTML几乎等同于盲目地将用户字符串连接到TSQL(而不是使用参数);充其量,格式将被屏蔽(没有正确处理
,您可以通过以下方式在没有循环的情况下连接;只需根据需要添加您自己的查询/连接等:

DECLARE @s varchar(max) = ''

SELECT @s = @s + '<br/><b>' + CONVERT(varchar(10), i.CreatedDate, 101) + '</b>' + ISNULL(i.Notes, '')
FROM @Items i

SELECT @s
DECLARE@s varchar(max)=”
选择@s=@s+'
'+CONVERT(varchar(10),i.CreatedDate,101)+''+ISNULL(i.Notes,'') 来自@Items i 选择@s
(您必须确保其中没有
NULL
s)

但不要这样做!

数据库是“强>不/强”的HTML生成位置;尤其是它对XSRF漏洞极大地开放了你。我会在UI层中这样做,适当地使用你所使用的任何平台所提供的HTML编码功能。将字符串转换为TSQL(而不是使用参数);充其量格式设置会被阻塞(没有正确处理

),类似这样的情况如何

;WITH Vals AS (
        SELECT  PIdFK,
                Notes,
                ItemIdFK
        FROM    @ItemsHistory ih INNER JOIN
                @Items i    ON  ih.ItemIdFK = i.ItemId
        WHERE   Notes IS NOT NULL
)
SELECT 
        v.PIdFK,
        STUFF( 
               (SELECT 
                    ', ' + v2.Notes 
                    FROM Vals v2 
                    WHERE v.PIdFK=v2.PIdFK 
                    ORDER BY v2.ItemIdFK 
                    FOR XML PATH(''), TYPE 
               ).value('.','varchar(max)') 
               ,1,2, '' 
          ) AS Notes 
FROM Vals v 
GROUP BY v.PIdFK

像这样的怎么样

;WITH Vals AS (
        SELECT  PIdFK,
                Notes,
                ItemIdFK
        FROM    @ItemsHistory ih INNER JOIN
                @Items i    ON  ih.ItemIdFK = i.ItemId
        WHERE   Notes IS NOT NULL
)
SELECT 
        v.PIdFK,
        STUFF( 
               (SELECT 
                    ', ' + v2.Notes 
                    FROM Vals v2 
                    WHERE v.PIdFK=v2.PIdFK 
                    ORDER BY v2.ItemIdFK 
                    FOR XML PATH(''), TYPE 
               ).value('.','varchar(max)') 
               ,1,2, '' 
          ) AS Notes 
FROM Vals v 
GROUP BY v.PIdFK

谢谢Marc,也谢谢“XSRF漏洞”的建议。事实上,我是在我的UI中这样做的,但我已经更改了db设计,需要更新Items表。这就是为什么我只想运行脚本并更新列。再次感谢您的帮助。@pst只有在它是xhtml而不是html的情况下才这样做……但可能。这将取决于场景。自由浮动的

可能会很痛苦。谢谢Marc,也谢谢“XSRF漏洞”的建议。事实上,我是在我的UI中这样做的,但我已经更改了db设计,需要更新Items表。这就是为什么我只想运行脚本并更新列。再次感谢您的帮助。@pst仅当它是xhtml而不是html时。…但也有可能。这将很大程度上取决于场景。自由浮动的

可能是一种痛苦。感谢astander,结果不是我所期待的,即“101你收到我的消息了吗?”,你好,亲爱的,你好吗?,“你的物品准备好了吗?”“102你收到我的消息了吗?”,你好,亲爱的,你好吗?,“你的物品准备好了。”结果是“101您好,亲爱的,您收到我的邮件了吗”“102您好,您的邮件准备好了吗”“很抱歉设置了格式。谢谢astander,结果不是我想要的结果,即“101您收到我的邮件了吗?”,您好,亲爱的,您好吗?,您的邮件准备好了。”“102您收到我的邮件了吗?”,您好,亲爱的,您好吗?,您的邮件准备好了。”uld为“101您好,亲爱的,您收到我的消息了吗”“102您好,您的物品准备好了吗”“很抱歉格式化。