চেক সংযোজনের সাথে চেক সংস্থার পরে বনাম বনাম সংযোজন


133

আমি এসকিউএল সার্ভার ২০০৮ এর জন্য অ্যাডভেঞ্চার ওয়ার্কসের নমুনা ডাটাবেসটি দেখছি এবং আমি তাদের তৈরি স্ক্রিপ্টগুলিতে দেখতে পাচ্ছি যে তারা নিম্নলিখিত ব্যবহারের ঝোঁক রয়েছে:

ALTER TABLE [Production].[ProductCostHistory] WITH CHECK ADD 
CONSTRAINT [FK_ProductCostHistory_Product_ProductID] FOREIGN KEY([ProductID])
  REFERENCES [Production].[Product] ([ProductID])
GO

সঙ্গে সঙ্গে অনুসরণ:

ALTER TABLE [Production].[ProductCostHistory] CHECK CONSTRAINT     
[FK_ProductCostHistory_Product_ProductID]
GO

আমি এটি বিদেশী কী (এখানে যেমন), অনন্য বাধা এবং নিয়মিত CHECKসীমাবদ্ধতার জন্য দেখতে পাচ্ছি ; DEFAULTসীমাবদ্ধতাগুলি নিয়মিত ফর্ম্যাট ব্যবহার করে যেমন এর সাথে আমি আরও পরিচিত:

ALTER TABLE [Production].[ProductCostHistory] ADD  CONSTRAINT  
[DF_ProductCostHistory_ModifiedDate]  DEFAULT (getdate()) FOR [ModifiedDate]
GO

দ্বিতীয়টি বনাম প্রথম উপায়ে করার মধ্যে পার্থক্য, যদি কোনও হয়?

উত্তর:


94

প্রথম বাক্য গঠনটি অপ্রয়োজনীয় - নতুন সীমাবদ্ধতার জন্য চেকের সাথে চেকটি ডিফল্ট এবং ডিফল্ট হিসাবেও সীমাবদ্ধতা চালু করা হয় is

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


12
দেখে মনে হচ্ছে না যে চেক আসলে ডিফল্ট, এটি কেবলমাত্র নতুন ডেটার জন্য ডিফল্ট। থেকে msdn.microsoft.com/en-us/library/ms190273.aspx : "নির্দিষ্ট করা নেই, তাহলে সঙ্গে চেক নতুন সীমাবদ্ধতার জন্য অধিকৃত হয়, এবং NOCHECK আবার সক্ষম সীমাবদ্ধতার জন্য অধিকৃত হয়।"
জয়ন রিজভী

8
@ জয়নরিজভি: নতুন ডেটা নয়, নতুন বাধা। আপনি যদি কোনও সীমাবদ্ধতা অক্ষম করেন ALTER TABLE foo NOCHECK CONSTRAINT fk_bএবং তারপরে এটি পুনরায় সক্ষম ALTER TABLE foo CHECK CONSTRAINT fk_bকরেন তবে সীমাবদ্ধতা যাচাই করে না। ALTER TABLE foo WITH CHECK CHECK CONSTRAINT fk_bতথ্য যাচাই করার জন্য প্রয়োজনীয়।
jmoreno

2
প্রাথমিকভাবে এটি পড়ার বিষয়টি আমার কাছে পরিষ্কার ছিল না। দ্বিতীয় (রিডানড্যান্ট) লাইনটি সীমাবদ্ধতাটি চালু করার ফাংশন। যেহেতু সীমাবদ্ধতা ডিফল্টরূপে চালু রয়েছে, তাই দ্বিতীয় লাইনটি অপ্রয়োজনীয়।
অন্ধচিকিত্সা

47

এটি কীভাবে কাজ করে তা প্রদর্শন করতে -

CREATE TABLE T1 (ID INT NOT NULL, SomeVal CHAR(1));
ALTER TABLE T1 ADD CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED (ID);

CREATE TABLE T2 (FKID INT, SomeOtherVal CHAR(2));

INSERT T1 (ID, SomeVal) SELECT 1, 'A';
INSERT T1 (ID, SomeVal) SELECT 2, 'B';

