Yinelenen satırları nasıl kaldırabilirim?


1285

Yinelenen satırları oldukça büyük bir SQL Servertablodan (yani 300.000'den fazla satır) kaldırmanın en iyi yolu nedir ?

Tabii ki satırlar, RowIDkimlik alanının varlığı nedeniyle mükemmel kopyalar olmayacak .

Benim masam

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

13
Bunu okuyan PostgreSQL kullanıcıları için hızlı ipucu (lotlar, ne sıklıkta bağlandığına bağlı olarak): Pg, CTE terimlerini güncellenebilir görünümler olarak göstermez, böylece DELETE FROMdoğrudan bir CTE terimini kullanamazsınız . Bkz. Stackoverflow.com/q/18439054/398670
Craig Ringer

@CraigRinger aynı Sybase için de geçerlidir - Kalan çözümleri burada topladım (PG ve diğerleri için de geçerli olmalıdır: stackoverflow.com/q/19544489/1855801 ( ROWID()varsa işlevi yalnızca RowID sütunu ile değiştirin )
maf-soft

12
Buraya bir uyarı eklemek için. Herhangi bir çoğaltma işlemini kaldırırken, ilk önce neleri sildiğinizi her zaman iki kez kontrol edin! Bu, iyi verileri yanlışlıkla silmenin çok yaygın olduğu alanlardan biridir.
Jeff Davis

Yanıtlar:


1142

Hiçbir boş değerlere varsayarsak, GROUP BYbenzersiz sütunları ve satır olarak RowId tutmak. Ardından, satır kimliği olmayan her şeyi silin:SELECTMIN (or MAX)

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

Bir tamsayı yerine bir GUID'niz olması durumunda,

MIN(RowId)

ile

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

327
Bu da işe yarar mı? DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
Georg Schölly

10
@Andriy - SQL Server'da sqlinthewild.co.za/index.php/2010/03/23/… 'LEFT JOIN den daha az verimlidir . Aynı site vs ile karşılaştırır . sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in 3 dışında bence en iyi performansı gösterir. Her üçü de, kendinden kaçınmakla birlikte bir plan oluşturacaktır. NOT EXISTS NOT INNOT EXISTSNOT EXISTS
Martin Smith

12
@Martin, @Georg: Bu yüzden küçük bir test yaptım. Burada açıklandığı gibi büyük bir tablo oluşturuldu ve dolduruldu: sqlinthewild.co.za/index.php/2010/03/23/… Daha sonra, biri LEFT JOIN + NEREDE NULL tekniği, diğeri NOT kullanarak iki SELECT üretildi Birinde. Sonra infaz planlarına devam ettim ve tahmin edin ne oldu? Sorgu maliyetleri, LEFT JOIN için% 18, NOT IN için% 82'ye karşıydı, bu benim için büyük bir sürpriz. Olmaması gereken bir şey yapmış olabilirim ya da tam tersi olabilirdi, eğer doğruysa gerçekten bilmek istiyorum.
Andriy M

16
@ GeorgSchölly zarif bir cevap verdi. Ben bir PHP hata benim yinelenen satırlar oluşturduğu bir tablo üzerinde kullandım.
Philip Kearns

12
Üzgünüz ama neden DELETE MyTable FROM MyTabledoğru sözdizimi? Tablo adının hemen arkasındaki DELETEbelgeyi burada belgede bir seçenek olarak koyarak görmüyorum . Bu başkaları tarafından görülüyorsa özür dilerim; Ben sadece öğrenmeye çalışıyorum SQL yeni başlayan biriyim. Daha da önemlisi neden işe yarıyor: tablonun adını oraya dahil etmek ya da etmemek arasındaki fark nedir?
levininja

760

Bunu yapmanın başka bir yolu da

; 

--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1;

ORDER BY (SELECT 0)Yukarıda bir kravat durumunda korumak için hangi satır keyfi olarak kullanıyorum .

RowIDÖrneğin , en sonuncuyu korumak içinORDER BY RowID DESC

Uygulama Planları

Bunun için yürütme planı, kendi kendine katılmayı gerektirmediği için genellikle kabul edilen cevaptan daha basit ve daha etkilidir.

Uygulama Planları

Ancak bu her zaman böyle değildir. Bir yerde GROUP BYçözüm yoluna gidilebilir bir durum olduğunu karma agrega bir dere agrega göre tercih edilecektir.

ROW_NUMBEROysa çözümü her zaman hemen hemen aynı planı verecektir GROUP BYstrateji daha esnektir.

Uygulama Planları

Karma toplam yaklaşımını destekleyebilecek faktörler

  • Bölümleme sütunlarında kullanışlı bir dizin yok
  • her grupta nispeten daha fazla kopyaya sahip nispeten daha az grup

Bu ikinci durumun uç sürümlerinde (her birinde çok sayıda yinelemeye sahip çok az grup varsa), yeni bir tabloya tutmak için satırları eklemeyi ve ardından TRUNCATEorijinali yeniden kaydetmeyi ve günlüğü en aza indirmek için bunları kopyalamayı bir satırların çok yüksek bir oranı.


28
Ekleyebilirsem: Kabul edilen cevap kullanan tablolarla çalışmaz uniqueidentifier. Bu çok daha basit ve herhangi bir masada mükemmel çalışıyor. Teşekkürler Martin.
BrunoLM

15
Bu harika bir cevap! Orada eski kopyaları fark etmeden önce eski PK'yi kaldırdığımda olay işe yaradı. +100
Mikael Eliasson

12
DBA.SE'de bu soruyu (bu cevapla) sorup cevaplamayı öneririm. Sonra bunu kanonik cevaplar listemize ekleyebiliriz .
Nick Chammas

16
Kabul edilen cevabın aksine, bu RowIdkarşılaştırmak için anahtar ( ) olmayan bir tablo üzerinde de çalıştı .
vossad01

8
Bu, tüm SQL sunucu sürümlerinde çalışmaz
David

150

Microsoft Destek sitesinde yinelenenleri kaldırmayla ilgili iyi bir makale var . Oldukça muhafazakar - her şeyi ayrı adımlarla yapmanıza izin veriyorlar - ancak büyük tablolara karşı iyi çalışmalıdır.

Muhtemelen bir HAVING cümlesi ile numaralandırılabilse de, geçmişte bunu yapmak için kendi kendine birleşmeleri kullandım:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField

mükemmel! Bu benim eski mariadb sürüm 10.1.xx yinelenen satırları kaldırmak için en verimli yolu olduğunu buldum. teşekkür ederim!
Sarhoş M

Çok daha basit ve anlaşılması kolay!
Marc

98

Aşağıdaki sorgu, yinelenen satırları silmek için kullanışlıdır. Bu örnekte tablo sahip IDbir kimlik sütunu olarak ve çift veriye sahip sütun vardır Column1, Column2ve Column3.

DELETE FROM TableName
WHERE  ID NOT IN (SELECT MAX(ID)
                  FROM   TableName
                  GROUP  BY Column1,
                            Column2,
                            Column3
                  /*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
                    nullable. Because of semantics of NOT IN (NULL) including the clause
                    below can simplify the plan*/
                  HAVING MAX(ID) IS NOT NULL) 

Aşağıdaki komut gösterileri kullanımı GROUP BY, HAVING, ORDER BYbir sorgu ve iadeler yinelenen sütuna ve sayımı sonuçları içinde.

SELECT YourColumnName,
       COUNT(*) TotalCount
FROM   YourTableName
GROUP  BY YourColumnName
HAVING COUNT(*) > 1
ORDER  BY COUNT(*) DESC 

1
İlk komut dosyasında MySQL hatası 'FROM yan tümcesinde güncelleme için' TableName 'hedef tablosunu belirtemezsiniz'
D.Rosado

D.Rosado zaten bildirilen hata dışında, ilk sorgunuz da çok yavaş. İlgili SELECT sorgusu, kurulumumu kabul edilen yanıttan + 20 kat daha uzun sürdü.
parvus

8
@parvus - Soru MySQL değil SQL Server olarak etiketlendi. Sözdizimi SQL Server'da iyidir. Ayrıca MySQL, alt sorguları optimize etmede kötü bir şekilde kötüdür, örneğin buraya bakın . Bu yanıt SQL Server'da iyidir. Aslında NOT INgenellikle daha iyi performans gösterir OUTER JOIN ... NULL. Ben HAVING MAX(ID) IS NOT NULLsemantik olarak burada
Martin Smith

2
PostgreSQL 8.4'te harika çalışıyor.
normalde

63
delete t1
from table t1, table t2
where t1.columnA = t2.columnA
and t1.rowid>t2.rowid

postgres:

delete
from table t1
using table t2
where t1.columnA = t2.columnA
and t1.rowid > t2.rowid

Neden bir SQL Server sorusuna Postgres çözümü yayınlamalıyım?
Lankymart

2
@Lankymart Çünkü postgres kullanıcıları da buraya geliyor. Bu cevabın puanına bakın.
Gabriel

2
Bunu burada , burada ve burada olduğu gibi bazı popüler SQL sorularında gördüm . OP cevabını aldı ve diğer herkes de yardım aldı. Sorun yok IMHO.
Gabriel

44
DELETE LU 
FROM   (SELECT *, 
               Row_number() 
                 OVER ( 
                   partition BY col1, col1, col3 
                   ORDER BY rowid DESC) [Row] 
        FROM   mytable) LU 
WHERE  [row] > 1 

1
Azure SQL DW bu iletiyi alıyorum: Bir FROM yan tümcesi şu anda bir DELETE deyiminde desteklenmiyor.
Amit

40

Bu, ilk satır hariç, yinelenen satırları silecektir

DELETE
FROM
    Mytable
WHERE
    RowID NOT IN (
        SELECT
            MIN(RowID)
        FROM
            Mytable
        GROUP BY
            Col1,
            Col2,
            Col3
    )

Bakınız ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )


10
MySQL için hata verecektir: Hata Kodu: 1093. FROM yan tümcesinde güncelleme için hedef tablo 'Mytable' belirtemezsiniz. ancak bu küçük değişiklik mysql için işe yarayacaktır: Mytable WOWE RowID'DEN OLMADAN SİL (TEMS OLARAK Mytable GRUP TARAFINDAN KİMLİK SEÇİN (MIN (RowID) SEÇİN)
Ritesh

35

Ben sql sunucu tablosundan yinelenen satırları silmek için CTE tercih ediyorum

bu makaleyi izlemenizi kesinlikle öneririz :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/

orijinal tutarak

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1

orijinali saklamadan

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)

