我正在尝试更正SQL Server中的大量重复记录,是否有办法将其作为批量更新而不是为每一行运行更新脚本?
数据如下:
client | voucher_no | sequence_no | id
-------+------------+-------------+------
AA | 11111111 | 1 | 0001
AA | 11111111 | 1 | 0002
AA | 11111111 | 1 | 0003
AA | 11111112 | 13 | 0004
AA | 11111112 | 13 | 0004
AA | 11111113 | 28 | 0005
AA | 11111113 | 28 | 0006
AA | 11111114 | 17 | 0007
AA | 11111114 | 17 | 0008
AA | 11111115 | 23 | 0009
AA | 11111115 | 23 | 0010
我一直试图找到一种一次性更新记录的方法,这样脚本的结果将是:
client | voucher_no | sequence_no | id
-------+------------+-------------+------
AA | 11111111 | 1 | 0001
AA | 11111111 | 2 | 0002
AA | 11111111 | 3 | 0003
AA | 11111112 | 13 | 0004
AA | 11111112 | 14 | 0005
AA | 11111113 | 28 | 0006
AA | 11111113 | 29 | 0007
AA | 11111114 | 17 | 0008
AA | 11111114 | 18 | 0009
AA | 11111115 | 23 | 0010
AA | 11111115 | 24 | 0011
UPDATE table_a
SET sequence_no = (SELECT ROW_NUMBER() OVER (PARTITION BY sequence_no ORDER BY t.client, t.voucher_no, t.sequence_no ))
FROM table_a AS t
WHERE t.id IN (0002, 0003, 0005, 0007, 0009, 0011)
上面的方法对于列表中的第一个ID可以正常工作,但是它使用与第一个相同的sequence_no更新其余记录。
所以我最终得到了
client | voucher_no | sequence_no | id
-------+------------+-------------+------
AA | 11111111 | 2 | 0002
AA | 11111111 | 2 | 0003
AA | 11111112 | 2 | 0005
AA | 11111113 | 2 | 0007
AA | 11111114 | 2 | 0009
AA | 11111115 | 2 | 0011
如果将序列号更新为该客户端和voucher_no组合已经存在的序列号,这可能会引起进一步的问题。
我也尝试过将以上内容包装在光标中,以为查询没有机会使用下一个ID号的正确sequence_no更新,但这也不起作用
答案 0 :(得分:0)
我设法通过使用以下代码解决了这个问题:
DECLARE @client VARCHAR(2)
DECLARE @voucher_no INT
DECLARE @sequence_no INT
DECLARE @id INT
DECLARE cursor_results CURSOR FOR
WITH T AS
(
SELECT *, COUNT(*) OVER (PARTITION BY client, voucher_no, sequence_no) AS cnt
FROM table_a
)
SELECT t.client, t.voucher_no, t.sequence_no,t.id
FROM T AS t
WHERE t.cnt > 1
AND agrtid IN (0002, 0003, 0005, 0007, 0009, 0011)
ORDER BY t.client, t.voucher_no, t.sequence_no DESC
OPEN cursor_results
FETCH NEXT FROM cursor_results INTO @client, @voucher_no, @sequence_no, @id
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @new_sequence_no INT = (SELECT MAX(sequence_no) + 1 FROM table_a WHERE client = @client AND voucher_no = @voucher_no)
UPDATE table_a
SET sequence_no = @new_sequence_no,
last_update = GETDATE(),
user_id = 'USR'
WHERE id = @id
AND client = @client
AND voucher_no = @voucher_no
FETCH NEXT FROM cursor_results INTO @client, @voucher_no, @sequence_no, @id
END
CLOSE cursor_results
DEALLOCATE cursor_results
虽然这可能不是使用游标解决此问题的最佳方法,但允许我逐步浏览记录并逐个更新它们,然后再移至下一个。
以这种方式设置@new_sequence_no还可以确保我为当时的记录获取正确的MAX(sequence_no)+ 1,而不是为所有重复项都赋予第一个MAX(sequence_no)+ 1。记录。