আমি কি এমন একটি অনন্য বাধা যুক্ত করতে পারি যা বিদ্যমান লঙ্ঘন উপেক্ষা করে?


40

আমার একটি টেবিল রয়েছে যার বর্তমানে একটি কলামে সদৃশ মান রয়েছে।

আমি এই ভুল অনুলিপিগুলি মুছে ফেলতে পারি না তবে আমি অতিরিক্ত অ-অনন্য মানগুলি যুক্ত হতে আটকাতে চাই।

আমি কি এমন একটি তৈরি করতে পারি UNIQUEযা বিদ্যমান সম্মতির জন্য পরীক্ষা করে না?

আমি ব্যবহার করার চেষ্টা করেছি NOCHECKকিন্তু ব্যর্থ হয়েছিল।

এই ক্ষেত্রে আমার কাছে একটি টেবিল রয়েছে যা লাইসেন্সিংয়ের তথ্য "কোম্পানির নাম" এর সাথে সম্পর্কিত করে

সম্পাদনা: একই "CompanyName" এর সাথে একাধিক সারি থাকা খারাপ ডেটা, তবে আমরা এই নকলগুলি এখনই সরাতে বা আপডেট করতে পারি না। একটি পদ্ধতির হ'ল INSERTএকটি স্টোরেজ পদ্ধতি ব্যবহার করা যা সদৃশদের জন্য ব্যর্থ হবে ... যদি এসকিউএল নিজস্বতা স্বতন্ত্রতা পরীক্ষা করে নেওয়া সম্ভব হত তবে তা অগ্রাধিকারযোগ্য।

এই তথ্য সংস্থার নাম দ্বারা অনুসন্ধান করা হয়। কয়েকটি বিদ্যমান নকলের জন্য এটির অর্থ হ'ল একাধিক সারি ফিরিয়ে দেওয়া এবং প্রদর্শিত হবে ... এটি ভুল হলেও এটি আমাদের ব্যবহারের ক্ষেত্রে গ্রহণযোগ্য। ভবিষ্যতে এটি প্রতিরোধ করা লক্ষ্য। আমার কাছে মন্তব্যগুলি থেকে মনে হয় যে সঞ্চিত পদ্ধতিতে আমাকে এই যুক্তিটি করতে হবে।


আপনি কি টেবিল পরিবর্তন করার অনুমতি পেয়েছেন (আরও একটি কলাম যুক্ত করুন)?
ypercubeᵀᴹ

দুর্ভাগ্যক্রমে @ টাইপকিউব না।
ম্যাথু

উত্তর:


33

উত্তরটি হল হ্যাঁ". আপনি এটি একটি ফিল্টার সূচক দিয়ে করতে পারেন ( ডকুমেন্টেশনের জন্য এখানে দেখুন )।

উদাহরণস্বরূপ, আপনি এটি করতে পারেন:

create unique index t_col on t(col) where id > 1000;

এটি পুরানো সারিগুলির পরিবর্তে কেবলমাত্র নতুন সারিগুলিতে অনন্য সূচক তৈরি করে । এই নির্দিষ্ট সূত্রটি বিদ্যমান মানগুলির সাথে সদৃশ করার অনুমতি দেবে।

আপনার কাছে যদি হাতে গোনা কয়েকটি ডুপ্লিকেট থাকে তবে আপনি এমন কিছু করতে পারেন:

create unique index t_col on t(col) where id not in (<list of ids for duplicate values here>);

2
এটি ভাল কিনা বা না "নির্ভর করে" পুরানো "বিদ্যমান আইটেমগুলি একই মান সহ নতুন আইটেম তৈরি করতে বাধা দেয় কিনা upon
সুপারক্যাট

1
@ সুপের্যাট । । বিদ্যমান নকল মান বাদে সবকিছুতে সূচক তৈরির জন্য আমি একটি বিকল্প সূত্র দিয়েছি form
গর্ডন লিনফ

