दो स्तंभों के संयोजन में अद्वितीय बाधा जोड़ें


149

मेरे पास एक मेज है और, किसी भी तरह, एक ही व्यक्ति मेरी Personतालिका में दो बार मिला । अभी, प्राथमिक कुंजी सिर्फ एक ऑटोनम्बर है लेकिन दो अन्य क्षेत्र हैं जो मौजूद हैं कि मैं अद्वितीय होने के लिए मजबूर करना चाहता हूं।

उदाहरण के लिए, क्षेत्र हैं:

ID  
Name  
Active  
PersonNumber  

मैं केवल 1 रिकॉर्ड करना चाहता हूं एक अद्वितीय व्यक्ति के साथ और Active = 1.
(इसलिए दो क्षेत्रों के संयोजन को अद्वितीय होना चाहिए)

SQL सर्वर में किसी मौजूदा टेबल पर सबसे अच्छा तरीका क्या है मैं इसे बना सकता हूं अगर कोई और किसी मौजूदा मूल्य के समान मूल्य के साथ एक सम्मिलित करता है, तो यह विफल हो जाता है इसलिए मुझे अपने आवेदन कोड में इस बारे में चिंता करने की आवश्यकता नहीं है।


3
आपको अपने एप्लिकेशन कोड में अभी भी इसके बारे में चिंता करनी होगी।
डेन ब्रुकुक

2
ठीक है, "इसके बारे में चिंता करने की ज़रूरत नहीं है" का मतलब क्या है? यदि कोई उपयोगकर्ता डुप्लिकेट सम्मिलित करने का प्रयास करता है, और SQL सर्वर ऐसा नहीं करता है, तो क्या आप उन्हें बताना नहीं चाहते हैं? लगता है जैसे अनुप्रयोग को इसके बारे में चिंता करने की ज़रूरत है।
आरोन बर्ट्रेंड

जवाबों:


219

एक बार जब आप अपना डुप्लिकेट हटा दें:

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

या

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

बेशक, इस उल्लंघन के लिए पहले जांच करना बेहतर हो सकता है, इससे पहले कि SQL सर्वर को पंक्ति सम्मिलित करने का प्रयास करने दें और एक अपवाद (अपवाद महंगे हैं) को वापस करने की कोशिश करें।

http://www.sqlperformance.com/2012/08/t-sql-queries/error-handling

http://www.mssqltips.com/sqlservertip/2632/checking-for-potential-constraint-violations-before-entering-sql-server-try-and-catch-logic/

यदि आप अनुप्रयोग में परिवर्तन किए बिना, एप्लिकेशन को बुदबुदाहट से अपवाद को रोकना चाहते हैं, तो आप INSTEAD OFट्रिगर का उपयोग कर सकते हैं :

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

लेकिन अगर आप उस उपयोगकर्ता को यह नहीं बताते हैं कि वे इंसर्ट नहीं करते हैं, तो वे आश्चर्यचकित हो जाते हैं कि डेटा क्यों नहीं है और कोई अपवाद नहीं बताया गया।


यहां EDIT एक ऐसा उदाहरण है जो आपके सवालों के समान नामों का उपयोग करते हुए भी आपसे जो पूछ रहा है, वैसा ही करता है और इसे साबित करता है। उपरोक्त विचारों को मानने से पहले आपको इसका प्रयास करना चाहिए केवल एक स्तंभ या दूसरे को संयोजन के विपरीत समझें ...

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

इस सब के बाद तालिका में डेटा:

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

अंतिम प्रविष्टि पर त्रुटि संदेश:

Msg 2627, स्तर 14, राज्य 1, लाइन 3 UNIQUE प्रमुख बाधा 'uq_Person' का उल्लंघन। डुप्लिकेट कुंजी को 'dbo.Person' ऑब्जेक्ट में सम्मिलित नहीं कर सकता। बयान समाप्त कर दिया गया है।


3
@ एलोरा हां, मुझे पूरा यकीन है कि मेरा जवाब दो स्तंभों पर अद्वितीयता के साथ है ।
हारून बर्ट्रेंड