INSERT T2 (FKID, SomeOtherVal) SELECT 1, 'A1';
INSERT T2 (FKID, SomeOtherVal) SELECT 1, 'A2';
INSERT T2 (FKID, SomeOtherVal) SELECT 2, 'B1';
INSERT T2 (FKID, SomeOtherVal) SELECT 2, 'B2';
INSERT T2 (FKID, SomeOtherVal) SELECT 3, 'C1';  --orphan
INSERT T2 (FKID, SomeOtherVal) SELECT 3, 'C2';  --orphan

--Add the FK CONSTRAINT will fail because of existing orphaned records
ALTER TABLE T2 ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);   --fails

--Same as ADD above, but explicitly states the intent to CHECK the FK values before creating the CONSTRAINT
ALTER TABLE T2 WITH CHECK ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);    --fails

--Add the CONSTRAINT without checking existing values
ALTER TABLE T2 WITH NOCHECK ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);  --succeeds
ALTER TABLE T2 CHECK CONSTRAINT FK_T2_T1;   --succeeds since the CONSTRAINT is attributed as NOCHECK

--Attempt to enable CONSTRAINT fails due to orphans
ALTER TABLE T2 WITH CHECK CHECK CONSTRAINT FK_T2_T1;    --fails

--Remove orphans
DELETE FROM T2 WHERE FKID NOT IN (SELECT ID FROM T1);

--Enabling the CONSTRAINT succeeds
ALTER TABLE T2 WITH CHECK CHECK CONSTRAINT FK_T2_T1;    --succeeds; orphans removed

--Clean up
DROP TABLE T2;
DROP TABLE T1;

7
পরিষ্কার করুন - DROP TABLE T2; DROP TABLE T1;
গ্রিম

8
আমি উড়ে যাওয়ার মাধ্যমে রাতে কপি-এবং-পাস্টারদের সহায়তা করতে আপনার প্রকৃত উত্তরে আপনার মন্তব্য থেকে ক্লিন-আপ কোড যুক্ত করেছি।
mwolfe02

18
"নাইট কপি-অ্যান্ড-পাস্টার ফ্লাই বাই" কিছুটা নেতিবাচক বলে মনে হচ্ছে। আমি নিজেকে সেই স্ট্যাক ব্যবহারকারীদের মধ্যে অন্যতম বিবেচনা করব (আরও ইতিবাচক শব্দের জন্য ...) "যারা এই ধরণের বিস্তারিত উদাহরণ অত্যন্ত মূল্যবান বলে মনে করেন"।
গাটেক থমাস

2
নির্দোষ বা না, 'রাতের বেলা উড়ে' মনে হয় এটি আমাকে পুরোপুরি বর্ণনা করে।
সানপিট

21

বিশ্বস্ত প্রতিবন্ধকতা সম্পর্কে উপরোক্ত দুর্দান্ত মন্তব্যে আরও:

select * from sys.foreign_keys where is_not_trusted = 1 ;
select * from sys.check_constraints where is_not_trusted = 1 ;

একটি অবিশ্বস্ত সীমাবদ্ধতা, এর নামটি যেমন বোঝায়, ঠিক এখনই টেবিলের ডেটার স্থিতি সঠিকভাবে উপস্থাপন করার জন্য বিশ্বাস করা যায় না। এটি যাইহোক, তবে ভবিষ্যতে ডেটা যুক্ত এবং সংশোধিত ডেটা পরীক্ষা করতে বিশ্বাসযোগ্য হতে পারে।

অতিরিক্তভাবে, অবিশ্বস্ত সীমাবদ্ধতা ক্যোয়ারী অপটিমাইজারের দ্বারা উপেক্ষা করা হয়।

"চেক" শব্দের তিনটি অর্থ সহ চেক সীমাবদ্ধতা এবং বিদেশী কী সীমাবদ্ধতা সক্ষম করার কোডটি বেশ খারাপ।

ALTER TABLE [Production].[ProductCostHistory] 
WITH CHECK -- This means "Check the existing data in the table".
CHECK CONSTRAINT -- This means "enable the check or foreign key constraint".
[FK_ProductCostHistory_Product_ProductID] -- The name of the check or foreign key constraint, or "ALL".

15

