最近,在項目中遇到資料庫中所有的表都有大量的重複資料的問題,而且是完全的重複,即所有的欄位資訊都一致,包括主鍵都一致,需要將重複的資料刪除,只保留任意一條資料。問了一些人,在網上也翻了半天,最後總結一下,共有如下幾種重複資料刪除資料的方式:
1.對於資料量不大,效率要求不高的,比較通用的一類方法,使用遊標進行刪除,如下面這段指令碼:
代碼
//定義兩個變數
delcare @max integer,@id integer
//定義一個本地遊標
declare cusCursor cursor local for select id,count(*) from tableName group by id having count(*)>1
//開啟遊標
open cusCursor
//將當前遊標讀取的內容放到變數中
fetch cusCursor into @id,@max
//判斷遊標執行前面fetch語句後的狀態,如果成功,則開始迴圈
while @@fetch_status=0
begin
select @max=@max-1
//設定後面語句處理的條數
set rowcount @max
//重複資料刪除的資料,只保留一條
delete from tableName where id=@id
//遊標向下移一行,繼續讀取資料
fetch cusCursor into @id,@max
end
//關閉遊標
close cusCursor
//刪除遊標
deallocate cusCursor
set rowcount 0
2.使用暫存資料表的方法重複資料刪除記錄,該方法效率較高,可是有局限性,如下面這段指令碼:
代碼
//將源表中的資料distinct以後,就只剩下唯一一條資料了,再將該條資料寫入到暫存資料表#tempTable中
select distinct * into #tempTable from tableName
//清空源表中的資料
truncate table tableName
//將暫存資料表中的資料寫入到源表中
select * into tableName from #temTable
//刪除暫存資料表
drop #tempTable
該方法存在的局限性就是,當資料庫的表中存在image,text類型欄位時會報錯,提示該類型欄位無法進行distinct操作。
3.征對第二種方法的局限性,而且資料量也較大,對效率也有一定的要求的情況下,可以第三種方法,如下:
代碼
//將源表的資料結構複製到暫存資料表#tempTable中
select * into #tempTable from tableName where 1<>1
//在暫存資料表中建立索引,並忽略重複列資料
Create unique index temp on #tempTable(重複列名) with IGNORE_DUP_KEY
//將源表中的資料拷貝到暫存資料表中,拷貝的同時會忽略重複列的資料,也即只保留了一份資料。
insert into #tempTable select * from tableName
//清空源表
truncate table tableName
//將暫存資料表中的資料寫入到源表中
insert into tableName select * from #tempTable
//刪除暫存資料表
drop table #tempTable
以上是最近總結出來的三種刪除資料庫重複記錄的方法,其中第三種方法在效率和通用性上都較好,在10W級資料量上都能有較好的表現。