Unique Constraint’in olmadığı mükerrer kayıtlar

Önceki yazıda mükerrer eden kayıtları sahip oldukları identity değeri sayesinde silebiliyorduk. Peki Sql Server’daki bu tabloda kayıtları birbirinden ayıracak herhangi bir Primary Key veya Unique Constraint yoksa kayıtları nasıl sileceğiz. L_User isimli tablosunda kayıtları şu şekilde durduğunu varsayalım.

Bu şekilde tekrar eden kayıtlardan birini SQL Server Enterprise Manager (SEM) içerisinde silmeye çalıştığımızda
Key column information is insufficient or incorrect. Too many rows were affected by update
hatasıyla karşılaşırız. Bu tür kayıtları SEM içerisinde değil Query Analyzer aracılığıyla silebiliriz.

DELETE FROM L_User
WHERE UserName='ahmet' AND UserPwd='123'

Bu durumda kullanıcı adı, “Ahmet”, şifresi,”123¨ olan tüm kayıtları silmiş oluruz. Oysa amacımız tekrar eden kayıtların tümünü silmek değil o kayıtları bire indirgemektir.
Böyle bir durum için en kısa çözüm, geçici(temporary) bir tablo kullanarak asıl tabloyu yeniden oluşturmaktır. Önce, satırları, tekrar eden kolonlarına göre gruplayıp geçici bir tabloya aktaracağız. Daha sonra asıl tabloyu silip geçici tabloyu, asıl tabloya aktaracağız.

--Kayıtları grupla ve T isimli geçici tabloya yükle
SELECT * INTO #T FROM L_User
GROUP BY UserName,UserPwd
/*
VEYA gruplama yerine DISTINCT kullanılabilir
SELECT DISTINCT UserName,UserPwd
INTO #T FROM L_User1
*/

--Asıl tablodaki kayıtları sil
DELETE L_User

--#T tablosunu asıl tabloya aktar
INSERT INTO L_User
SELECT * FROM #T
UserName UserPwd
adem 789
ahmet 123
mehmet 456

Tabi kayıtların bu şekilde databasede tutulması pek mantıklı bir yaklaşım olmadığı için bunlara identity kazandırmak daha doğru olacaktır. Bu durumda verileri geçici tabloya aktarırken identity kolon da oluşturulabiliriz.

--Kayıtları grupla ve T isimli geçici tabloya yükle
SELECT ColumnId=IDENTITY(int,1,1),UserName,UserPwd
INTO #T FROM L_User
GROUP BY UserName,UserPwd

--Asıl tabloyu drop edelim
DROP TABLE L_User

--#T tablosunu L_User isimli bir tabloya kopyalayalım.
SELECT * INTO L_User
FROM #T
ColumnId UserName UserPwd
1 adem 789
2 ahmet 123
3 mehmet 456

SQL Server 2005‘te mükerrer kayıtları silmeyi aynı mantıkla yapabileceğimiz gibi kendisinin sunmuş olduğu ROW_NUMBER() fonksiyonundan yararlanılabilir. Bu fonksiyon, SELECT anında belirlediğimiz argümanlara göre kolonları numaralandırır. ROW_NUMBER() fonksiyonu, PARTITION sözcüğüyle kullanıldığı zaman parametre olarak aldığı kolonların değerine göre parçalı sıralama yapar. Yani aynı kayıtları kendi içerisinde gruplandırarak ardışık numaralandırır. Diğer farklı kayda geçtiği zaman yeniden 1’den başlayarak numaralandırır. Bu şekilde satırları numaralandırdıktan sonra araya ikinci bir tablo atmamak için de yine SQL 2005’in önemli özelliklerinden biri olan Common Table Expression(CTE) yöntemini kullanacağız. CTE, bir tabloyu yeniden tanımlamak ve bu tanımlayı referans alacak bir querynin çalıştırılmasıdır. Özellikle bir tablo üzerindeki yinelemeli işlemlerde kullanılır.

SELECT ROW_NUMBER() OVER (ORDER BY UserName ASC) AS ColumnId, * FROM L_User
TekraraBagliId UserName UserPwd
1 adem 789
2 adem 789
1 ahmet 123
2 ahmet 123
1 mehmet 456

Bu ifadeyi CTE ile birlikte kullanalım. Yapacağımız işlem basit; TekraraBagliId kolonu 1’den büyük olanları sileceğiz.

WITH TekrarliKayit AS
(	SELECT
	ROW_NUMBER() OVER (
		PARTITION BY UserName,UserPwd
		ORDER BY UserName ASC) AS TekraraBagliId,
	* FROM L_User
)

DELETE FROM TekrarliKayit WHERE TekraraBagliId>1

Unique Constraint’in olmadığı mükerrer kayıtlar” üzerine bir düşünce

  1. irfan Dölek

    Ahmet Kaymaz Bey..Tek kelime ile süpersiniz.Geçenlerde bu problemi aynen yaşamışdım.Harika bir makale..ellerinize sağlık..1000 ler selam..

    Cevapla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.