क्या मैं SQL में पहले निष्पादित किए जा रहे कार्यों पर भरोसा कर सकता हूं


9

कृपया निम्नलिखित स्क्रिप्ट पर विचार करें:

create or replace function f(p_limit in integer) return integer as
begin
  set_global_context ('limit', p_limit);
  return p_limit;
end;
/

create view v as 
select level as val from dual connect by level<=sys_context('global_context','limit');

select f(2), v.* from v;

/*
F(2)                   VAL                    
---------------------- ---------------------- 
2                      1                      
2                      2                      
*/

select f(4), v.* from v;

/*
F(4)                   VAL                    
---------------------- ---------------------- 
4                      1                      
4                      2                      
4                      3                      
4                      4                      
*/

क्या मैं f(x)संदर्भ के अंदर दृश्य को पढ़ने से पहले निष्पादित होने पर भरोसा कर सकता हूं , जैसा कि 10.2 पर चलाए गए इस परीक्षण मामले में है?


मदद नहीं कर सकता लेकिन लगता है कि एक लॉगिन ट्रिगर अधिक उपयुक्त हो सकता है (यदि स्तर हमेशा समान रहेगा, वह है)
Philᵀᴹ

@ यह केवल एक उदाहरण है - मैं एक दृश्य के लिए sys_context का उपयोग कर रहा हूं और प्रत्येक बार परम अलग होगा। यदि आप एसक्यूएल से एक वैश्विक संदर्भ सेट करने के तरीके के बारे में इस तरह से खिलवाड़ के बिना जानते हैं, तो मुझे भी सुनने में दिलचस्पी होगी!
जैक का कहना है कि

1
@JackDouglas: एक दृश्य को परवरिश करना एक ऐसा विचार है जो मेरे लिए "सही" महसूस नहीं करता है। MSSQL के तहत आप जो करने की कोशिश कर रहे हैं वह एक उपयोगकर्ता परिभाषित फ़ंक्शन का उपयोग करके किया जा सकता है जो एक परिणाम (मान के बजाय) लौटाता है, - आप तब SELECT stuff FROM dbo.FuncReturningTable(param)या इसी तरह का हो सकता है। Oracle में संभवतः समान कार्यक्षमता है। हालांकि अगर बड़े डेटा सेट का उपयोग करने पर मुझे प्रदर्शन पर नज़र रखने में सावधानी होगी: मुझे यकीन नहीं है कि इस तरह के सिंटैक्स से एक कुशल योजना बनाने के लिए क्वेरी प्लानर को कितना उज्ज्वल होना होगा।
डेविड स्पिललेट

@ द्रविड़ पैराएमराइज़िंग एक दृश्य आमतौर पर sys_context के साथ किया जाता है - आमतौर पर आप क्वेरी को निष्पादित करने से पहले संदर्भ सेट करेंगे (जैसे पीएल / एसक्यूएल के एक बिट के साथ)। ओरेकल के पास सेट-रिटर्निंग और / या पाइपलाइन किए गए कार्य हैं लेकिन वे इसे प्राप्त करने का 'सामान्य' तरीका नहीं हैं। स्पष्ट होने के लिए, मुझे लगता है कि शीर्षक में प्रश्न का उत्तर "नहीं" है - मुझे आश्चर्य है कि अगर कोई बेहतर जानता था।
जैक कहते हैं कि

जवाबों:


8

नहीं।

यदि आप अपने विचार को संदर्भ के साथ फ़िल्टर कर रहे हैं जहाँ क्लॉज़ (कनेक्ट द्वारा) के बजाय, आपको संदर्भ के लिए पहले से निर्धारित मान मिलेगा:

create table t as 
 select rownum r from dual connect by level <= 10;

create or replace view v as 
  select r val from t where r <=sys_context('global_context','limit');

select f(2), v.* from v;

F(2) VAL
---- ---
   2   1 
   2   2 

select f(4), v.* from v;

F(4) VAL
---- ---
   4   1 
   4   2 

select f(4), v.* from v;

F(4) VAL
---- ---
   4   1 
   4   2 
   4   3 
   4   4 

चूंकि जहां कॉलम चयनित होने से पहले क्लॉज का मूल्यांकन किया जाता है, वहीं फ़ंक्शन को दिया गया मान तब तक सेट नहीं किया जाता है जब तक संदर्भ पढ़ा नहीं जाता है। आपकी क्वेरी में sys_context कॉल का स्थान (चयन करें, जहां, समूह द्वारा, आदि) इस मूल्य को सेट करने पर बिल्कुल प्रभावित करेगा।


+1 यह मेरी पुस्तक में बहुत "केस बंद" है, धन्यवाद।
जैक का कहना है कि topanswers.xyz की कोशिश करें

2

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

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

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


2
अच्छा जवाब है, लेकिन मुझे लगता है कि जैक एक निश्चित तकनीकी ओरेकल जवाब की तलाश में है।
फिलु

1

प्रलेखन केवल यह वादा करता है कि "आशावादी पहले अभिव्यक्तियों और शर्तों का मूल्यांकन करता है जिसमें स्थिरांक पूरी तरह से संभव है।" ( १०.२ , ११.२ )। आपको इस बात की गारंटी नहीं है कि यह किसी विशेष अभिव्यक्ति का पहले मूल्यांकन करेगा, या यह समय-समय पर उस आदेश को नहीं बदलेगा (एक ही रिलीज के भीतर एक नया पैचवेल?)।


+1 उत्कृष्ट, धन्यवाद (हालांकि मेरे उन डॉक्स को क्रिस के जवाब के साथ बहुत अधिक नहीं पढ़ा गया है )
जैक कहते हैं कि

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

@ क्रिस वह बोलने का अनुभव है या आपको डॉक्स से कहीं मिला है?
जैक कहते हैं कि topanswers.xyz की कोशिश करें

मुझे एक डॉक्टर संदर्भ नहीं मिल रहा है। मेरे अनुभव के आधार पर, यदि किसी एकल तालिका को फ़िल्टर करने के लिए जहां खंड में कहा जाता है, तो इसे हर पंक्ति (एफटीएस मानकर) तक पहुँचा जा सकेगा, लेकिन केवल चयनित सूची में होने पर पंक्तियों के लिए ही लौटा दिया जाएगा। चूंकि निष्पादन योजना को पार्सिंग के दौरान सेट किया गया है, इसका मतलब यह है कि चयन में कार्य इसे प्रभावित नहीं कर सकते हैं। यह जांचने के लिए एक परीक्षण मामला एक काउंटर (एक पैकेज या टेबल में) एक फ़ंक्शन सेटिंग बनाकर और आउटपुट के आधार पर तुलना करने के लिए किया जा सकता है जहां यह क्वेरी में रखा गया है।
क्रिस सैक्सन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.