1
পরবর্তী কাজ করার জন্য, একটিকে অবশ্যই নিশ্চিত করতে হবে যে নকলগুলি থাকা প্রতিটি স্বতন্ত্র মূল্যের জন্য একটি আইডিকে তালিকা থেকে বাদ দেওয়া হয়েছে, এবং এটিও নিশ্চিত করতে হবে যে তালিকাটি ইচ্ছাকৃতভাবে তালিকা থেকে বাদ দেওয়া হয়েছে তা যদি টেবিল থেকে সরিয়ে ফেলা হয় got সমান কী সহ একটি আইটেম তালিকা থেকে সরানো হবে।
সুপারক্যাট

@ সুপের্যাট । । আমি রাজী. আপডেটগুলি এবং মুছার জন্য সূচককে ধারাবাহিক রাখা আরও চ্যালেঞ্জিং কারণ আপনি ট্রিগারটিতে সূচিটি পুনরায় তৈরি করতে পারবেন না। যাইহোক, আমি ওপি থেকে ধারণা পেয়েছিলাম যে ডেটা - বা কমপক্ষে নকল - প্রায়শই পরিবর্তন হয় না, যদি তা হয় না।
গর্ডন লিনফ

আইডির তালিকার পরিবর্তে মানগুলির তালিকা বাদ দিবেন না কেন? তারপরে আপনাকে বাদ দেওয়া আইডির তালিকা থেকে ডুপ্লিকেট মান অনুযায়ী একটি আইডি বাদ দিতে হবে না
জেএমডি কোলেসেস

23

হ্যাঁ আপনি এটি করতে পারেন।

এখানে নকল সহ একটি টেবিল:

CREATE TABLE dbo.Party
  (
    ID INT NOT NULL
           IDENTITY ,
    CONSTRAINT PK_Party PRIMARY KEY ( ID ) ,
    Name VARCHAR(30) NOT NULL
  ) ;
GO

INSERT  INTO dbo.Party
        ( Name )
VALUES  ( 'Frodo Baggins' ),
        ( 'Luke Skywalker' ),
        ( 'Luke Skywalker' ),
        ( 'Harry Potter' ) ;
GO

আসুন আমরা বিদ্যমানগুলিকে উপেক্ষা করুন এবং নিশ্চিত করুন যে কোনও নতুন সদৃশ যোগ করা যাবে না:

-- Add a new column to mark grandfathered duplicates.
ALTER TABLE dbo.Party ADD IgnoreThisDuplicate INT NULL ;
GO

-- The *first* instance will be left NULL.
-- *Secondary* instances will be set to their ID (a unique value).
UPDATE  dbo.Party
SET     IgnoreThisDuplicate = ID
FROM    dbo.Party AS my
WHERE   EXISTS ( SELECT *
                 FROM   dbo.Party AS other
                 WHERE  other.Name = my.Name
                        AND other.ID < my.ID ) ;
GO

-- This constraint is not strictly necessary.
-- It prevents granting further exemptions beyond the ones we made above.
ALTER TABLE dbo.Party WITH NOCHECK
ADD CONSTRAINT CHK_Party_NoNewExemptions 
CHECK(IgnoreThisDuplicate IS NULL);
GO

SELECT * FROM dbo.Party;
GO

-- **THIS** is our pseudo-unique constraint.
-- It works because the grandfathered duplicates have a unique value (== their ID).
-- Non-grandfathered records just have NULL, which is not unique.
CREATE UNIQUE INDEX UNQ_Party_UniqueNewNames ON dbo.Party(Name, IgnoreThisDuplicate);
GO

আসুন আমরা এই সমাধানটি পরীক্ষা করি:

-- cannot add a name that exists
INSERT  INTO dbo.Party
        ( Name )
VALUES  ( 'Frodo Baggins' );

Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'.

-- cannot add a name that exists and has an ignored duplicate
INSERT  INTO dbo.Party
        ( Name )
VALUES  ( 'Luke Skywalker' );

Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'.


-- can add a new name 
INSERT  INTO dbo.Party
        ( Name )
VALUES  ( 'Hamlet' );

-- but only once
INSERT  INTO dbo.Party
        ( Name )
VALUES  ( 'Hamlet' );

