让我说我有这样的表变量......
DECLARE @LocalTable TABLE
(
IdField NVARCHAR(MAX),
NameField NVARCHAR(MAX)
)
我就像这样填充它......
INSERT INTO @LocalTable
SELECT
IdColumn,
NameColumn
FROM SourceTable
源表中的 NameColumn
可能具有重复值,因此本地表中的NameField
将具有相同的重复值。
让我们说我想将本地表插入到目标表中,就像这样......
INSERT INTO TargetTable (NewIdColumn, NewNameColumn)
SELECT
IdField,
NameField
FROM
@LocalTable
但是NewNameColumn
中的TargetTable
有一个UNIQUE
约束,因此重复会导致异常。
我想应用这个例子,
ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY NameField)
这样NameField
附加/后缀一个数字,表示其重复。
我有这个可以选择正确附加值的工作示例,但是我无法在这样的更新语句中使用它:
UPDATE localtable
SET NameField = AppendedNameField
FROM @LocalTable AS localtable
SELECT
CONCAT(Ref.NameField, ROW_NUMBER() OVER (PARTITION BY Ref.NameField
ORDER BY Source.IdField)), *
FROM
@LocalTable AS Source
INNER JOIN
@LocalTable AS Ref ON Ref.NameField = Source.NameField
AND Ref.IdField != Source.IdField
提前致谢。
答案 0 :(得分:5)
如果我理解你要做的事情。
WITH CTE AS
(
SELECT
CONCAT(NameField, ROW_NUMBER()
OVER(PARTITION BY NameField ORDER BY IdField)) AS NewName, *
FROM @LocalTable
)
UPDATE
CTE SET Name = NewName
如果您只想对重复的名称执行此操作,则可以使用该名称将COUNT(*) OVER (PARTITION BY Name)
添加到CTE和条件逻辑中。
答案 1 :(得分:1)
您不一定需要更新表,不能在插入时添加后缀吗?
DECLARE @LocalTable TABLE (IdField INT, NameField VARCHAR(50));
INSERT @LocalTable VALUES (1, 'Not Duplicate'), (2, 'Duplicate'), (3, 'Duplicate');
INSERT INTO TargetTable (NewIdColumn, NewNameColumn)
SELECT IdField,
CONCAT(NameField,
CASE WHEN COUNT(*) OVER(PARTITION BY NameField) > 1
THEN ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY IdField)
ELSE ''
END)
FROM @LocalTable
ORDER BY IdField;
或者,您可以通过简单地将上面的select包装在子查询中来更新,并更新:
DECLARE @LocalTable TABLE (IdField INT, NameField VARCHAR(50));
INSERT @LocalTable VALUES (1, 'Not Duplicate'), (2, 'Duplicate'), (3, 'Duplicate');
UPDATE t
SET NameField = NewNameField
FROM
(
SELECT IdField, NameField,
NewNameField = CONCAT(NameField,
CASE WHEN COUNT(*) OVER(PARTITION BY NameField) > 1
THEN ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY IdField)
ELSE ''
END)
FROM @LocalTable
) AS t;
SELECT * FROM @LocalTable;
答案 2 :(得分:0)
只需在temp表中添加一个标识字段即可。
DECLARE @LocalTable TABLE
(
ix int identity primary key,
IdField NVARCHAR(MAX),
NameField NVARCHAR(MAX)
)
Insert into @LocalTable(IdColumn, NameColumn)
SELECT
IdColumn,
NameColumn
FROM SourceTable
-- Make sure same names are consecutive in the table
ORDER BY NameColumn
设置NameColumn如下:
update lt set
NameColumn = NameColumn
-- Add a number based on the ix, minus the lowest ix entry for the same name
+ cast(
(select lt.ix - min(lt2.ix) + 1
from @localTable lt2 where lt2.name = lt.name)
as nvarchar(10))
from @LocalTable lt
-- Only do those with duplicated names
where lt.NameColumn in (
select NameColumn from @localtable group by NameColumn having count(1) > 1
)
答案 3 :(得分:0)
首先,考虑使用Temp表而不是temp变量
其次,尝试将NVARCHAR(MAX)改为更小的东西,如INT
以下是仅在NameField中包含唯一值的代码:
CREATE TABLE #LocalTable
(
IdField NVARCHAR(MAX),
NameField NVARCHAR(MAX)
)
INSERT INTO #LocalTable
VALUES (1,'A'), (2,'B'), (3,'B')
INSERT INTO TargetTable
(
NewIdColumn,
NewNameColumn
)
SELECT IdField, NameField
FROM #LocalTable
WHERE IdField in (
SELECT MIN(IdField) FROM #LocalTable
GROUP BY NameField
);
请注意,重复记录的“IdField”将被忽略,不会插入目标表。
答案 4 :(得分:0)
尝试使用以下代码:
WITH TargetTable AS(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField) AS UniqueID
FROM @LocalTable AS L
),
UpdatedData AS(
SELECT Source.NameField,
ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField) AS UniqueID,
CONCAT(Ref.NameField, ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField)) AS AppendedNameField
FROM @LocalTable AS Source
INNER JOIN @LocalTable AS Ref ON Ref.NameField = Source.NameField AND Ref.IdField != Source.IdField
)
UPDATE T
SET NameField=U.AppendedNameField
FROM TargetTable AS T
JOIN UpdatedData AS U ON T.NameField=U.NameField AND T.UniqueID=U.UniqueID;