sql >> Database >  >> RDS >> Sqlserver

Unieke beperking toevoegen aan combinatie van twee kolommen

Nadat u uw duplicaat(en) heeft verwijderd:

ALTER TABLE dbo.yourtablename
  ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);

of

CREATE UNIQUE INDEX uq_yourtablename
  ON dbo.yourtablename(column1, column2);

Natuurlijk kan het vaak beter zijn om eerst op deze overtreding te controleren, voordat u SQL Server laat proberen de rij in te voegen en een uitzondering te retourneren (uitzonderingen zijn duur).

  • Invloed op de prestaties van verschillende technieken voor foutafhandeling

  • Controleren op mogelijke schendingen van beperkingen voordat TRY/CATCH wordt ingevoerd

Als u wilt voorkomen dat uitzonderingen naar de applicatie borrelen, zonder wijzigingen in de applicatie aan te brengen, kunt u een INSTEAD OF gebruiken trigger:

CREATE TRIGGER dbo.BlockDuplicatesYourTable
 ON dbo.YourTable
 INSTEAD OF INSERT
AS
BEGIN
  SET NOCOUNT ON;

  IF NOT EXISTS (SELECT 1 FROM inserted AS i 
    INNER JOIN dbo.YourTable AS t
    ON i.column1 = t.column1
    AND i.column2 = t.column2
  )
  BEGIN
    INSERT dbo.YourTable(column1, column2, ...)
      SELECT column1, column2, ... FROM inserted;
  END
  ELSE
  BEGIN
    PRINT 'Did nothing.';
  END
END
GO

Maar als je de gebruiker niet vertelt dat ze de invoeging niet hebben uitgevoerd, zullen ze zich afvragen waarom de gegevens er niet zijn en er is geen uitzondering gemeld.

BEWERKEN hier is een voorbeeld dat precies doet wat je vraagt, zelfs met dezelfde namen als je vraag, en het bewijst. Je moet het eerst uitproberen voordat je aanneemt dat de bovenstaande ideeën alleen de ene of de andere kolom behandelen in plaats van de combinatie...

USE tempdb;
GO

CREATE TABLE dbo.Person
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  Name NVARCHAR(32),
  Active BIT,
  PersonNumber INT
);
GO

ALTER TABLE dbo.Person 
  ADD CONSTRAINT uq_Person UNIQUE(PersonNumber, Active);
GO

-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 1, 22);
GO

-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 0, 22);
GO

-- fails:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 1, 22);
GO

Gegevens in de tabel na dit alles:

ID   Name   Active PersonNumber
---- ------ ------ ------------
1    foo    1      22
2    foo    0      22

Foutmelding op de laatste invoeging:

Msg 2627, niveau 14, staat 1, regel 3 Schending van UNIQUE KEY-beperking 'uq_Person'. Kan geen dubbele sleutel invoegen in object 'dbo.Person'. De instructie is beëindigd.

Ook heb ik recentelijk geblogd over een oplossing voor het toepassen van een unieke beperking op twee kolommen in willekeurige volgorde :

  • Een unieke beperking afdwingen waar volgorde er niet toe doet


  1. Behoud regelonderbrekingen van TextArea bij schrijven naar MySQL

  2. Hoe strftime en datetime correct te gebruiken met behulp van de Room-bibliotheek?

  3. Hoe rijen met null-waarden te filteren in Select-instructie in SQL Server - SQL Server / TSQL-zelfstudie, deel 110

  4. MySql krijgt records of gegevens per dag, week, maand en jaar