24

Yinelenen Satırları Getirmek için:

SELECT
name, email, COUNT(*)
FROM 
users
GROUP BY
name, email
HAVING COUNT(*) > 1

Yinelenen Satırları Silmek için:

DELETE users 
WHERE rowid NOT IN 
(SELECT MIN(rowid)
FROM users
GROUP BY name, email);      

MySQL kullanıcıları için, her şeyden önce olması gerektiğini unutmayın DELETE FROM, ikincisi işe yaramaz, çünkü SELECTaynı tablodan DELETEgelemezsiniz. MySQL'de bu patlıyor MySQL error 1093.
Méhor Mé

23

Tam ve yinelenen satırları silmek için Hızlı ve Kirli (küçük tablolar için):

select  distinct * into t2 from t1;
delete from t1;
insert into t1 select *  from t2;
drop table t2;

3
Sorunun aslında tam olmayan çoğaltma (satır kimliği nedeniyle) belirlediğini unutmayın.
Dennis Jaheruddin

21

Ben okumayı daha kolay buldum ve çalıştırmadan önce silinecek doğrulamak için bir SELECT deyimi açmak çok kolay oldu, çünkü iç birleştirmek için count (*)> 1 çözüm sahip alt sorgu tercih.

--DELETE FROM table1 
--WHERE id IN ( 
     SELECT MIN(id) FROM table1 
     GROUP BY col1, col2, col3 
     -- could add a WHERE clause here to further filter
     HAVING count(*) > 1
--)

