Database
 sql >> डेटाबेस >  >> RDS >> Database

टेबल एक्सप्रेशन के मूल तत्व, भाग 10 - दृश्य, चुनें *, और डीडीएल परिवर्तन

टेबल एक्सप्रेशन पर श्रृंखला के हिस्से के रूप में, पिछले महीने मैंने विचारों का कवरेज शुरू किया था। विशेष रूप से, मैंने विचारों के तार्किक पहलुओं का कवरेज शुरू किया, और उनके डिजाइन की तुलना व्युत्पन्न तालिकाओं और सीटीई के साथ की। इस महीने मैं SELECT * और DDL परिवर्तनों पर अपना ध्यान केंद्रित करते हुए, विचारों के तार्किक पहलुओं की कवरेज जारी रखने जा रहा हूँ।

इस लेख में मैं जिस कोड का उपयोग कर रहा हूं, उसे किसी भी डेटाबेस में निष्पादित किया जा सकता है, लेकिन मेरे डेमो में, मैं TSQLV5 का उपयोग कर रहा हूं - वही नमूना डेटाबेस जो मैंने पिछले लेखों में उपयोग किया था। आप यहां TSQLV5 बनाने और पॉप्युलेट करने वाली स्क्रिप्ट और इसके ईआर आरेख यहां पा सकते हैं।

दृश्य की आंतरिक क्वेरी में SELECT * का उपयोग करना एक बुरा विचार है

पिछले महीने के लेख के समापन खंड में मैंने विचार के लिए भोजन के रूप में एक प्रश्न रखा था। मैंने समझाया कि श्रृंखला में पहले मैंने व्युत्पन्न तालिकाओं और सीटीई के साथ उपयोग की जाने वाली आंतरिक तालिका अभिव्यक्तियों में चयन * का उपयोग करने के पक्ष में एक मामला बनाया था। यदि आपको अपनी स्मृति को ताज़ा करने की आवश्यकता है, तो विवरण के लिए श्रृंखला में भाग 3 देखें। फिर मैंने आपको यह सोचने के लिए कहा कि क्या वही अनुशंसा अभी भी दृश्य को परिभाषित करने के लिए उपयोग की जाने वाली आंतरिक तालिका अभिव्यक्ति के लिए मान्य होगी। शायद इस खंड का शीर्षक पहले से ही एक बिगाड़ने वाला था, लेकिन मैं बल्ले से सही कहूँगा कि विचारों के साथ यह वास्तव में एक बहुत बुरा विचार है।

मैं उन विचारों से शुरू करूंगा जो SCHEMABINDING विशेषता के साथ परिभाषित नहीं हैं, जो संबंधित वस्तुओं के लिए प्रासंगिक डीडीएल परिवर्तनों को रोकता है, और फिर समझाता है कि जब आप इस विशेषता का उपयोग करते हैं तो चीजें कैसे बदलती हैं।

मैं सीधे एक उदाहरण पर जाता हूँ क्योंकि यह मेरा तर्क प्रस्तुत करने का सबसे आसान तरीका होगा।

dbo.T1 नामक तालिका बनाने के लिए निम्न कोड का उपयोग करें और तालिका के सामने SELECT * वाली क्वेरी के आधार पर dbo.V1 नामक दृश्य बनाएं:

TSQLV5 का उपयोग करें; ड्रॉप व्यू अगर मौजूद है dbo.V1; ड्रॉप टेबल अगर मौजूद है तो dbo.T1; GO CREATE TABLE dbo.T1 (कीकॉल इंट नॉट न्यूल आइडेंटिटी कंस्ट्रेंट PK_T1 प्राइमरी की, इंट नॉट नॉट न्यूल, चारकोल वर्चर (10) नॉट न्यूल); dbo.T1(intcol, charcol) VALUES (10, 'A'), (20, 'B') में INSERT करें; dbo.V1AS सेलेक्ट करें या बदलें dbo.T1 से चुनें; GO

ध्यान दें कि तालिका में वर्तमान में कॉलम keycol, intcol और charcol हैं।

दृश्य को क्वेरी करने के लिए निम्न कोड का उपयोग करें:

dbo.V1 से * चुनें;

आपको निम्न आउटपुट मिलता है:

कीकोल intcol charcol-----------------------------------1 10 A2 20B

यहां कुछ खास नहीं है।

