2008-11-04 5 views
19

एक दृश्य खराब बनाने के लिए '*' का उपयोग क्यों कर रहा है?एक दृश्य खराब बनाने के लिए '*' का उपयोग क्यों कर रहा है?

मान लीजिए कि आपके पास जटिल जुड़ाव है और सभी फ़ील्ड कहीं भी उपयोग किए जा सकते हैं।

फिर आपको बस आवश्यक फ़ील्ड चुनना होगा।

SELECT field1, field2 FROM aview WHERE ... 

दृश्य "aview" हो सकता है SELECT table1.*, table2.* ... FROM table1 INNER JOIN table2 ...

हम एक समस्या है, तो 2 क्षेत्रों table1 और table2 में एक ही नाम है।

क्या यही कारण है कि '*' दृश्य में उपयोग करना बुरा है?

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

मुझे क्या याद आ रही है?

सादर

उत्तर

33

मैं वहाँ सॉफ्टवेयर में ज्यादा है कि "सिर्फ बुरा" है नहीं लगता है, लेकिन वहाँ सामान के बहुत सारे है कि :-)

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

दूसरी ओर, यदि आप वास्तव में आपके विचार चाहते सानंद अंतर्निहित टेबल, जो मामले में एक * सिर्फ तुम क्या चाहते हो जाएगा करने के लिए सभी परिवर्तनों को स्वीकार करने के लिए हो सकता है।

अद्यतन: मैं अगर ओपी दिमाग में कोई विशेष डाटाबेस विक्रेता था पता नहीं है, लेकिन यह अब स्पष्ट है कि मेरा आखिरी टिप्पणी सभी प्रकार के लिए सच नहीं होता है। मैं इसे इंगित करने के लिए उपयोगकर्ता 12861 और जॉनी लीड्स का ऋणी हूं, और खेद है कि मेरे जवाब को संपादित करने के लिए मुझे 6 साल से अधिक समय लगेगा।

+1

कृपया मेरी अन्य टिप्पणी देखें, SQL सर्वर पर सभी परिवर्तन जरूरी नहीं हैं। – user12861

+0

इसके अतिरिक्त, दृश्य का उपयोग करने वाले कोड का उपयोग नहीं करना चाहिए *, इसलिए दृश्य में * उपयोग करना काफी उचित हो सकता है, और यह सुनिश्चित करने के लिए कि यह * का उपयोग नहीं कर रहा है, यह सुनिश्चित करने के लिए कोड पर कोड होगा। –

+3

अंत में टिप्पणी पूरी तरह से गलत है (कम से कम SQL सर्वर में) - विपरीत होता है - अंतर्निहित तालिकाओं में परिवर्तन चुपचाप अनदेखा कर रहे हैं। यह @ user12861 उल्लेख है। एसक्यूएल सर्वर में चयन * का उपयोग करके किसी भी दृश्य को अंडरलिंग टेबल बदलते समय ड्रॉप और पुनर्निर्माण की आवश्यकता होगी अन्यथा यह चुपचाप सभी कॉलम नहीं दिखाएगा। यह विफलता का एक बहुत बुरा रूप है क्योंकि यह एक देव वातावरण में उठाए जाने की संभावना नहीं है जहां आप अपने डेटाबेस को नियमित आधार पर खरोंच से पुनर्निर्माण कर रहे हैं। जब आप कॉलम –

3

ऐसा इसलिए है क्योंकि यह सुनिश्चित करें कि आप क्या आप विशेष रूप से की जरूरत के बारे में सोच रहे हैं बनाने के लिए नहीं है कि हर चर की जरूरत है, और यह भी है।

उदाहरण के लिए आपकी साइट पर उपयोगकर्ताओं की एक सूची बनाते समय डेटाबेस से सभी हैश किए गए पासवर्ड प्राप्त करने का कोई मतलब नहीं है, इसलिए एक चयन * अनुत्पादक होगा।

3

एक समय की बात है, मैं एक और डेटाबेस (एक ही सर्वर पर) में एक टेबल के खिलाफ एक दृश्य

