我尝试通过连接另一个表中的行来更新临时表中的列。
看看这个:
DECLARE @Test VARCHAR(MAX);
CREATE TABLE #Test
(
EmployeeId INT
,Html VARCHAR(MAX)
);
CREATE TABLE #EmployeeItems
(
EmployeeId INT
,ItemNo INT
);
INSERT INTO #EmployeeItems (EmployeeId, ItemNo)
VALUES
(1, 1)
,(1, 2);
INSERT INTO #Test (EmployeeId, Html) VALUES (1, '<div class="first">');
SET @Test = '<div class="first">';
UPDATE T SET Html += '<div class="second">' + CAST(E.ItemNo AS VARCHAR) + '</div>'
FROM #Test AS T
JOIN #EmployeeItems AS E ON T.EmployeeId = E.EmployeeId;
SELECT @Test += '<div class="second">' + CAST(E.ItemNo AS VARCHAR) + '</div>'
FROM #Test AS T
JOIN #EmployeeItems AS E ON T.EmployeeId = E.EmployeeId;
UPDATE #Test SET Html += '</div>';
SET @Test += '</div>';
SELECT Html FROM #Test;
SELECT @Test;
DROP TABLE #Test;
DROP TABLE #EmployeeItems;
#Test表中的列包含:<div class="first"><div class="second">1</div></div>
@Test变量包含:<div class="first"><div class="second">1</div><div class="second">2</div></div>
这是为什么?它有什么区别?我以为我会得到相同的结果,但在表格中它只连接一行,第一行。
如果不运行光标,我应该怎么做才能更新我的表?
修改
我原来的问题来自这样的事情:
我的输入数据是
CREATE TABLE #Actions(EmployeeId INT,EmployeeName VARCHAR(100),ActionStart TIME,ActionEnd TIME,Type VARCHAR(10));
INSERT INTO #Actions(EmployeeId,EmployeeName,ActionStart,ActionEnd, Type)
VALUES (1,'Bob','09:00','12:00', 'action'),(1,'Bob','14:30','16:00', 'action'),(1,'Bob','18:00','20:00', 'event'),(2,'Susan','10:00','12:00', 'action');
我想要这样的输出
<div class="employee" employeeid="1" employeename="Bob">
<div class="action" start="09:00" end="12:00" type="action"></div>
<div class="action" start="14:30" end="16:00" type="action"></div>
<div class="action" start="18:00" end="20:00" type="event"></div>
</div>
<div class="employee" employeeid="2" employeename="Susan">
<div class="action" start="10:00" end="12:00" type="action"></div>
</div>
与第一个例子一样,这是一个简化的例子。但如果我解决了一个案例,我可以解决我的问题。你会如何使用FOR XML子句做到这一点?
答案 0 :(得分:0)
对于测试表,更新是针对每一行完成的,因此如果从表中选择所有行,您将获得两行:
<div class="first"><div class="second">1</div></div>
<div class="first"><div class="second">2</div></div>
在第二种情况下,它会添加'<div class="second">' + CAST(E.ItemNo AS VARCHAR) + '</div>'
次,因为表中有行。由于你有两行,它会将两个div添加到变量中。
如果希望表的每一行都具有@Test
的值,则不需要游标。只需更新表格即可获得@Test
。
答案 1 :(得分:0)
将变量连接看作是一个怪癖;它是不受支持的行为,在代码中被大量使用:)如果你想继续使用它,你可以像这样修改你的UPDATE语句:
UPDATE t
SET HTML = @Test
FROM #test t
另一种方法是使用FOR XML语法连接
CREATE TABLE #Test
(
EmployeeId INT
, Html VARCHAR(MAX)
) ;
CREATE TABLE #EmployeeItems
(
EmployeeId INT
, ItemNo INT
) ;
INSERT INTO #EmployeeItems
( EmployeeId, ItemNo )
VALUES ( 1, 1 ) ,
( 1, 2 ) ;
INSERT INTO #Test
( EmployeeId, Html )
VALUES ( 1, '<div class="first">' ) ;
UPDATE #Test
SET HTML+= REPLACE(REPLACE(( SELECT '|div class="second"|'
+ CAST(E.ItemNo AS VARCHAR) + '|/div|'
FROM #Test AS T
JOIN #EmployeeItems AS E ON T.EmployeeId = E.EmployeeId
FOR
XML PATH('')
), '|div class="second"|',
'<div class="second">'), '|/div|', '</div>')
UPDATE #Test
SET Html += '</div>' ;
SELECT Html
FROM #Test ;
DROP TABLE #Test ;
DROP TABLE #EmployeeItems ;
或(也许最好),只需直接构建XML文档。
SELECT 'first' AS "div/@class"
, 'second' AS "div/div/@class"
, e.ItemNo AS "div/div"
FROM #EmployeeItems e
FOR XML PATH('')
编辑问题的附加答案:
BEGIN TRAN
CREATE TABLE #Actions
(
EmployeeId INT
, EmployeeName VARCHAR(100)
, ActionStart TIME
, ActionEnd TIME
, Type VARCHAR(10)
) ;
INSERT INTO #Actions
( EmployeeId, EmployeeName, ActionStart, ActionEnd, Type )
VALUES ( 1, 'Bob', '09:00', '12:00', 'action' ),
( 1, 'Bob', '14:30', '16:00', 'action' ),
( 1, 'Bob', '18:00', '20:00', 'event' ),
( 2, 'Susan', '10:00', '12:00', 'action' ) ;
;
WITH CTE
AS ( SELECT DISTINCT
EmployeeID
, EmployeeName
FROM #actions
)
SELECT 'employee' AS "@class"
, employeeid AS "@employeeid"
, employeename AS "@employeename"
, ( SELECT 'action' AS "@class"
, ActionStart AS "@start"
, ActionEnd AS "@end"
, Type AS "@type"
FROM #Actions a2
WHERE a2.EmployeeId = a.EmployeeID
FOR
XML PATH('div')
, TYPE
)
FROM cte a
FOR XML PATH('div')
ROLLBACK TRAN