जब आप कोई दृश्य बनाते हैं, तो SQL सर्वर कई कैटलॉग ऑब्जेक्ट में मेटाडेटा जानकारी रिकॉर्ड करता है। यह कुछ सामान्य जानकारी को रिकॉर्ड करता है, जिसे आप sys.views के माध्यम से क्वेरी कर सकते हैं, दृश्य परिभाषा जिसे आप sys.sql_modules के माध्यम से क्वेरी कर सकते हैं, कॉलम जानकारी जिसे आप sys.columns के माध्यम से क्वेरी कर सकते हैं, और अधिक जानकारी अन्य ऑब्जेक्ट्स के माध्यम से उपलब्ध है। हमारी चर्चा के लिए जो प्रासंगिक है वह यह है कि SQL सर्वर आपको दृश्यों के विरुद्ध एक्सेस अनुमतियों को नियंत्रित करने देता है। दृश्य की आंतरिक तालिका अभिव्यक्ति में SELECT * का उपयोग करते समय मैं आपको चेतावनी देना चाहता हूं, जब अंतर्निहित निर्भर वस्तुओं पर डीडीएल परिवर्तन लागू होते हैं तो क्या हो सकता है।

उपयोगकर्ता 1 नामक उपयोगकर्ता बनाने के लिए निम्न कोड का उपयोग करें और उपयोगकर्ता को दृश्य से कॉलम कीकोल और इंटकॉल का चयन करने की अनुमति दें, लेकिन चारकोल नहीं:

यदि उपयोगकर्ता मौजूद है तो उपयोगकर्ता को छोड़ दें1; लॉगिन के बिना उपयोगकर्ता उपयोगकर्ता1 बनाएं; उपयोगकर्ता1 को dbo.V1(keycol, intcol) पर चयन दें;

इस बिंदु पर, आइए हमारे विचार से संबंधित कुछ रिकॉर्ड किए गए मेटाडेटा का निरीक्षण करें। sys.views से दृश्य का प्रतिनिधित्व करने वाली प्रविष्टि को वापस करने के लिए निम्न कोड का उपयोग करें:

चुनें SCHEMA_NAME(schema_id) AS स्कीमानाम, नाम, object_id, type_descFROM sys.viewsWHERE object_id =OBJECT_ID(N'dbo.V1');

यह कोड निम्न आउटपुट उत्पन्न करता है:

स्कीमानाम नाम object_id type_desc----------- -------------------------dbo V1 130099504 देखें

sys.modules से दृश्य परिभाषा प्राप्त करने के लिए निम्न कोड का उपयोग करें:

sys.sql_modules से परिभाषा चुनें, जहां object_id =OBJECT_ID(N'dbo.V1');

एक अन्य विकल्प OBJECT_DEFINITION फ़ंक्शन का उपयोग इस प्रकार करना है:

 OBJECT_DEFINITION चुनें (OBJECT_ID(N'dbo.V1'));

आपको निम्न आउटपुट मिलता है:

देखें dbo.V1AS चुनें * dbo.T1 से;

sys.columns से व्यू की कॉलम परिभाषाओं को क्वेरी करने के लिए निम्न कोड का उपयोग करें:

का चयन नाम AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');

जैसा कि अपेक्षित था, आपको व्यू के तीन कॉलम कीकॉल, इंटकोल और चारकोल के बारे में जानकारी मिलती है:

column_name column_id data_type-------------------------------कीकॉल 1 intintcol 2 intcharcol 3 varchar

कॉलम से जुड़े कॉलम आईडी (क्रमिक स्थिति) का निरीक्षण करें।

आप मानक सूचना स्कीमा दृश्य INFORMATION_SCHEMA.COLUMNS को क्वेरी करके समान जानकारी प्राप्त कर सकते हैं, जैसे:

COLUMN_NAME, ORDINAL_POSITION, DATA_TYPEFROM INFORMATION_SCHEMA.COLUMNSWHERE TABLE_SCHEMA =N'dbo' और TABLE_NAME =N'V1' चुनें;

दृश्य की निर्भरता जानकारी प्राप्त करने के लिए (वस्तुओं को यह संदर्भित करता है), आप sys.dm_sql_referenced_entities को क्वेरी कर सकते हैं, जैसे:

चयन OBJECT_NAME(referenced_id) AS संदर्भित_वस्तु, संदर्भित_माइनर_आईडी, COL_NAME(referenced_id, Referenced_minor_id) AS column_nameFROM sys.dm_sql_referenced_entities(N'dbo.V1', N'OBJECT');