Select * From dbname..tablename 

साथ फिर एक दिन बनाया, किसी स्तंभ लक्षित तालिका में जोड़ा गया था। दृश्य को फिर से तैनात किए जाने तक पूरी तरह गलत परिणामों को वापस करना शुरू कर दिया।


पूरी तरह से गलत: कोई पंक्ति नहीं।

यह एसक्यूएल सर्वर 2000 पर था।

मुझे लगता है कि यह syscolumns मानों के कारण है कि दृश्य पर कब्जा कर लिया गया था, भले ही मैंने * का उपयोग किया था।

11

किसी भी उत्पादन के लिए '*' का उपयोग करना बुरा है। यह एक-एक प्रश्न के लिए बहुत अच्छा है, लेकिन उत्पादन कोड में आपको हमेशा यथासंभव स्पष्ट होना चाहिए।

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

15

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

मैं हर समय वाइल्डकार्ड का उपयोग करने से बचता हूं। इस तरह यदि कोई कॉलम नाम बदलता है, तो मुझे तुरंत दृश्य या क्वेरी में कोई त्रुटि मिलती है, और मुझे पता है कि इसे कहां ठीक करना है। यदि कॉलम अंतर्निहित तालिका में स्थिति बदलता है, तो दृश्य में कॉलम का क्रम निर्दिष्ट करना या क्वेरी इसके लिए क्षतिपूर्ति करता है।

+2

कृपया मेरा दूसरा उत्तर पढ़ें, कम से कम SQL सर्वर पर अंतर्निहित तालिकाओं में परिवर्तन हमेशा परिलक्षित नहीं होते हैं। – user12861

18

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

+0

उत्कृष्ट अंक! –

+0

यह चयन का उपयोग न करने का मेरा मुख्य कारण है *। अन्य कारण मुख्य रूप से प्रासंगिक हैं यदि आप अन्य चीजें जो खतरनाक हैं, जैसे कि चयन * नाम के बजाय इंडेक्स द्वारा कॉल या संदर्भ कॉलम के साथ चयन करें। दुह, कोर्स का वे खतरनाक संयोजन हैं। लेकिन स्वयं चुनकर * बुरा नहीं है। –

+0

मैं मानता हूं कि यह आमतौर पर खतरनाक नहीं है। डीबी पर डेटा जांच करते समय मैं अक्सर चयन * का उपयोग करता हूं। हालांकि, मैं उत्पादन कोड लिखते समय SELECT * का उपयोग करने से बचने के लिए प्रयास करता हूं ताकि उपरोक्त चित्रित समस्याओं का सामना करने के साथ-साथ अच्छी प्रोग्रामिंग आदतों को लागू करना जारी रखा जा सके। –

2

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

3

दृश्य के भीतर SELECT * का उपयोग करते हुए प्रदर्शन के बाहर कॉलम का उपयोग नहीं किए जाने पर प्रदर्शन प्रदर्शन ओवरहेड नहीं होता है - ऑप्टिमाइज़र उन्हें अनुकूलित करेगा; SELECT * FROM TheView शायद बैंडविड्थ को बर्बाद कर सकता है, जैसे किसी भी समय आप नेटवर्क कनेक्शन में अधिक कॉलम खींचते हैं।

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

हालांकि, ऊपर दिए गए सभी कारणों से, मैं शायद ही कभी SELECT * का उपयोग करता हूं।

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

2

मुझे लगता है कि यह आपके द्वारा उपयोग की जाने वाली भाषा पर निर्भर करता है। मैं चयन * का उपयोग करना पसंद करता हूं जब भाषा या डीबी चालक परिणाम के एक dict (पायथन, पर्ल, आदि) या सहयोगी सरणी (PHP) देता है। यह आपके कोड को समझने में आसान बनाता है अगर आप किसी सरणी में इंडेक्स के बजाय नाम से कॉलम का जिक्र कर रहे हैं।

+1