2
यह नहीं कि प्रत्येक स्तंभ को अद्वितीय होना है, स्तंभों का संयोजन (संयोजन) अद्वितीय होना है। क्या इसका कोई मतलब है । ।
लीरा

14

यह जीयूआई में भी किया जा सकता है:

  1. तालिका "व्यक्ति" के तहत, अनुक्रमित पर राइट क्लिक करें
  2. न्यू इंडेक्स पर क्लिक / होवर करें
  3. गैर-संकुलित सूचकांक पर क्लिक करें ...

यहाँ छवि विवरण दर्ज करें

  1. एक डिफ़ॉल्ट इंडेक्स नाम दिया जाएगा, लेकिन आप इसे बदलना चाह सकते हैं।
  2. यूनिक चेकबॉक्स चेक करें
  3. Add ... बटन पर क्लिक करें

यहाँ छवि विवरण दर्ज करें

  1. अपने इच्छित कॉलमों की जाँच करें

यहाँ छवि विवरण दर्ज करें

  1. प्रत्येक विंडो में ओके पर क्लिक करें ।

1
अद्वितीय बाधा और अद्वितीय सूचकांक के बीच क्या अंतर है? क्योंकि जब आप विशिष्ट बाधा निर्धारित करते हैं, तो इसमें 900 बाइट्स सीमा होती है, लेकिन ऐसा लगता है कि अद्वितीय सूचकांक के पास नहीं है।
बत्तमीसी

2
कुछ नहीं संदर्भ के लिए इस लेख को देखें: blog.sqlauthority.com/2007/04/26/…
एली

मेरा new Indexक्लिक करने योग्य नहीं है यह अक्षम है :(
फैसल

4
@ फ़ैसल उस तालिका के लिए आपके द्वारा खोले गए परिणामों / डिज़ाइन विंडो को बंद करें और पुनः प्रयास करें।
कालगणना

@ फैसल ने यह जाँच की: stackoverflow.com/a/60014466/4654957
डिएगो

3

मेरे मामले में, मैं कई inactives और दो सक्रिय चाबियाँ, इस तरह का केवल एक संयोजन अनुमति देने के लिए की जरूरत:

UUL_USR_IDF  UUL_UND_IDF    UUL_ATUAL
137          18             0
137          19             0
137          20             1
137          21             0

यह काम करने लगता है:

CREATE UNIQUE NONCLUSTERED INDEX UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL
ON USER_UND(UUL_USR_IDF, UUL_ATUAL)
WHERE UUL_ATUAL = 1;

यहाँ मेरे परीक्षण के मामले हैं:

SELECT * FROM USER_UND WHERE UUL_USR_IDF = 137

insert into USER_UND values (137, 22, 1) --I CAN NOT => Cannot insert duplicate key row in object 'dbo.USER_UND' with unique index 'UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL'. The duplicate key value is (137, 1).
insert into USER_UND values (137, 23, 0) --I CAN
insert into USER_UND values (137, 24, 0) --I CAN

DELETE FROM USER_UND WHERE UUL_USR_ID = 137

insert into USER_UND values (137, 22, 1) --I CAN
insert into USER_UND values (137, 27, 1) --I CAN NOT => Cannot insert duplicate key row in object 'dbo.USER_UND' with unique index 'UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL'. The duplicate key value is (137, 1).
insert into USER_UND values (137, 28, 0) --I CAN
insert into USER_UND values (137, 29, 0) --I CAN

मैं यहां आपके परीक्षण मामले सहित आपकी सराहना करता हूं। यह एक सबसे अच्छा अभ्यास है जिसे मैं अधिक स्टैक ओवरफ्लो उत्तरों को अपनाना चाहता हूं।
जेरेमी कैनी

0

और अगर आपके पास बहुत सारे प्रश्न हैं, लेकिन हर बार एक ERROR संदेश नहीं देना चाहते हैं, तो आप यह कर सकते हैं:

CREATE UNIQUE NONCLUSTERED INDEX SK01 ON dbo.Person(ID,Name,Active,PersonNumber) 
WITH(IGNORE_DUP_KEY = ON)

यहाँ छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.