İç sorguda görünen tüm kayıtları silmez. Yalnızca kopyaları kaldırmamız ve orijinali korumamız gerekir.
Sandy

3
Yalnızca, seçim maddesindeki min (id) değerine göre en düşük kimliğe sahip olanı döndürüyorsunuz.
James Errico

2
Sorgunun ilk, ikinci ve son satırlarını kaldırın.
James Errico

7
Bu, tüm kopyaları temizlemez. Yinelenen 3 satırınız varsa, yalnızca MIN (id) içeren satırı seçer ve yinelenen iki satır bırakarak bu satırı siler.
Chloe

2
Yine de, bu ifadeyi tekrar tekrar tekrar tekrar kullandım, böylece bağlantı zaman aşımına uğramak veya bilgisayarın uyku moduna geçmesi yerine ilerleme kaydedilecekti. MAX(id)Son kopyaları ortadan kaldırmak için değiştirdim ve LIMIT 1000000tüm sorguyu taramak zorunda kalmayacak şekilde iç sorguya ekledim . Bu, ilerlemeyi saatlerce beklediğimiz diğer cevaplardan çok daha hızlı gösterdi. Tablo yönetilebilir bir boyuta getirildikten sonra, diğer sorgularla bitirebilirsiniz. İpucu: col1 / col2 / col3'ün gruplama ölçütü için dizinleri olduğundan emin olun.
Chloe