यदि फ़ील्ड का क्रम संशोधित किया गया है, तो सहयोगी सरणी काम जारी रखती है। –

13

इन अन्य उत्तरों में सभी अच्छे अंक हैं, लेकिन कम से कम SQL सर्वर पर उनके कुछ गलत बिंदु भी हैं। इसे आज़माएं:

create table temp (i int, j int) 
go 
create view vtemp as select * from temp 
go 
insert temp select 1, 1 
go 
alter table temp add k int 
go 
insert temp select 1, 1, 1 
go 
select * from vtemp 

एसक्यूएल सर्वर जोड़े जाने पर "नया" कॉलम के बारे में नहीं सीखता है। आप जो चाहते हैं उसके आधार पर यह एक अच्छी बात या बुरी चीज हो सकती है, लेकिन किसी भी तरह से यह संभवतः उस पर निर्भर नहीं है। तो इसे टालना सिर्फ एक अच्छा विचार की तरह लगता है।

मेरे लिए यह अजीब व्यवहार चुनिंदा * विचारों से बचने के लिए सबसे अधिक आकर्षक कारण है।

टिप्पणियों ने मुझे सिखाया है कि MySQL के समान व्यवहार है और ओरेकल नहीं है (यह तालिका में परिवर्तनों के बारे में जानेंगे)। विचारों में चयन * का उपयोग न करने के लिए मेरे लिए यह असंगतता अधिक कारण है।

+1

MySQL में वही व्यवहार - नया कॉलम दृश्य का हिस्सा नहीं बनता है। स्पष्ट रूप से वाइल्डकार्ड दृश्य के समय कॉलम की सूची में परिवर्तित हो जाता है। आधार तालिका में एक कॉलम का नाम बदलने से दृश्य अनुपयोगी हो जाता है। –

+3

ओरेकल इस तरह काम नहीं करता है। दृश्य तालिका परिवर्तन द्वारा अमान्य किया जाएगा और नए कॉलम के साथ अगली पहुंच पर पुन: संकलित किया जाएगा। –

2

किसी और ने इसका उल्लेख नहीं किया है, लेकिन SQL सर्वर के भीतर आप schemabinding विशेषता के साथ अपना दृश्य भी सेट कर सकते हैं।

यह किसी भी बेस टेबल (उन्हें छोड़कर) में संशोधन को रोकता है जो दृश्य परिभाषा को प्रभावित करेगा।

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

3

एक एसक्यूएल क्वेरी मूल रूप से एक कार्यात्मक इकाई है जिसे किसी प्रोग्रामर द्वारा कुछ संदर्भ में उपयोग के लिए डिज़ाइन किया गया है। लंबी अवधि की स्थिरता और समर्थनशीलता (संभवतः आपके अलावा किसी अन्य व्यक्ति द्वारा) एक कार्यात्मक इकाई में सबकुछ एक उद्देश्य के लिए होना चाहिए, और यह उचित रूप से स्पष्ट होना चाहिए (या दस्तावेज) यह क्यों है - विशेष रूप से डेटा के हर तत्व।

यदि मैं आपकी क्वेरी को बदलने की आवश्यकता या इच्छा के साथ अब से दो साल के साथ आना चाहता हूं, तो मुझे विश्वास होगा कि इससे पहले कि मैं इससे गड़बड़ कर सकूं, मैं इसे पूरी तरह से ग्रोक करने की उम्मीद करूंगा। जिसका अर्थ है कि मुझे समझने की आवश्यकता होगी कि सभी कॉलम क्यों बुलाए जाते हैं। (यदि आप एक से अधिक संदर्भों में क्वेरी का पुन: उपयोग करने का प्रयास कर रहे हैं, तो यह और भी स्पष्ट रूप से सच है। सामान्य कारणों में, सामान्य कारणों में समस्याग्रस्त है।) यदि मुझे आउटपुट में कॉलम देखना था कि मैं कुछ उद्देश्य से संबंधित नहीं हो सकता , मुझे पूरा यकीन होगा कि मुझे समझ में नहीं आया कि उसने क्या किया, और क्यों, और इसके परिणाम क्या बदलेंगे।