आप तालिका T1 और उसके तीन स्तंभों पर निर्भरता पाएंगे:

संदर्भित_ऑब्जेक्ट संदर्भित_माइनर_आईडी कॉलम_नाम-------------------------------------- ---- T1 0 NULLT1 1 keycolT1 2 intcolT1 3 चारकोल

जैसा कि आप शायद अनुमान लगा सकते हैं, कॉलम के लिए Reference_minor_id मान वह कॉलम आईडी है जिसे आपने पहले देखा था।

यदि आप V1 के विरुद्ध user1 की अनुमति प्राप्त करना चाहते हैं, तो आप sys.database_permissions को क्वेरी कर सकते हैं, जैसे:

चयन OBJECT_NAME(major_id) AS संदर्भित_ऑब्जेक्ट, माइनर_आईडी, COL_NAME(major_id, नाबालिग_आईडी) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') AND Grantee_principal_id(N'user1'); पूर्व> 

यह कोड निम्नलिखित आउटपुट उत्पन्न करता है, यह पुष्टि करते हुए कि वास्तव में उपयोगकर्ता 1 के पास केवल कीकोल और इंटकॉल के खिलाफ चुनिंदा अनुमतियां हैं, लेकिन चारकोल के खिलाफ नहीं:

संदर्भित_ऑब्जेक्ट माइनर_आईडी कॉलम_नाम अनुमति_नाम------------------------------------- --------------V1 1 कीकॉल SELECTV1 2 intcol SELECT

फिर से, नाबालिग_आईडी मान वह कॉलम आईडी है जिसे आपने पहले देखा था। हमारे उपयोगकर्ता, उपयोगकर्ता 1, के पास उन स्तंभों की अनुमति है जिनकी आईडी 1 और 2 हैं।

इसके बाद, उपयोगकर्ता 1 का प्रतिरूपण करने के लिए और V1 के सभी स्तंभों को आज़माने और क्वेरी करने के लिए निम्न कोड चलाएँ:

EXECUTE AS USER =N'user1'; चुनें * dbo.V1 से;

जैसा कि आप उम्मीद करेंगे, चारकोल को क्वेरी करने की अनुमति की कमी के कारण आपको अनुमति त्रुटि मिलती है:

Msg 230, Level 14, State 1, Line 141
ऑब्जेक्ट 'V1', डेटाबेस 'TSQLV5', स्कीमा 'dbo' के कॉलम 'charcol' पर SELECT अनुमति को अस्वीकार कर दिया गया था।

केवल keycol और intcol क्वेरी करने का प्रयास करें:

कीकोल चुनें, dbo.V1 से intcol;

इस बार क्वेरी सफलतापूर्वक चलती है, जिससे निम्न आउटपुट उत्पन्न होता है:

कीकॉल intcol--------------------------1 102 20

अब तक कोई आश्चर्य नहीं हुआ।

अपने मूल उपयोगकर्ता पर वापस जाने के लिए निम्न कोड चलाएँ:

रिवर्ट;

आइए अब अंतर्निहित तालिका dbo.T1 में कुछ संरचनात्मक परिवर्तन लागू करें। पहले डेटकॉल और बाइनरीकोल नामक दो कॉलम जोड़ने के लिए निम्न कोड चलाएँ, और फिर कॉलम इंटेक को छोड़ने के लिए:

ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), Binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233); ALTER TABLE dbo.T1 DROP COLUMN intcol;

SQL सर्वर ने दृश्य द्वारा संदर्भित स्तंभों में संरचनात्मक परिवर्तनों को अस्वीकार नहीं किया क्योंकि दृश्य SCHEMABINDING विशेषता के साथ नहीं बनाया गया था। अब, पकड़ने के लिए। इस बिंदु पर, SQL सर्वर ने अभी तक विभिन्न कैटलॉग ऑब्जेक्ट्स में दृश्य की मेटाडेटा जानकारी को ताज़ा नहीं किया है।

अपने मूल उपयोगकर्ता (अभी तक उपयोगकर्ता1 नहीं) के साथ दृश्य को क्वेरी करने के लिए निम्न कोड का उपयोग करें:

dbo.V1 से * चुनें;

आपको निम्न आउटपुट मिलता है:

कीकोल intcol चारकोल-----------------------------------1 ए 9999-12-312 बी 9999-12-31 