17
SELECT  DISTINCT *
      INTO tempdb.dbo.tmpTable
FROM myTable

TRUNCATE TABLE myTable
INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
DROP TABLE tempdb.dbo.tmpTable

5
MyTable'a yabancı anahtar referanslarınız varsa kesme işlemi çalışmaz.
Sameer Alibhai

15

Özel koşullar altında çalıştığı için çözümümü paylaşacağımı düşündüm. Benim durumumda yinelenen değerleri olan tablo yabancı bir anahtar yoktu (çünkü değerleri başka bir db çoğaltıldı).

begin transaction
-- create temp table with identical structure as source table
Select * Into #temp From tableName Where 1 = 2

-- insert distinct values into temp
insert into #temp 
select distinct * 
from  tableName

-- delete from source
delete from tableName 

-- insert into source from temp
insert into tableName 
select * 
from #temp

rollback transaction
-- if this works, change rollback to commit and execute again to keep you changes!!

Not: Böyle şeyler üzerinde çalışırken her zaman bir işlem kullanıyorum, bu sadece her şeyin bir bütün olarak yürütülmesini sağlamakla kalmaz, aynı zamanda hiçbir şey riske atmadan test etmeme de izin verir. Ama tabii ki sadece emin olmak için bir yedek almalısın ...


14

Bu sorgu benim için çok iyi bir performans gösterdi:

DELETE tbl
FROM
    MyTable tbl
WHERE
    EXISTS (
        SELECT
            *
        FROM
            MyTable tbl2
        WHERE
            tbl2.SameValue = tbl.SameValue
        AND tbl.IdUniqueValue < tbl2.IdUniqueValue
    )

2M'lik bir tablodan 30 saniyeden biraz daha uzun bir sürede 1M satırlarını sildi (% 50 kopya)


14

CTE kullanma. Fikir, yinelenen bir kayıt oluşturan bir veya daha fazla sütuna katılmak ve hangisini isterseniz onu kaldırmaktır:

;with cte as (
    select 
        min(PrimaryKey) as PrimaryKey
        UniqueColumn1,
        UniqueColumn2
    from dbo.DuplicatesTable 
    group by
        UniqueColumn1, UniqueColumn1
    having count(*) > 1
)
delete d
from dbo.DuplicatesTable d 
inner join cte on 
    d.PrimaryKey > cte.PrimaryKey and
    d.UniqueColumn1 = cte.UniqueColumn1 and 
    d.UniqueColumn2 = cte.UniqueColumn2;

1
Sanırım JOIN'ınızda bir AND eksik.
Justin R.

13