Cannot insert duplicate key row in object 'dbo.Party' with unique index 'UNQ_Party_UniqueNewNames'.

4
তিনি টেবিলে কোনও কলাম যুক্ত করতে পারবেন না।
অ্যারন বারট্র্যান্ড

3
আমি পছন্দ করি যে এই উত্তরটি কীভাবে নূন্যমূল্যগুলিকে অ-মানক উপায়ে অনন্য সীমাবদ্ধভাবে কার্যকর কিছুতে পরিণত করা হয়। চালাকি কৌশল।
ypercubeᵀᴹ

@ ইয়পারকিউবিᵀᴹ, আপনি কী অনন্য প্রতিবন্ধকতাগুলির মধ্যে NUL পরিচালনা সম্পর্কে অ-মানক ব্যাখ্যা করতে পারেন? আপনি যা আশা করেছিলেন তার থেকে এটি কীভাবে আলাদা? ধন্যবাদ!
নোয়াচ

1
@ এসকিউএল সার্ভারে নোনাচ, একটি নালামযোগ্য UNIQUEকলামে একটি সীমাবদ্ধতা নিশ্চিত করে যে সেখানে সর্বাধিক একক NULLমান রয়েছে। এসকিউএল স্ট্যান্ডার্ড (এবং প্রায় সব অন্যান্য এসকিউএল ডিবিএমএস) বলে যে এটি কোনও সংখ্যক NULLমানকে (যেমন সীমাবদ্ধতা নাল মানকে উপেক্ষা করা উচিত) মঞ্জুরি দেয় ।
ypercubeᵀᴹ

@ ypercubeᵀᴹ সুতরাং এটি অন্য একটি ডিবিএমএসে প্রয়োগ করতে, আমাদের কেবল NULL এর পরিবর্তে ডিফল্ট 0 ব্যবহার করা উচিত। সঠিক?
নোয়াচ

16

ফিল্টার অনন্য সূচক একটি উজ্জ্বল ধারণা কিন্তু এটা একটি ছোটখাট অসুবিধা আছে - কোন ব্যাপার যদি আপনি ব্যবহার WHERE identity_column > <current value>শর্ত বা WHERE identity_column NOT IN (<list of ids for duplicate values here>)

প্রথম পদ্ধতির সাহায্যে আপনি এখনও ভবিষ্যতে সদৃশ ডেটা, বিদ্যমান (এখন) ডেটারের নকল সন্নিবেশ করতে সক্ষম হবেন। উদাহরণস্বরূপ, যদি আপনার এখন (কেবলমাত্র একটি) সারি থাকে CompanyName = 'Software Inc.'তবে সূচক একই সংস্থার নামের সাথে আরও একটি সারি সন্নিবেশ করতে নিষেধ করবে না। আপনি কেবল দু'বার চেষ্টা করলে এটি এটি নিষিদ্ধ করবে।

দ্বিতীয় পদ্ধতির সাথে একটি উন্নতি আছে, উপরেরটি কাজ করবে না (যা ভাল)) তবে, আপনি আরও ডুপ্লিকেট বা বিদ্যমান নকল সন্নিবেশ করতে সক্ষম হবেন। উদাহরণস্বরূপ, আপনার যদি এখন (দুই বা ততোধিক) সারি থাকে CompanyName = 'DoubleData Co.'তবে সূচক একই সংস্থার নামের সাথে আরও একটি সারি সন্নিবেশ করতে নিষেধ করবে না। আপনি কেবল দু'বার চেষ্টা করলে এটি এটি নিষিদ্ধ করবে।

(আপডেট) প্রতিটি ডুপ্লিকেট নামের জন্য, আপনি বাদ দেওয়া তালিকার একটি আইডি বাইরে রাখলে এটি সংশোধন করা যায়। যদি উপরের উদাহরণের মতো, সদৃশ CompanyName = DoubleData Co.এবং আইডি সহ 4 টি সারি থাকে 4,6,8,9, তবে বাদ পড়ার তালিকায় এই আইডিগুলির মধ্যে কেবল 3 টি থাকা উচিত।

