আমি ধরে নিই যে ডাটাবেসটি সর্বদা ডিফল্ট মানগুলি পরীক্ষা করে, যদি আমি সঠিক মান সরবরাহ করি তবে আমি একই কাজটি দু'বার করছি।
ওম, তুমি কেন ধরে নিবে? ;-)। প্রদত্ত ডিফল্ট একটি মান প্রদান করার জন্য বিদ্যমান থাকে যখন তারা যে কলামটি সংযুক্ত থাকে তা INSERT
বিবৃতিতে উপস্থিত না থাকে , আমি ঠিক এর বিপরীতটি ধরে নেব: যে সম্পর্কিত কলামটি INSERT
বিবৃতিতে উপস্থিত থাকলে সেগুলি সম্পূর্ণ উপেক্ষা করা হবে ।
ভাগ্যক্রমে, প্রশ্নটির এই বক্তব্যের কারণে আমাদের উভয়কেই কিছু অনুমান করার দরকার নেই:
আমি বেশিরভাগই পারফরম্যান্সে আগ্রহী।
কর্মক্ষমতা সম্পর্কে প্রশ্নগুলি প্রায় সর্বদা পরীক্ষামূলক able সুতরাং এসকিউএল সার্ভারকে (এখানে প্রকৃত কর্তৃত্ব) এই প্রশ্নের উত্তর দেওয়ার জন্য আমাদের কেবল একটি পরীক্ষা নিয়ে আসা উচিত।
সেটআপ
নিম্নলিখিত একবার চালান:
SET NOCOUNT ON;
-- DROP TABLE #HasDefault;
CREATE TABLE #HasDefault
(
[HasDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NULL,
[SomeDate] DATETIME NOT NULL DEFAULT (GETDATE())
);
-- DROP TABLE #NoDefault;
CREATE TABLE #NoDefault
(
[NoDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NULL,
[SomeDate] DATETIME NOT NULL
);
-- make sure that data file and Tran Log file are grown, if need be, ahead of time:
INSERT INTO #HasDefault ([SomeInt])
SELECT TOP (2000000) NULL
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
1A এবং 1B স্বতন্ত্রভাবে পরীক্ষাগুলি সম্পাদন করুন, একসাথে নয় যা সময়সীমাকে তত্পর করে। প্রত্যেকের জন্য গড় সময় নির্ধারণের জন্য একাধিকবার চালান।
পরীক্ষা 1 এ
TRUNCATE TABLE #HasDefault;
GO
PRINT '#HasDefault:';
SET STATISTICS TIME ON;
INSERT INTO #HasDefault ([SomeDate])
SELECT TOP (1000000) '2017-05-15 10:11:12.000'
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
SET STATISTICS TIME OFF;
GO
পরীক্ষা 1 বি
TRUNCATE TABLE #NoDefault;
GO
PRINT '#NoDefault:';
SET STATISTICS TIME ON;
INSERT INTO #NoDefault ([SomeDate])
SELECT TOP (1000000) '2017-05-15 10:11:12.000'
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
SET STATISTICS TIME OFF;
GO
পরীক্ষাগুলি 2A এবং 2B স্বতন্ত্রভাবে চালিত করুন, একসাথে নয় যা সময়সীমাকে তত্পর করে। প্রত্যেকের জন্য গড় সময় নির্ধারণের জন্য একাধিকবার চালান।
পরীক্ষা 2 এ
TRUNCATE TABLE #HasDefault;
GO
DECLARE @Counter INT = 0,
@StartTime DATETIME,
@EndTime DATETIME;
BEGIN TRAN;
--SET STATISTICS TIME ON;
SET @StartTime = GETDATE();
WHILE (@Counter < 100000)
BEGIN
INSERT INTO #HasDefault ([SomeDate]) VALUES ('2017-05-15 10:11:12.000');
SET @Counter = @Counter + 1;
END;
SET @EndTime = GETDATE();
--SET STATISTICS TIME OFF;
COMMIT TRAN;
PRINT DATEDIFF(MILLISECOND, @StartTime, @EndTime);
পরীক্ষা 2 বি
TRUNCATE TABLE #NoDefault;
GO
DECLARE @Counter INT = 0,
@StartTime DATETIME,
@EndTime DATETIME;
BEGIN TRAN;
--SET STATISTICS TIME ON;
SET @StartTime = GETDATE();
WHILE (@Counter < 100000)
BEGIN
INSERT INTO #NoDefault ([SomeDate]) VALUES ('2017-05-15 10:11:12.000');
SET @Counter = @Counter + 1;
END;
SET @EndTime = GETDATE();
--SET STATISTICS TIME OFF;
COMMIT TRAN;
PRINT DATEDIFF(MILLISECOND, @StartTime, @EndTime);
আপনার দেখতে হবে পরীক্ষা 1A এবং 1B এর মধ্যে সময় নির্ধারণের মধ্যে, বা 2A এবং 2B পরীক্ষার মধ্যে কোনও বাস্তব পার্থক্য নেই। সুতরাং, না, কোনও DEFAULT
সংজ্ঞায়িত তবে ব্যবহার নেই এমন কোনও পারফরম্যান্স পেনাল্টি নেই ।
এছাড়াও, কেবল উদ্দেশ্যমূলক আচরণের দলিল করার পাশাপাশি আপনার মনে রাখা দরকার যে আপনার সঞ্চিত পদ্ধতিতে ডিএমএল বিবৃতি সম্পূর্ণরূপে অন্তর্ভুক্ত থাকার বিষয়ে আপনারাই যত্নবান। সমর্থন ভাবেন না। ভবিষ্যতের বিকাশকারীরা এই সমস্ত সঞ্চিত পদ্ধতিতে সমস্ত ডিএমএল সজ্জিত করার আপনার ইচ্ছা সম্পর্কে সচেতন হতে পারে না, বা জানা থাকলেও যত্ন নিতে পারে। এবং আপনি চলে যাওয়ার পরে যে কেউ এই ডিবি বজায় রাখবে (অন্য কোনও প্রকল্প বা চাকরী) সে হয়তো যত্নশীল নয়, বা তারা যতই প্রতিবাদ জানায় না কেন কোনও ওআরএম ব্যবহার রোধ করতে সক্ষম হতে পারে না। সুতরাং, ডিফল্টস, এটি করতে সাহায্য করতে পারে যে তারা যখন লোকজনকে একটি "আউট" দেয় INSERT
, বিশেষত INSERT
একটি সমর্থন প্রতিনিধি দ্বারা সম্পাদিত একটি অ্যাড-হক , কারণ এটি একটি কলাম তাদের অন্তর্ভুক্ত করার দরকার নেই (এই কারণেই আমি সর্বদা নিরীক্ষার ক্ষেত্রে খেলাপি ব্যবহার করি না তারিখ কলাম)।
এবং, এটি আমার কাছে কেবল ঘটেছিল যে DEFAULT
সম্পর্কিত কলামটি INSERT
বিবৃতিতে উপস্থিত থাকলে একটি পরীক্ষা করা হয় কিনা তা বরং বরং উদ্দেশ্যমূলকভাবে এটি প্রদর্শিত হতে পারে : কেবল একটি অবৈধ মান সরবরাহ করে। নিম্নলিখিত পরীক্ষাটি ঠিক তা করে:
-- DROP TABLE #BadDefault;
CREATE TABLE #BadDefault
(
[BadDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NOT NULL DEFAULT (1 / 0)
);
INSERT INTO #BadDefault ([SomeInt]) VALUES (1234); -- Success!!!
SELECT * FROM #BadDefault; -- just to be sure ;-)
INSERT INTO #BadDefault ([SomeInt]) VALUES (DEFAULT); -- Error:
/*
Msg 8134, Level 16, State 1, Line xxxxx
Divide by zero error encountered.
The statement has been terminated.
*/
SELECT * FROM #BadDefault; -- just to be sure ;-)
GO
আপনি দেখতে পাচ্ছেন, যখন একটি কলাম (এবং একটি মান, মূলশব্দ নয় DEFAULT
) সরবরাহ করা হয় তখন ডিফল্টটি 100% উপেক্ষা করা হয়। আমরা এটি জানি কারণ INSERT
সফল হয়। তবে যদি ডিফল্টটি ব্যবহার করা হয়, তবে শেষ পর্যন্ত এটি কার্যকর করা হওয়ায় একটি ত্রুটি রয়েছে।
একটি ট্রিগার কার্যকর করার মধ্যে ডিফল্ট বাধা এড়ানোর কোনও উপায় আছে কি?
ডিফল্ট সীমাবদ্ধতাগুলি এড়াতে হবে (কমপক্ষে এই প্রসঙ্গে) সম্পূর্ণ অপ্রয়োজনীয়, পরিপূর্ণতার জন্য এটি লক্ষ করা যায় যে কেবল INSTEAD OF
ট্রিগারের মধ্যেই কোনও ডিফল্ট সীমাবদ্ধতা "এড়ানো" সম্ভব হবে তবে কোনও ট্রিগারের মধ্যে নয় not ট্রিগার তৈরিAFTER
করার জন্য ডকুমেন্টেশন অনুসারে :
ট্রিগার টেবিলে যদি প্রতিবন্ধকতাগুলি উপস্থিত থাকে তবে সেগুলি ট্রিগার নির্বাহের INSTEAD এর পরে এবং আফ্রিকার ট্রিগার মৃত্যুর আগে পরীক্ষা করা হয়। যদি সীমাবদ্ধতাগুলি লঙ্ঘন করা হয়, তবে ট্রিগার ক্রিয়াকলাপগুলি INSTEAD OF ফিরিয়ে আনা হবে এবং AFTER ট্রিগারটি বরখাস্ত করা হবে না।
অবশ্যই, একটি INSTEAD OF
ট্রিগার ব্যবহারের প্রয়োজন হবে:
- ডিফল্ট সীমাবদ্ধতা অক্ষম করা হচ্ছে
- একটি
AFTER
ট্রিগার তৈরি করা যা সীমাবদ্ধ করে তোলে
তবে, আমি ঠিক এটি করার পরামর্শ দিচ্ছি না।