Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Thêm ràng buộc duy nhất vào sự kết hợp của hai cột

Khi bạn đã xóa (các) bản sao của mình:

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

hoặc

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

Tất nhiên, tốt hơn hết là bạn nên kiểm tra vi phạm này trước, trước khi cho phép SQL Server cố gắng chèn hàng và trả về một ngoại lệ (ngoại lệ rất đắt).

  • Tác động hiệu suất của các kỹ thuật xử lý lỗi khác nhau

  • Kiểm tra các vi phạm ràng buộc tiềm ẩn trước khi tham gia TRY / CATCH

Nếu bạn muốn ngăn các trường hợp ngoại lệ xuất hiện trong ứng dụng mà không thực hiện thay đổi đối với ứng dụng, bạn có thể sử dụng INSTEAD OF kích hoạt:

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

Nhưng nếu bạn không nói với người dùng rằng họ không thực hiện chèn, họ sẽ tự hỏi tại sao dữ liệu không có ở đó và không có ngoại lệ nào được báo cáo.

CHỈNH SỬA đây là một ví dụ thực hiện chính xác những gì bạn đang yêu cầu, thậm chí sử dụng cùng tên với câu hỏi của bạn và chứng minh điều đó. Bạn nên dùng thử trước khi giả định rằng các ý tưởng trên chỉ coi một cột này hay cột kia trái ngược với sự kết hợp ...

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

Dữ liệu trong bảng sau tất cả những điều này:

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

Thông báo lỗi trên phụ trang cuối cùng:

Msg 2627, Mức 14, Trạng thái 1, Dòng 3 Vi phạm ràng buộc KEY DUY NHẤT 'uq_Person'. Không thể chèn khóa trùng lặp vào đối tượng 'dbo.Person'. Câu lệnh đã bị chấm dứt.

Ngoài ra, gần đây tôi đã viết blog về giải pháp áp dụng một ràng buộc duy nhất cho hai cột theo một trong hai thứ tự :

  • Thực thi một ràng buộc duy nhất khi đơn đặt hàng không quan trọng


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thế tiến thoái lưỡng nan về đặt tên bảng:Tên số ít so với số nhiều

  2. Hợp nhất hai phân vùng thành một trong SQL Server (T-SQL)

  3. Triển khai SQL Server AlwaysOn Av available Groups trên Linux

  4. Làm cách nào để điền vào một cột với các số ngẫu nhiên trong SQL? Tôi nhận được cùng một giá trị trong mọi hàng

  5. 3 lĩnh vực sẽ được hưởng lợi từ việc sử dụng công cụ giám sát hiệu suất máy chủ SQL