ध्यान दें कि इंटकॉल वास्तव में चारकोल की सामग्री लौटाता है और चारकोल डेटकॉल की सामग्री लौटाता है। याद रखें, अब तालिका में कोई इंटकॉल नहीं है, लेकिन डेटकॉल है। साथ ही, आपको नया कॉलम बाइनरीकोल वापस नहीं मिलता है।

क्या हो रहा है, यह जानने के लिए, व्यू के कॉलम मेटाडेटा को क्वेरी करने के लिए निम्न कोड का उपयोग करें:

का चयन नाम AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');

यह कोड निम्न आउटपुट उत्पन्न करता है:

column_name column_id data_type-------------------------------कीकॉल 1 intintcol 2 intcharcol 3 varchar

जैसा कि आप देख सकते हैं, दृश्य का मेटाडेटा अभी भी ताज़ा नहीं है। आप इंटकॉल को कॉलम आईडी 2 के रूप में और चारकोल को कॉलम आईडी 3 के रूप में देख सकते हैं। व्यवहार में, इंटकॉल अब मौजूद नहीं है, चारकोल को कॉलम 2 माना जाता है, और डेटकॉल को कॉलम 3 माना जाता है।

आइए देखें कि अनुमति जानकारी के साथ कोई परिवर्तन हुआ है या नहीं:

चयन OBJECT_NAME(major_id) AS संदर्भित_ऑब्जेक्ट, माइनर_आईडी, COL_NAME(major_id, नाबालिग_आईडी) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') AND Grantee_principal_id(N'user1'); पूर्व> 

आपको निम्न आउटपुट मिलता है:

संदर्भित_ऑब्जेक्ट माइनर_आईडी कॉलम_नाम अनुमति_नाम------------------------------------- --------------V1 1 कीकॉल SELECTV1 2 intcol SELECT

अनुमति जानकारी से पता चलता है कि उपयोगकर्ता 1 को दृश्य में कॉलम 1 और 2 की अनुमति है। हालांकि, भले ही मेटाडेटा सोचता है कि कॉलम 2 को इंटकॉल कहा जाता है, यह वास्तव में व्यवहार में टी 1 में चारकोल के लिए मैप किया गया है। यह खतरनाक है क्योंकि उपयोगकर्ता 1 को चारकोल तक पहुंच नहीं होनी चाहिए। क्या होगा यदि वास्तविक जीवन में यह कॉलम पासवर्ड जैसी संवेदनशील जानकारी रखता है।

आइए उपयोगकर्ता 1 को फिर से प्रतिरूपित करें, और सभी दृश्य स्तंभों को क्वेरी करें:

EXECUTE AS USER ='user1'; चुनें * dbo.V1 से;

आपको यह कहते हुए अनुमति त्रुटि मिलती है कि आपके पास चारकोल तक पहुंच नहीं है:

Msg 230, Level 14, State 1, Line 211
ऑब्जेक्ट 'V1', डेटाबेस 'TSQLV5', स्कीमा 'dbo' के कॉलम 'charcol' पर SELECT अनुमति को अस्वीकार कर दिया गया था।

हालांकि, देखें कि क्या होता है जब आप स्पष्ट रूप से keycol और intcol मांगते हैं:

कीकोल चुनें, dbo.V1 से intcol;

आपको निम्न आउटपुट मिलता है:

कीकॉल intcol---------------------1 A2 B

यह क्वेरी सफल होती है, केवल यह intcol के तहत चारकोल की सामग्री लौटाती है। हमारे उपयोगकर्ता, उपयोगकर्ता 1, के पास इस जानकारी तक पहुंच नहीं होनी चाहिए। ओह!

इस बिंदु पर, निम्न कोड चलाकर मूल उपयोगकर्ता पर वापस लौटें:

रिवर्ट;

SQL मॉड्यूल रीफ़्रेश करें

आप स्पष्ट रूप से देख सकते हैं कि दृश्य की आंतरिक तालिका अभिव्यक्ति में SELECT * का उपयोग करना एक बुरा विचार है। लेकिन यह केवल इतना ही नहीं है। आम तौर पर, प्रत्येक डीडीएल को संदर्भित वस्तुओं और स्तंभों में बदलने के बाद दृश्य के मेटाडेटा को ताज़ा करना एक अच्छा विचार है। आप ऐसा sp_refreshview या अधिक सामान्य sp_refreshmodule का उपयोग करके कर सकते हैं, जैसे:

EXEC sys.sp_refreshsqlmodule N'dbo.V1';