WITH NOCHECK যখন কোনও টেবিলে বিদ্যমান ডেটা থাকে যা সংজ্ঞায়িত হিসাবে সীমাবদ্ধতার সাথে খাপ খায় না এবং আপনি যে নতুন প্রতিবন্ধকতাটি প্রয়োগ করছেন তা পুরোপুরি চালানো চান না ...


13

WITH CHECK সত্যই এটি পূর্বনির্ধারিত আচরণ তবে আপনার কোডিংয়ের মধ্যে অন্তর্ভুক্ত করা ভাল অনুশীলন।

বিকল্প আচরণটি অবশ্যই ব্যবহারযোগ্য WITH NOCHECK, সুতরাং আপনার উদ্দেশ্যগুলি স্পষ্টভাবে সংজ্ঞায়িত করা ভাল। আপনি যখন ইনলাইন পার্টিশনগুলি পরিবর্তন / পরিবর্তন / স্যুইচ করে চলেছেন তখন এটি প্রায়শই ব্যবহৃত হয়।


9

বিদেশী কী এবং চেক সীমাবদ্ধতার বিশ্বাসযোগ্য বা অবিশ্বস্ত হওয়ার পাশাপাশি সক্ষম এবং অক্ষম হওয়ার ধারণা রয়েছে। ALTER TABLEসম্পূর্ণ তথ্যের জন্য এমএসডিএন পৃষ্ঠা দেখুন ।

WITH CHECKনতুন বিদেশী কী এবং চেক সীমাবদ্ধতা যুক্ত করার WITH NOCHECKজন্য এটি ডিফল্ট , অক্ষম বিদেশী কী এবং চেক সীমাবদ্ধতাগুলিকে পুনরায় সক্ষম করার জন্য ডিফল্ট। পার্থক্য সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ।

এই কথাটি বলার পরে, ইউটিলিটিগুলি দ্বারা উত্পন্ন কোনও আপাত বিব্রত বিবৃতি কেবল সুরক্ষা এবং / অথবা কোডিংয়ের স্বাচ্ছন্দ্যের জন্য রয়েছে। তাদের সম্পর্কে চিন্তা করবেন না।


আপনি কি এই লিঙ্কটি উল্লেখ করছেন: এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms190273.aspx ? এর অর্থ কি এই যে আমাদের প্রতিবন্ধকতার জন্য এটি করার পরিবর্তে সমস্ত চেক চেক পরীক্ষা করে একটি টেবিল টেবিলটি করতে হবে?
হেনরিক স্টাউন পুলসন

@ হেনরিকসটেনপলসন: হ্যাঁ সেই লিঙ্কটি। স্বতন্ত্রভাবে প্রতিটি প্রতিবন্ধকতা আপনাকে সক্ষম করে এমন কিছু নেই, তবে WITH CHECK CHECK CONSTRAINTতাদের আস্থা রাখতে আপনার বলার দরকার নেই ।
খ্রিস্টান হাইটার

আমি চেষ্টা করেছি; আমি "অল্টার টেবিলে [dfm] চালিয়েছি [ তবে এফকে এখনও ইস_ নট_বিস্তারিত = 1 রয়েছে। তারপরে আমি এফকে ফেলে দিয়েছি এবং এটিকে "উইথ চেক চেক" দিয়ে পুনরায় তৈরি করেছি এবং এখন আমার ইস_নট_রোস্টড = 0 রয়েছে। শেষ পর্যন্ত. তুমি কি জানো কেন? দয়া করে মনে রাখবেন যে আমি সর্বদা is_not_for_replication = 0 পেয়েছি
হেনরিক

@ হেনরিক স্টাটেনপলসন: আমি জানি না, এটি সবসময় আমার পক্ষে ভাল কাজ করে। আমি select * from sys.objects where [type] in ('C', 'F') and (objectproperty([object_id], 'CnstIsDisabled') = 1 or objectproperty([object_id], 'CnstIsNotTrusted') = 1)অক্ষম এবং অবিশ্বস্ত সীমাবদ্ধতা সন্ধান করার মতো একটি কোয়েরি চালাচ্ছি । উপরের মতো যথাযথ অল্টার টেবিলের বিবৃতি জারি করার পরে, সেই সীমাবদ্ধতাগুলি ক্যোয়ারী থেকে অদৃশ্য হয়ে যায়, তাই আমি এটি কাজ করে দেখতে পারি।
খ্রিস্টান হাইটার