Yine başka bir kolay çözüm yapıştırılan linkten bulunabilir burada . Bunu kavramak kolay ve benzer sorunların çoğu için etkili gibi görünüyor. SQL Server için olsa da kullanılan kavram kabul edilebilir daha fazladır.

Bağlantı verilen sayfadaki ilgili bölümler şunlardır:

Bu verileri düşünün:

EMPLOYEE_ID ATTENDANCE_DATE
A001    2011-01-01
A001    2011-01-01
A002    2011-01-01
A002    2011-01-01
A002    2011-01-01
A003    2011-01-01

Peki bu yinelenen verileri nasıl silebiliriz?

İlk olarak, aşağıdaki kodu kullanarak tabloya bir kimlik sütunu ekleyin:

ALTER TABLE dbo.ATTENDANCE ADD AUTOID INT IDENTITY(1,1)  

Çözmek için aşağıdaki kodu kullanın:

DELETE FROM dbo.ATTENDANCE WHERE AUTOID NOT IN (SELECT MIN(AUTOID) _
    FROM dbo.ATTENDANCE GROUP BY EMPLOYEE_ID,ATTENDANCE_DATE) 

1
Yöntem oluşur hakkında bir kelime "etkili görünüyor", "Kolay kavramak" değil. Sadece link geçersiz olur hayal, ne faydası sonra yöntem olduğunu bilmek olurdu oldu kavramak ve etkili kolay? Lütfen yöntemin açıklamasının önemli bölümlerini postanıza eklemeyi düşünün, aksi takdirde bu bir cevap değildir.
Andriy M

Bu yöntem henüz tanımlanmış bir kimliğiniz olmayan tablolar için kullanışlıdır. Birincil anahtarı tanımlamak için genellikle kopyalardan kurtulmanız gerekir!
Jeff Davis

@JeffDavis - ROW_NUMBERSürüm, başlamadan önce yeni bir sütun eklemenin uzunluğuna gitmeye gerek kalmadan bu durum için iyi çalışır.
Martin Smith

12

İşte yinelenenleri kaldırma hakkında iyi bir makale .

Neden zor olduğunu açıklar: " SQL ilişkisel cebire dayalıdır ve ilişkisel cebirde yinelenemezler, çünkü bir kümede yinelemelere izin verilmez. "

Temp tablo çözeltisi ve iki mysql örneği.

Gelecekte, onu veritabanı düzeyinde veya uygulama açısından engelleyeceksiniz. Veritabanı düzeyini öneririm çünkü veritabanınız referans bütünlüğünü korumaktan sorumlu olmalıdır, geliştiriciler sadece sorunlara neden olacaktır;)


1
SQL çoklu kümelere dayanır. Ancak setlere dayansa bile, bu iki tuple (1, a) & (2, a) farklıdır.
Andrew

12

Tabiiki. Geçici bir tablo kullanın. Eğer "işe yarayan" tek, çok performanslı olmayan bir ifade istiyorsanız şu yolla gidebilirsiniz:

DELETE FROM MyTable WHERE NOT RowID IN
    (SELECT 
        (SELECT TOP 1 RowID FROM MyTable mt2 
        WHERE mt2.Col1 = mt.Col1 
        AND mt2.Col2 = mt.Col2 
        AND mt2.Col3 = mt.Col3) 
    FROM MyTable mt)

Temel olarak, tablodaki her satır için alt seçim, söz konusu satırla aynı olan tüm satırların en üst Satır Kimliğini bulur. Böylece "özgün" çoğaltılmamış satırları temsil eden bir RowID listesi ile sonuçlanır.


11

Yinelenmeyen satırları korumak için gereken bir tablo vardı. Hız veya verimlilik konusunda emin değilim.

DELETE FROM myTable WHERE RowID IN (
  SELECT MIN(RowID) AS IDNo FROM myTable
  GROUP BY Col1, Col2, Col3
  HAVING COUNT(*) = 2 )

7
Bu, en fazla 1 kopya olduğunu varsayar.
Martin Smith

Neden olmasın HAVING COUNT(*) > 1?
Philipp M

11

Bunu kullan