दृश्य को फिर से क्वेरी करें, अब जबकि इसका मेटाडेटा रीफ़्रेश कर दिया गया है:

dbo.V1 से * चुनें;

इस बार आपको अपेक्षित आउटपुट मिलता है:

कीकोल चारकोल डेटकोल बाइनरीकोल----------------------------------------------ए 9999 -12-31 0x1122332 बी 9999-12-31 0x112233

कॉलम चारकोल को सही नाम दिया गया है और सही डेटा दिखाता है; आप इंटकॉल नहीं देखते हैं, और आप नए कॉलम डेटकॉल और बाइनरीकोल देखते हैं।

व्यू के कॉलम मेटाडेटा को क्वेरी करें:

का चयन नाम AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');

आउटपुट अब सही कॉलम मेटाडेटा जानकारी दिखाता है:

column_name column_id data_type ------------ ---------------------कीकॉल 1 intcharcol 2 varchardatecol 3 datebinarycol 4 varbinary

दृश्य के विरुद्ध उपयोगकर्ता1 की अनुमतियां पूछें:

चयन OBJECT_NAME(major_id) AS संदर्भित_ऑब्जेक्ट, माइनर_आईडी, COL_NAME(major_id, नाबालिग_आईडी) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') AND Grantee_principal_id(N'user1'); पूर्व> 

आपको निम्न आउटपुट मिलता है:

संदर्भित_ऑब्जेक्ट माइनर_आईडी कॉलम_नाम अनुमति_नाम------------------------------------- --------------V1 1 कीकोल चुनें

अनुमति जानकारी अब सही है। हमारे उपयोगकर्ता, उपयोगकर्ता 1, के पास केवल कीकॉल चुनने की अनुमति है, और इंटकॉल के लिए अनुमति जानकारी हटा दी गई है।

यह सुनिश्चित करने के लिए कि सब कुछ अच्छा है, आइए उपयोगकर्ता 1 का रूप धारण करके और दृश्य को क्वेरी करके इसका परीक्षण करें:

EXECUTE AS USER ='user1'; चुनें * dbo.V1 से;

डेटकॉल और बाइनरीकोल के लिए अनुमतियों की कमी के कारण आपको दो अनुमति त्रुटियां मिलती हैं:

Msg 230, Level 14, State 1, Line 281
ऑब्जेक्ट 'V1', डेटाबेस 'TSQLV5', स्कीमा 'dbo' के कॉलम 'datecol' पर SELECT अनुमति को अस्वीकार कर दिया गया था।

Msg 230, Level 14, State 1, Line 281
ऑब्जेक्ट 'V1', डेटाबेस 'TSQLV5', स्कीमा 'dbo' के 'बाइनरीकॉल' कॉलम पर SELECT अनुमति को अस्वीकार कर दिया गया था।

keycol और intcol को क्वेरी करने का प्रयास करें:

कीकोल चुनें, dbo.V1 से intcol;

इस बार त्रुटि सही ढंग से कहती है कि intcol नाम का कोई कॉलम नहीं है:

संदेश 207, स्तर 16, राज्य 1, रेखा 279

अमान्य कॉलम नाम 'intcol'।

क्वेरी केवल intcol:

dbo.V1 से कीकॉल चुनें;

निम्नलिखित आउटपुट उत्पन्न करते हुए यह क्वेरी सफलतापूर्वक चलती है:

कीकॉल-----------12

इस बिंदु पर निम्नलिखित कोड चलाकर अपने मूल उपयोगकर्ता पर वापस लौटें:

रिवर्ट;

क्या यह SELECT * से बचने और स्पष्ट कॉलम नामों का उपयोग करने के लिए पर्याप्त है?

यदि आप एक अभ्यास का पालन करते हैं जो दृश्य की आंतरिक तालिका अभिव्यक्ति में कोई चयन * नहीं कहता है, तो क्या यह आपको परेशानी से दूर रखने के लिए पर्याप्त होगा? खैर, देखते हैं…

तालिका को फिर से बनाने और देखने के लिए निम्न कोड का उपयोग करें, केवल इस बार दृश्य की आंतरिक क्वेरी में कॉलम को स्पष्ट रूप से सूचीबद्ध करें:

ड्रॉप व्यू अगर मौजूद है dbo.V1;ड्रॉप टेबल अगर मौजूद है तो dbo.T1;GO क्रिएट टेबल dbo.T1 (कीकॉल इंट नॉट न्यूल आइडेंटिटी कॉन्सट्रेंट PK_T1 प्राइमरी की, इंट नॉट न्यूल, चारकोल वर्चर (10) नॉट न्यूल); dbo.T1(intcol, charcol) VALUES (10, 'A'), (20, 'B') में INSERT करें; dbo.V1AS बनाएं या बदलें देखें dbo.T1;GO

दृश्य को क्वेरी करें:

dbo.V1 से * चुनें;

आपको निम्न आउटपुट मिलता है:

कीकोल intcol charcol-----------------------------------1 10 A2 20B

फिर से, keycol और intcol चुनने के लिए user1 को अनुमति दें:

उपयोगकर्ता1 को dbo.V1(keycol, intcol) पर चयन प्रदान करें;

इसके बाद, वही संरचनात्मक परिवर्तन लागू करें जैसे आपने पहले किया था:

ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), Binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233); ALTER TABLE dbo.T1 DROP COLUMN intcol;

ध्यान दें कि SQL सर्वर ने इन परिवर्तनों को स्वीकार कर लिया है, भले ही दृश्य में intcol का स्पष्ट संदर्भ हो। फिर से, ऐसा इसलिए है क्योंकि दृश्य SCHEMABINDING विकल्प के बिना बनाया गया था।

दृश्य को क्वेरी करें:

dbo.V1 से * चुनें;

इस बिंदु पर SQL सर्वर निम्न त्रुटि उत्पन्न करता है:

संदेश 207, स्तर 16, राज्य 1, प्रक्रिया V1, पंक्ति 5 [बैच प्रारंभ पंक्ति 344]
अमान्य स्तंभ नाम 'intcol'।

संदेश 4413, स्तर 16, राज्य 1, पंक्ति 345
बाध्यकारी त्रुटियों के कारण दृश्य या कार्य 'dbo.V1' का उपयोग नहीं कर सका।

SQL सर्वर ने दृश्य में intcol संदर्भ को हल करने का प्रयास किया, और निश्चित रूप से असफल रहा।

लेकिन क्या होगा अगर आपकी मूल योजना इंटकॉल छोड़ने और बाद में इसे वापस जोड़ने की थी? इसे वापस जोड़ने के लिए निम्न कोड का उपयोग करें, और फिर दृश्य को क्वेरी करें:

ALTER TABLE dbo.T1 ADD intcol INT NOT NULL DEFAULT(0); चुनें * dbo.V1 से;

यह कोड निम्न आउटपुट उत्पन्न करता है:

कीकोल intcol charcol----------------------------------------1 0 A2 0B

परिणाम सही लगता है।

उपयोगकर्ता 1 के रूप में दृश्य को क्वेरी करने के बारे में कैसे? आइए इसे आजमाएं:

EXECUTE AS USER ='user1';चुनें * dbo.V1 से;

सभी स्तंभों को क्वेरी करते समय, आपको चारकोल के विरुद्ध अनुमतियों की कमी के कारण अपेक्षित त्रुटि मिलती है:

Msg 230, Level 14, State 1, Line 367
ऑब्जेक्ट 'V1', डेटाबेस 'TSQLV5', स्कीमा 'dbo' के कॉलम 'चारकोल' पर सेलेक्ट अनुमति को अस्वीकार कर दिया गया था।

स्पष्ट रूप से कीकॉल और इंटकॉल क्वेरी करें:

कीकोल चुनें, dbo.V1 से intcol;

आपको निम्न आउटपुट मिलता है:

कीकॉल intcol--------------------------1 02 0

ऐसा लगता है कि सब कुछ क्रम में है, इस तथ्य के लिए धन्यवाद कि आपने दृश्य की आंतरिक क्वेरी में SELECT * का उपयोग नहीं किया, भले ही आपने दृश्य के मेटाडेटा को ताज़ा नहीं किया। फिर भी, डीडीएल द्वारा संदर्भित वस्तुओं और स्तंभों को सुरक्षित पक्ष में बदलने के बाद दृश्य के मेटाडेटा को ताज़ा करना एक अच्छा अभ्यास हो सकता है।

इस बिंदु पर, निम्न कोड चलाकर अपने मूल उपयोगकर्ता पर वापस लौटें:

रिवर्ट;

योजनाबद्ध करना

