【发布时间】:2018-08-01 15:16:02
【问题描述】:
我看过几个类似的问题,但没有找到一个可以回答我的问题。
我有一个源表,其中包含公司的许多单独注释
CompanyName, Notes3
Company1, "spoke with someone"
Company2, "Email no longer works"
Company1, "Moved address"
我有一个目标表(vchCompanyName 在这里是唯一的)
vchCompanyName, vchNotes
Company1, "started business in 2005"
Company2, null
我想结束
vchCompanyName, vchNotes
Company1, "started business in 2005
spoke with someone
Moved address"
Company2, "Email no longer works"
我试过这个代码
WITH CTE
AS (SELECT ROW_NUMBER() OVER (PARTITION BY CompanyName, Notes3 ORDER BY CompanyName) RowNum, *
FROM CompanyContact
)
merge dCompany as target
using CTE as source
on target.vchcompanyname = source.companyname
when matched and len(source.notes3)>0 and source.RowNum = 1
then
update set target.vchnote = vchnote + CHAR(13) + source.Notes3
但得到错误
MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。 MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。 这是准确的。
我也尝试过STRING_AGG,但得到一个未定义的 UDF 错误。
如何更改我的代码以迭代运行?
--编辑-- 我试过以下更新代码
WITH CTE
AS (SELECT ROW_NUMBER() OVER (PARTITION BY CompanyName, Notes3 ORDER BY CompanyName) RowNum, *
FROM CompanyContact
)
UPDATE dCompany SET vchNote = vchNote +
(select CHAR(13) + cc.Notes3 from CompanyContact cc
inner JOIN dCompany dc ON dc.vchCompanyName COLLATE database_default = LEFT(cc.CompanyName,50) COLLATE database_default
inner join CTE on dc.vchCompanyName COLLATE database_default = LEFT(CTE.CompanyName,50) COLLATE database_default
WHERE LEN(cc.Notes3)>0
and RowNum = 1
);
但得到错误
子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。
【问题讨论】:
-
当唯一的操作是
UPDATE时,为什么要使用MERGE?为什么不直接更新目标? -
<first unnamed table>中似乎没有提供订单的列。 -
看起来您正在尝试使用第一个表中的 连接 字符串更新第二个表。这不是一个简单的更新,绝对不需要合并。
STRING_AGG是在 SQL Server 2017 中添加的。如果您不能使用它,则意味着您使用的是旧版本的 SQL Server。您必须为连接字符串创建自定义解决方案。 This article by Aaron Bertrand 解释各种技术及其性能 -
看起来您尝试使用
MERGE而不是UPDATE执行quirky update。MERGE不允许对同一行进行多次修改。如果是这样,您最终会更新您在同一个 MERGE 语句中添加的同一行 -
更新 可能 工作,但没有指定行的顺序。
ROW_NUBMER()将返回一个随机顺序,any 字符串连接技术也是如此。除非您使用ORDER BY子句指定,否则表行没有顺序
标签: sql-server tsql merge