+0

उत्कृष्ट बिंदु और एक मैंने पहले उन शर्तों में नहीं सोचा था। – HLGEM

+0

यह केवल दिखाता है कि '*' -ed क्वेरी को स्पष्ट रूप से नामित क्वेरी में बदलना मुश्किल है; यह कुछ भी नहीं कहता है क्यों '*' -ed क्वेरी खराब है। आईएमओ, '*' -ed क्वेरी के बारे में स्वाभाविक रूप से बुरा नहीं है; इसका मतलब है कि आपको बहुत बढ़िया होने की आवश्यकता नहीं है। –

+0

मुझे यकीन नहीं है कि निर्भरता निर्धारण के संदर्भ में "बहुत बढ़िया" का अर्थ क्या है। जब तक आप तय नहीं करते हैं निर्भरता महत्वहीन हैं। – dkretz

1

और यदि आप चुनिंदा * स्वचालित रूप से उपयोग करने में शामिल हो गए हैं तो इसका मतलब है कि आप जितना आवश्यक हो उतना डेटा वापस कर रहे हैं क्योंकि जुड़ने वाले फ़ील्ड में डेटा दोहराया जाता है। यह डेटाबेस और नेटवर्क संसाधनों का अपमानजनक है।

यदि आप अन्य विचारों को कॉल करने वाले विचारों का उपयोग करने के लिए पर्याप्त मूर्ख हैं, तो चयन * का उपयोग करके उन्हें और भी खराब कलाकार बना सकते हैं (यह तकनीक है जो अपने प्रदर्शन के लिए खराब है, कॉल करने वाले मल्टीप्ल कॉलम जिन्हें आपको आवश्यकता नहीं है और भी बुरा)।

2

SQL सर्वर की स्थिति वास्तव में @ user12861 के उत्तर से भी बदतर है: यदि आप एकाधिक तालिकाओं के विरुद्ध SELECT * का उपयोग करते हैं, तो प्रश्न में जल्दी संदर्भित तालिका में कॉलम जोड़ना वास्तव में आपके विचार को मानों को वापस करने का कारण बन जाएगा पुराने कॉलम की नींव के तहत नए कॉलम।नीचे दिए गए उदाहरण को देखें:

-- create two tables 
CREATE TABLE temp1 (ColumnA INT, ColumnB DATE, ColumnC DECIMAL(2,1)) 
CREATE TABLE temp2 (ColumnX INT, ColumnY DATE, ColumnZ DECIMAL(2,1)) 
GO 


-- populate with dummy data 
INSERT INTO temp1 (ColumnA, ColumnB, ColumnC) VALUES (1, '1/1/1900', 0.5) 
INSERT INTO temp2 (ColumnX, ColumnY, ColumnZ) VALUES (1, '1/1/1900', 0.5) 
GO 


-- create a view with a pair of SELECT * statements 
CREATE VIEW vwtemp AS 
SELECT * 
FROM temp1 INNER JOIN temp2 ON 1=1 
GO 


-- SELECT showing the columns properly assigned 
SELECT * FROM vwTemp 
GO 


-- add a few columns to the first table referenced in the SELECT 
ALTER TABLE temp1 ADD ColumnD varchar(1) 
ALTER TABLE temp1 ADD ColumnE varchar(1) 
ALTER TABLE temp1 ADD ColumnF varchar(1) 
GO 


-- populate those columns with dummy data 
UPDATE temp1 SET ColumnD = 'D', ColumnE = 'E', ColumnF = 'F' 
GO 


-- notice that the original columns have the wrong data in them now, causing any datatype-specific queries (e.g., arithmetic, dateadd, etc.) to fail 
SELECT * 
FROM vwtemp 
GO 

-- clean up 
DROP VIEW vwTemp 
DROP TABLE temp2 
DROP TABLE temp1 
संबंधित मुद्दे

 संबंधित मुद्दे