SCHEMABINDING व्यू एट्रिब्यूट का उपयोग करके आप अपने आप को उपरोक्त कई परेशानियों से बचा सकते हैं। आपके द्वारा पहले देखी गई परेशानी से बचने के लिए चाबियों में से एक है कि दृश्य की आंतरिक क्वेरी में SELECT * का उपयोग न करें। लेकिन निर्भर वस्तुओं के खिलाफ संरचनात्मक परिवर्तन का मुद्दा भी है, जैसे संदर्भित कॉलम छोड़ना, जिसके परिणामस्वरूप दृश्य को क्वेरी करते समय त्रुटियां हो सकती हैं। SCHEMABINDING दृश्य विशेषता का उपयोग करके, आपको आंतरिक क्वेरी में SELECT * का उपयोग करने की अनुमति नहीं होगी। इसके अलावा, SQL सर्वर निर्भर वस्तुओं और स्तंभों पर प्रासंगिक DDL परिवर्तनों को लागू करने के प्रयासों को अस्वीकार कर देगा। प्रासंगिक रूप से, मेरा मतलब किसी संदर्भित तालिका या कॉलम को छोड़ना जैसे परिवर्तन हैं। किसी संदर्भित तालिका में कॉलम जोड़ना स्पष्ट रूप से कोई समस्या नहीं है, इसलिए SCHEMABINDING ऐसे परिवर्तन को नहीं रोकता है।

इसे प्रदर्शित करने के लिए, दृश्य परिभाषा में SCHEMABINDING के साथ तालिका और दृश्य को फिर से बनाने के लिए निम्न कोड का उपयोग करें:

ड्रॉप व्यू अगर मौजूद है dbo.V1;ड्रॉप टेबल अगर मौजूद है तो dbo.T1;GO क्रिएट टेबल dbo.T1 (कीकॉल इंट नॉट न्यूल आइडेंटिटी कॉन्सट्रेंट PK_T1 प्राइमरी की, इंट नॉट न्यूल, चारकोल वर्चर (10) नॉट न्यूल); dbo.T1(intcol, charcol) Values ​​(10, 'A'), (20, 'B') में INSERT करें 

आपको एक त्रुटि मिलती है:

Msg 1054, स्तर 15, राज्य 6, प्रक्रिया V1, पंक्ति 5 [बैच स्टार्ट लाइन 387]
Syntax '*' स्कीमा-बाउंड ऑब्जेक्ट में अनुमति नहीं है।

SCHEMABINDING का उपयोग करते समय, आपको दृश्य की आंतरिक तालिका अभिव्यक्ति में SELECT * का उपयोग करने की अनुमति नहीं है।

एक स्पष्ट कॉलम सूची के साथ केवल इस बार फिर से दृश्य बनाने का प्रयास करें:

SCHEMABINDINGAS के साथ dbo.V1 बनाएं या बदलें

इस बार दृश्य सफलतापूर्वक बनाया गया है।

keycol और intcol पर user1 अनुमतियां प्रदान करें:

उपयोगकर्ता1 को dbo.V1(keycol, intcol) पर चयन प्रदान करें;

इसके बाद, तालिका में संरचनात्मक परिवर्तनों को लागू करने का प्रयास करें। सबसे पहले, कुछ कॉलम जोड़ें:

ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), Binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233);

कॉलम जोड़ना कोई समस्या नहीं है क्योंकि वे मौजूदा स्कीमा-बाउंड व्यू का हिस्सा नहीं हो सकते हैं, इसलिए यह कोड सफलतापूर्वक पूरा होता है।

कॉलम को इंटकॉल छोड़ने का प्रयास करें:

ALTER TABLE dbo.T1 DROP COLUMN intcol;

आपको निम्न त्रुटि मिलती है:

Msg 5074, लेवल 16, स्टेट 1, लाइन 418
ऑब्जेक्ट 'V1' कॉलम 'intcol' पर निर्भर है।

Msg 4922, Level 16, State 9, Line 418
ALTER TABLE DROP COLUMN intcol विफल हुआ क्योंकि एक या अधिक ऑब्जेक्ट इस कॉलम तक पहुँचते हैं।

स्कीमा-बाउंड ऑब्जेक्ट मौजूद होने पर संदर्भित कॉलम को छोड़ना या बदलना अस्वीकृत है।

यदि आपको अभी भी इंटकॉल छोड़ने की आवश्यकता है, तो आपको पहले स्कीमा-बाउंड रेफरेंसिंग व्यू को छोड़ना होगा, परिवर्तन लागू करना होगा, और फिर दृश्य को फिर से बनाना होगा और अनुमतियों को पुन:असाइन करना होगा, जैसे:

