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

Query Analyzer Add comments

Ö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

2 Responses to “Unique Constraint’in olmadığı mükerrer kayıtlar”

  1. irfan Dölek Says:

    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..

  2. Aziz Says:

    Mükemmel Bir Kaynak. Çok Teşekkür Ederim.

Leave a Reply


7 + = 8

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS GiriÅŸ