2
@ হেনরিক স্টাটেনপলসন, কারণ এটি_পরিচালনের পতাকাটি 1 এ সেট করা হয়েছে কারণ এটি প্রতিবন্ধকে বিশ্বাসযোগ্য নয় as নাম নির্বাচন, তৈরি_ তারিখ, সংশোধন_ তারিখ, is_disक्षम, is_not_for_replication, is_not_trusted FROM sys.foreign_keys যেখানে হয়_নাট_বিস্তারিত = 1 সেক্ষেত্রে আপনাকে সীমাবদ্ধতাটি ড্রপ এবং পুনরায় তৈরি করতে হবে। আমি এটিকে সম্পূর্ণ করতে এই ব্যবহার করি gist.github.com/smoothdeveloper/ea48e43aead426248c0f মনে রাখবেন যে এই স্ক্রিপ্টে মুছে ফেলা এবং আপডেট করা সুনির্দিষ্ট নয় এবং আপনার এটি অ্যাকাউন্টে নেওয়া উচিত।
কুকলেই

8

একটি ডেটাবেসে অবিশ্বস্ত চুক্তি সনাক্ত এবং সংশোধন করতে সহায়তা করার জন্য আমি এখানে কিছু কোড লিখেছি। এটি প্রতিটি সমস্যা সমাধানের জন্য কোড উত্পন্ন করে।

    ;WITH Untrusted (ConstraintType, ConstraintName, ConstraintTable, ParentTable, IsDisabled, IsNotForReplication, IsNotTrusted, RowIndex) AS
(
    SELECT 
        'Untrusted FOREIGN KEY' AS FKType
        , fk.name AS FKName
        , OBJECT_NAME( fk.parent_object_id) AS FKTableName
        , OBJECT_NAME( fk.referenced_object_id) AS PKTableName 
        , fk.is_disabled
        , fk.is_not_for_replication
        , fk.is_not_trusted
        , ROW_NUMBER() OVER (ORDER BY OBJECT_NAME( fk.parent_object_id), OBJECT_NAME( fk.referenced_object_id), fk.name) AS RowIndex
    FROM 
        sys.foreign_keys fk 
    WHERE 
        is_ms_shipped = 0 
        AND fk.is_not_trusted = 1       

    UNION ALL

    SELECT 
        'Untrusted CHECK' AS KType
        , cc.name AS CKName
        , OBJECT_NAME( cc.parent_object_id) AS CKTableName
        , NULL AS ParentTable
        , cc.is_disabled
        , cc.is_not_for_replication
        , cc.is_not_trusted
        , ROW_NUMBER() OVER (ORDER BY OBJECT_NAME( cc.parent_object_id), cc.name) AS RowIndex
    FROM 
        sys.check_constraints cc 
    WHERE 
        cc.is_ms_shipped = 0
        AND cc.is_not_trusted = 1

)
SELECT 
    u.ConstraintType
    , u.ConstraintName
    , u.ConstraintTable
    , u.ParentTable
    , u.IsDisabled
    , u.IsNotForReplication
    , u.IsNotTrusted
    , u.RowIndex
    , 'RAISERROR( ''Now CHECKing {%i of %i)--> %s ON TABLE %s'', 0, 1' 
        + ', ' + CAST( u.RowIndex AS VARCHAR(64))
        + ', ' + CAST( x.CommandCount AS VARCHAR(64))
        + ', ' + '''' + QUOTENAME( u.ConstraintName) + '''' 
        + ', ' + '''' + QUOTENAME( u.ConstraintTable) + '''' 
        + ') WITH NOWAIT;'
    + 'ALTER TABLE ' + QUOTENAME( u.ConstraintTable) + ' WITH CHECK CHECK CONSTRAINT ' + QUOTENAME( u.ConstraintName) + ';' AS FIX_SQL
FROM Untrusted u
CROSS APPLY (SELECT COUNT(*) AS CommandCount FROM Untrusted WHERE ConstraintType = u.ConstraintType) x
ORDER BY ConstraintType, ConstraintTable, ParentTable;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.