ड्रॉप व्यू अगर मौजूद है dbo.V1;GO ALTER TABLE dbo.T1 DROP COLUMN intcol;GO Create या ALTER VIEW dbo.V1 SCHEMABINDINGAS के साथ dbo. सेलेक्ट कीकोल, dbo.t1; GO GRAND से कीकोल, डेटकोल, बाइनरीकोल चुनें। V1 (कीकॉल, डेटकॉल, बाइनरीकोल) टू यूजर1;जाओ

बेशक इस समय दृश्य परिभाषा को ताज़ा करने की कोई आवश्यकता नहीं है, क्योंकि आपने इसे नए सिरे से बनाया है।

अब जब आप परीक्षण कर चुके हैं, तो सफाई के लिए निम्न कोड चलाएँ:

ड्रॉप व्यू अगर मौजूद है dbo.V1;ड्रॉप टेबल अगर मौजूद है तो dbo.T1;ड्रॉप यूजर अगर मौजूद है तो यूजर1;

सारांश

दृश्य की आंतरिक तालिका अभिव्यक्ति में SELECT * का उपयोग करना एक बहुत बुरा विचार है। संदर्भित वस्तुओं पर संरचनात्मक परिवर्तन लागू होने के बाद, आप गलत कॉलम नाम प्राप्त कर सकते हैं, और यहां तक ​​कि उपयोगकर्ताओं को उस डेटा तक पहुंचने की अनुमति भी दे सकते हैं, जिस तक उनकी पहुंच नहीं है। संदर्भित कॉलम नामों को स्पष्ट रूप से सूचीबद्ध करना एक महत्वपूर्ण अभ्यास है।

दृश्य परिभाषा में SCHEMABINDING का उपयोग करके आपको स्तंभ नामों को स्पष्ट रूप से सूचीबद्ध करने के लिए मजबूर किया जाता है, और आश्रित वस्तुओं के लिए प्रासंगिक संरचनात्मक परिवर्तन SQL सर्वर द्वारा अस्वीकार कर दिए जाते हैं। इसलिए, ऐसा लग सकता है कि SCHEMBINDING के साथ विचार बनाना हमेशा एक अच्छा विचार है। हालाँकि, इस विकल्प के साथ एक चेतावनी है। जैसा कि आपने देखा, SCHEMBINDING का उपयोग करते समय संदर्भित वस्तुओं में संरचनात्मक परिवर्तन लागू करना एक लंबी, अधिक विस्तृत प्रक्रिया बन जाती है। यह विशेष रूप से उन प्रणालियों में एक मुद्दा हो सकता है जिनकी उपलब्धता बहुत अधिक होनी चाहिए। कल्पना कीजिए कि आपको VARCHAR(50) से VARCHAR(60) के रूप में परिभाषित कॉलम को बदलने की जरूरत है। यदि इस कॉलम को संदर्भित करने वाले SCHEMABINDING के साथ परिभाषित कोई दृश्य है, तो यह एक अनुमत परिवर्तन नहीं है। संदर्भित विचारों के एक समूह को छोड़ने के निहितार्थ, जिसे अन्य विचारों द्वारा संदर्भित किया जा सकता है, और इसी तरह, सिस्टम के लिए समस्याग्रस्त हो सकता है। संक्षेप में, कंपनियों के लिए केवल ऐसी नीति अपनाना इतना तुच्छ नहीं है जो कहती है कि SCHEMABINDING का उपयोग उन सभी वस्तुओं में किया जाना चाहिए जो इसका समर्थन करती हैं। हालाँकि, विचारों के आंतरिक प्रश्नों में SELECT * का उपयोग न करने की नीति अपनाना अधिक सीधा होना चाहिए।

विचारों के संबंध में तलाशने के लिए और भी बहुत कुछ है। अगले महीने जारी रहेगा...


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. डेटा माइनिंग का परिचय

  2. एजेंट-आधारित बनाम एजेंट रहित निगरानी के बीच निर्णय करें

  3. अपडेट किया गया Azure SQL डेटाबेस टियर विकल्प

  4. निष्पादन योजनाओं में पंक्ति लक्ष्य निर्धारित करना और उनकी पहचान करना

  5. पुरानी रिपोर्ट को ठीक करने के लिए AT TIME ZONE का उपयोग करना