मुझे लगता है कि डेटाबेस हमेशा डिफ़ॉल्ट मान की जाँच कर रहा है, भले ही मैं सही मूल्य की आपूर्ति करता हूं, इसलिए मैं एक ही काम दो बार कर रहा हूं।
उम, आप ऐसा क्यों मानेंगे? ;-)। यह देखते हुए कि डिफॉल्ट्स एक मान प्रदान करने के लिए मौजूद हैं जब वे जिस कॉलम में संलग्न होते हैं वह INSERT
कथन में मौजूद नहीं होता है, मैं इसके विपरीत मानूंगा: यदि वे संबंधित कॉलम INSERT
स्टेटमेंट में मौजूद हैं तो उन्हें पूरी तरह से अनदेखा कर दिया जाता है ।
सौभाग्य से, हम में से किसी को भी इस कथन के कारण कुछ भी मानने की आवश्यकता नहीं है:
मुझे ज्यादातर प्रदर्शन पर दिलचस्पी है।
प्रदर्शन के बारे में प्रश्न लगभग हमेशा परीक्षण योग्य होते हैं। इसलिए हमें इस प्रश्न का उत्तर देने के लिए SQL सर्वर (यहाँ सही प्राधिकारी) की अनुमति देने के लिए एक परीक्षण की आवश्यकता है।
सेट अप
निम्नलिखित को एक बार चलाएं:
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;
परीक्षा 1 ए और 1 बी को व्यक्तिगत रूप से परीक्षण करें, न कि एक साथ जो समय सीमा को पूरा करता है। हर एक के लिए औसत टाइमिंग की समझ पाने के लिए हर बार कई बार दौड़ें।
टेस्ट 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);
आपको देखना चाहिए कि परीक्षण 1 ए और 1 बी के बीच, या परीक्षण 2 ए और 2 बी के बीच के समय में कोई वास्तविक अंतर नहीं है। तो, नहीं, कोई DEFAULT
परिभाषित नहीं है, लेकिन इसका उपयोग नहीं किया गया है।
इसके अलावा, केवल इच्छित व्यवहार का दस्तावेजीकरण करने के अलावा, आपको यह ध्यान रखने की आवश्यकता है कि यह ज्यादातर आप ही हैं जो डीएमएल स्टेटमेंट के बारे में परवाह करते हैं जो आपके संग्रहीत प्रक्रियाओं में पूरी तरह से निहित है। समर्थन करने वाले लोगों को परवाह नहीं है। भविष्य के डेवलपर्स को आपकी इच्छा के बारे में पता नहीं हो सकता है कि उन सभी डीएमएल को उन संग्रहीत प्रक्रियाओं में संलग्न किया गया है, या वे जानते हुए भी देखभाल करते हैं। और जो आपके जाने के बाद इस DB को बनाए रखता है (या तो किसी अन्य परियोजना या नौकरी) परवाह नहीं कर सकता है, या ORM के उपयोग को रोकने में सक्षम नहीं हो सकता है, चाहे वे कितना भी विरोध करें। इसलिए, डिफॉल्ट्स, इसमें मदद कर सकते हैं कि वे लोगों को "आउट" करते हैं 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
सफल होता है। लेकिन अगर डिफ़ॉल्ट का उपयोग किया जाता है, तो एक त्रुटि है क्योंकि इसे अंततः निष्पादित किया जा रहा है।
ट्रिगर निष्पादन के भीतर DEFAULT बाधा से बचने का एक तरीका है?
डिफ़ॉल्ट बाधाओं से बचने की आवश्यकता है (कम से कम इस संदर्भ में) पूरी तरह से अनावश्यक है, पूर्णता के लिए यह ध्यान दिया जा सकता है कि यह केवल एक INSTEAD OF
ट्रिगर के भीतर एक डिफ़ॉल्ट बाधा से "बचने" के लिए संभव होगा , लेकिन एक ट्रिगर के भीतर नहींAFTER
। के लिए दस्तावेज़ के अनुसार बनाएं TRIGGER :
यदि ट्रिगर लाइन पर बाधाएं मौजूद हैं, तो उन्हें ट्रिगर निष्पादन के INSTEAD और AFTER ट्रिगर निष्पादन से पहले चेक किया जाता है। यदि बाधाओं का उल्लंघन किया जाता है, तो ट्रिगर कार्रवाई के INSTEAD को वापस ले लिया जाता है और AFTER ट्रिगर को निकाल नहीं दिया जाता है।
बेशक, INSTEAD OF
ट्रिगर का उपयोग करने की आवश्यकता होगी:
- डिफ़ॉल्ट बाधा को अक्षम करना
- एक
AFTER
ट्रिगर बनाना जो बाधा को सक्षम करता है
हालाँकि, मैं ऐसा करने की सलाह नहीं दूंगा।