WITH tblTemp as
(
SELECT ROW_NUMBER() Over(PARTITION BY Name,Department ORDER BY Name)
   As RowNumber,* FROM <table_name>
)
DELETE FROM tblTemp where RowNumber >1

10

Diğer yol, aynı alanlarla ve Benzersiz Dizin ile yeni bir tablo oluşturmaktır . Ardından tüm verileri eski tablodan yeni tabloya taşıyın . Otomatik olarak SQL SERVER yoksay (yinelenen bir değer olacaksa ne yapılacağı hakkında bir seçenek vardır: yoksay, kes veya sth) yinelenen değerler. Yani aynı tablo yinelenen satırlar olmadan var. Benzersiz Dizin istemiyorsanız, aktarım verisinden sonra veriyi bırakabilirsiniz .

Özellikle daha büyük tablolar için, tüm verileri hızlı bir şekilde benzersiz şekilde dizine eklenmiş tablonuza aktarmak için DTS'yi (verileri içe / dışa aktarmak için SSIS paketi) kullanabilirsiniz. 7 milyon satır için sadece birkaç dakika sürer.


9

Aşağıdaki sorguyu kullanarak, tek veya birden çok sütuna dayalı yinelenen kayıtları silebiliriz. aşağıdaki sorgu iki sütuna göre siliniyor. tablo adı: testingve sütun adlarıempno,empname

DELETE FROM testing WHERE empno not IN (SELECT empno FROM (SELECT empno, ROW_NUMBER() OVER (PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
or empname not in
(select empname from (select empname,row_number() over(PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)

9
  1. Aynı yapıya sahip yeni boş tablo oluşturma

  2. Böyle bir sorgu yürüt

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) > 1
  3. Ardından bu sorguyu yürütün

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) = 1


7

Bu yaklaşımın yanı sıra yardımcı olabilir ve tüm SQL sunucularında çalışır: Oldukça sık sık sadece bir - iki kopya ve Ids ve kopyaların sayısı bilinir. Bu durumda:

SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0

7

Uygulama seviyesinden (maalesef). Çoğaltmayı önlemenin uygun yolunun benzersiz bir dizin kullanarak veritabanı düzeyinde olduğunu kabul ediyorum, ancak SQL Server 2005'te bir dizinin yalnızca 900 bayt olmasına izin verildi ve varchar (2048) alanım bunu uçurdu.

Ne kadar iyi performans göstereceğini bilmiyorum, ancak doğrudan bir indeksle yapamasanız bile, bunu uygulamak için bir tetikleyici yazabileceğinizi düşünüyorum. Gibi bir şey:

-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism 
ON stories 
after INSERT, UPDATE 
AS 
    DECLARE @cnt AS INT 

    SELECT @cnt = Count(*) 
    FROM   stories 
           INNER JOIN inserted 
                   ON ( stories.story = inserted.story 
                        AND stories.story_id != inserted.story_id ) 

    IF @cnt > 0 
      BEGIN 
          RAISERROR('plagiarism detected',16,1) 

          ROLLBACK TRANSACTION 
      END 

Ayrıca, varchar (2048) bana balık gibi geliyor (hayattaki bazı şeyler 2048 bayt, ancak oldukça nadirdir); gerçekten varchar (max) olmamalı mı?



7
DELETE
FROM
    table_name T1
WHERE
    rowid > (
        SELECT
            min(rowid)
        FROM
            table_name T2
        WHERE
            T1.column_name = T2.column_name
    );

Merhaba Teena, silme yorumundan sonra Alice adı T1 tablosunu kaçırdınız, aksi takdirde sözdizimi istisnası olacaktır.
Nagaraj M

6
CREATE TABLE car(Id int identity(1,1), PersonId int, CarId int)

INSERT INTO car(PersonId,CarId)
VALUES(1,2),(1,3),(1,2),(2,4)

--SELECT * FROM car

;WITH CTE as(
SELECT ROW_NUMBER() over (PARTITION BY personid,carid order by personid,carid) as rn,Id,PersonID,CarId from car)

DELETE FROM car where Id in(SELECT Id FROM CTE WHERE rn>1)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.