দ্বিতীয় পদ্ধতির সাথে আরেকটি অসুবিধা হ'ল জটিল পরিস্থিতি (প্রথম স্থানটিতে কতগুলি নকল রয়েছে তার উপর কতটা জটিলতা নির্ভর করে), যেহেতু এসকিউএল-সার্ভার ফিল্টারড সূচকগুলির অংশটিতে NOT INঅপারেটরটিকে সমর্থন করে না WHERE। দেখুন এসকিউএল বেহালার । পরিবর্তে WHERE (CompanyID NOT IN (3,7,4,6,8,9)), আপনার এমন কিছু থাকতে হবে যেমন WHERE (CompanyID <> 3 AND CompanyID <> 7 AND CompanyID <> 4 AND CompanyID <> 6 AND CompanyID <> 8 AND CompanyID <> 9)আমি নিশ্চিত নই যে এই জাতীয় শর্তের সাথে দক্ষতার সাথে জড়িত রয়েছে কিনা, যদি আপনার শত শত নকল নাম থাকে।


আরেকটি সমাধান (@ অ্যালেক্স কুজনেটসভের অনুরূপ) হ'ল অন্য কলাম যুক্ত করা, র‌্যাঙ্ক সংখ্যার সাথে এটি বিশিষ্ট করা এবং এই কলাম সহ একটি অনন্য সূচক যুক্ত করা:

ALTER TABLE Company
  ADD Rn TINYINT DEFAULT 1;

UPDATE x
SET Rn = Rnk
FROM
  ( SELECT 
      CompanyID,
      Rn,
      Rnk = ROW_NUMBER() OVER (PARTITION BY CompanyName 
                               ORDER BY CompanyID)
    FROM Company 
  ) x ;

CREATE UNIQUE INDEX CompanyName_UQ 
  ON Company (CompanyName, Rn) ; 

তারপরে, সদৃশ নামের সাথে একটি সারি সন্নিবেশ করা DEFAULT 1সম্পত্তি এবং অনন্য সূচকের কারণে ব্যর্থ হবে । এটি এখনও 100% বুদ্ধিমান নয় (যদিও অ্যালেক্সের রয়েছে)। যদি বিবৃতিতে Rnস্পষ্টভাবে সেট করা INSERTথাকে বা Rnমানগুলি দূষিতভাবে আপডেট করা হয় তবে ডুপ্লিকেটগুলি এখনও পিছলে যাবে ।

এসকিউএল বেহালার-2


-2

অন্য বিকল্পটি হ'ল একটি স্কেলার ফাংশন লিখুন যা টেবিলে কোনও মান ইতিমধ্যে উপস্থিত রয়েছে কিনা তা পরীক্ষা করে এবং তারপরে একটি চেক সীমাবদ্ধতা থেকে সেই ফাংশনটি কল করে।

এটি পারফরম্যান্সে ভয়াবহ কাজ করবে।



হারুনের নির্দেশিত ইস্যুগুলি ছাড়াও, এই চেক সীমাবদ্ধতা কীভাবে যুক্ত করা যায় তাই এটি বিদ্যমান নকলকে উপেক্ষা করে উত্তরটি ব্যাখ্যা করে না।
ypercubeᵀᴹ

-2

আমি এটির জন্য অনুসন্ধান করছি - একটি অবিশ্বস্ত অনন্য সূচক তৈরি করুন যাতে বিদ্যমান খারাপ ডেটা উপেক্ষা করা হয়, তবে নতুন রেকর্ডগুলি ইতিমধ্যে বিদ্যমান যে কোনওটির সদৃশ হতে পারে না।

এই থ্রেডটি পড়ার সময়, আমার কাছে এটি আসে যে একটি ট্রিগার লেখার চেয়ে আরও ভাল সমাধান হ'ল ডুপ্লিকেটগুলির জন্য পিতামাতার টেবিলের বিপরীতে [সন্নিবেশিত] পরীক্ষা করা হবে এবং যদি এই টেবিলগুলির মধ্যে কোনও নকল উপস্থিত থাকে, রোলব্যাক ট্রান TR

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.