2008-09-26 18 views
16

मैं पिछले सप्ताह कुछ यूनिट परीक्षणों को कोड के एक टुकड़े के लिए लिख रहा था जो कुछ एसक्यूएल स्टेटमेंट उत्पन्न करता था।सामान्य एसक्यूएल वाक्यविन्यास से मेल खाने के लिए नियमित अभिव्यक्ति?

मैं SELECT, INSERT और अद्यतन वाक्यविन्यास से मेल खाने के लिए एक रेगेक्स को समझने की कोशिश कर रहा था, इसलिए मैं सत्यापित कर सकता था कि मेरी विधियां वैध एसक्यूएल उत्पन्न कर रही थीं, और विभिन्न रेगेक्स संपादकों के साथ खोज और गड़बड़ी के 3-4 घंटे बाद मैंने छोड़ दिया ।

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

किसी भी मदद की सराहना की जाएगी किया, मैं नियमित अभिव्यक्ति के साथ बहुत अच्छा नहीं कर रहा हूँ, लेकिन मैं उनके बारे में अधिक जानकारी चाहते हैं।

वैसे यह सी # regex है कि मैं के बाद हूँ।

स्पष्टीकरण

मैं न एक डेटाबेस के लिए उपयोग की जरूरत के रूप में यह एक यूनिट परीक्षण का हिस्सा है और मैं अपने कोड का परीक्षण करने के लिए एक डेटाबेस बनाए रखने के लिए है करने के लिए wan't नहीं करना चाहती। जो परियोजना से अधिक समय तक जीवित रह सकता है।

उत्तर

36

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

+0

सहमत हुए। Regexp के अलावा अन्य कुछ दृष्टिकोण की आवश्यकता है। किसी चयनित कथन के लिए कानूनी वाक्यविन्यास से मिलान करने का कोई तरीका नहीं है: http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_10002.htm#SQLRF01702 –

+0

सहमत हैं। असल में, आपको एक एसक्यूएल पार्सर चाहिए। यहां एक आलेख दिखाया गया है कि सामान्य एसक्यूएल पार्सर की सहायता से विक्रेता-विशिष्ट ऑफ़लाइन एसक्यूएल सिंटैक्स चेक कैसे करें: http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use- सामान्य -एसक्ल-पार्सर/विक्रेता-विशिष्ट-ऑफलाइन-एसक्यूएल-सिंटैक्स-चेक/ –

+1

किसी भी संदर्भ मुक्त व्याकरण को आधुनिक नियमित अभिव्यक्तियों द्वारा पार्स किया जा सकता है। नियमित अभिव्यक्तियों को नियमित भाषाओं को पार्स करने के लिए अब तक सीमित नहीं हैं। यदि यह सत्य था, तो भाषा '{a^nb^n}' पारदर्शी नहीं होगी, हालांकि इसे नियमित अभिव्यक्ति '/^(ए (\ 1)? बी) $/'द्वारा पार्स किया जा सकता है। अधिक जानकारी के लिए https://nikic.github.io/2012/06/15/The-true-power-of-regular-expressions.html देखें। – Jack

0

क्या आपने आलसी चयनकर्ताओं की कोशिश की है। जितना संभव हो सके मिलान करने के बजाय, वे जितना संभव हो उतना कम मिलान करते हैं जो शायद उद्धरणों के लिए आपको चाहिए।

0

मुझे लगता है कि आपने ऐसा कुछ किया है "। *" इसके बजाय कोशिश करें "[^"] * "जो आपको पूरी लाइन खाने से रोक देगा। यह अभी भी उन मामलों पर झूठी सकारात्मक स्थिति देगा जहां आपके पास आपके तारों के अंदर \" ।

+0

नहीं मैंने \ s स्पेस और हाइफ़न निर्दिष्ट किया है और यह लाइन –

1

मेरे सिर के ऊपर बंद: नहीं आप एक डेटाबेस के लिए उत्पन्न एसक्यूएल गुजरती हैं और उन पर व्याख्या और किसी भी अपवाद जो खराब गठन एसक्यूएल का संकेत होगा पकड़ने का उपयोग कर सकते हैं?

+0

लाइन के अंत में चला गया है जो यूनिट परीक्षण के लिए उपयोगी नहीं है, जहां मुझे आवश्यक रूप से किसी डेटाबेस तक पहुंच नहीं हो सकती है, जो मुझे पता है कि हमेशा चल रहा होगा –

+0

पर निर्भर करता है सर्वर, उदाहरण के लिए, MySQL केवल चुनिंदा बयानों पर व्याख्या करने की अनुमति देता है। – pilsetnieks

0

प्रश्नों को मान्य करने के लिए, बस SET NOEXEC ON के साथ उन्हें चलाने के लिए, कि कैसे Entreprise प्रबंधक यह होता है जब आप इसे क्रियान्वित करने के बिना एक क्वेरी को पार्स है।

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

0

मैं एक ही स्कीमा के साथ एक डेटाबेस बनाने का सुझाव है, संभवतः एक एम्बेडेड एसक्यूएल इंजन का उपयोग कर, और कहा कि करने के लिए एसक्यूएल गुजर।

0

मुझे नहीं लगता है कि आप भी क्योंकि इस प्रणाली OBJECT_NAME आदि को हल करने जब तक यह बयान सफलतापूर्वक पार्स है की कोशिश नहीं करेंगे, बयान मान्य करने के लिए सक्षम होने के लिए बनाई गई स्कीमा की आवश्यकता है। इस मामले में, ": तालिका या दृश्य मौजूद नहीं है ORA-00942" में

select * from non_existant_table; 

:

एक उदाहरण के रूप ओरेकल के साथ

, आप निश्चित रूप से कोई त्रुटि मिलती है अगर तुमने किया था।

लेकिन यदि आप निष्पादित करें:

select * frm non_existant_table; 

तो फिर तुम एक सिंटैक्स त्रुटि मिल जाएगा, "ORA-00923: कीवर्ड से नहीं, जहां की उम्मीद नहीं मिला"।

यह वाक्य रचना पार्सिंग त्रुटि है कि गलत वाक्यविन्यास और तालिकाओं नाम और अनुमतियाँ आदि से संबंधित त्रुटियों का संकेत में त्रुटियों को वर्गीकृत करने के लिए संभव होना चाहिए ..

में जोड़े कि विभिन्न RDBMSs और यहां तक ​​कि विभिन्न संस्करणों की समस्या अलग वाक्यविन्यास की इजाजत दी और मुझे लगता है कि आपको वास्तव में इस कार्य के लिए डीबी इंजन में जाना है।

2

जहां तक ​​मुझे पता है कि यह रेगेक्स से परे है और आप बीएनएफ और कंपाइलर्स के अंधेरे कलाओं के करीब आ रहे हैं।

http://savage.net.au/SQL/

वही बातें लोग हैं, जो सही वाक्य रचना हाइलाइटिंग क्या करना चाहते करने के लिए होता है। आप चीजों को रेगेक्स में क्रैम करना शुरू करते हैं और फिर आप एक कंपाइलर लिखते हैं ...

14

एसक्यूएल type-2 grammar है, यह नियमित अभिव्यक्तियों द्वारा वर्णित होने के लिए बहुत शक्तिशाली है। यह वही है जैसे आपने सी # कोड उत्पन्न करने का निर्णय लिया और उसके बाद संकलक का आविष्कार किए बिना इसे सत्यापित किया। सामान्य रूप से डेटाबेस इंजन आसानी से stubbed करने के लिए बहुत जटिल है।

उस ने कहा, आप ANTLR's SQL grammars आज़मा सकते हैं।

+0

किसी भी संदर्भ मुक्त व्याकरण को आधुनिक नियमित अभिव्यक्तियों द्वारा पार्स किया जा सकता है। नियमित अभिव्यक्तियों को नियमित भाषाओं को पार्स करने के लिए अब तक सीमित नहीं हैं। यदि यह सत्य था, तो भाषा '{a^nb^n}' पारदर्शी नहीं होगी, हालांकि इसे नियमित अभिव्यक्ति '/^(ए (\ 1)? बी) $/'द्वारा पार्स किया जा सकता है। अधिक जानकारी के लिए https://nikic.github.io/2012/06/15/The-true-power-of-regular-expressions.html देखें। – Jack

+0

@ जैक, अच्छा बिंदु! तो एएनएसआई एसक्यूएल चयन के लिए सी # regex क्या होगा? – Constantin

0

एसक्यूएल पार्स करने के लिए ANTLR grammars हैं। in memory database या sqlite जैसे बहुत हल्के डेटाबेस का उपयोग करना वास्तव में एक बेहतर विचार है। यह जांचने के लिए मुझे अपमानजनक लगता है कि एसक्यूएल एक पार्सिंग दृष्टिकोण से मान्य है, और तालिका और कॉलम नामों और आपकी क्वेरी के विनिर्देशों को जांचने के लिए और अधिक उपयोगी है।

1

मुझे एक ही समस्या थी - एक दृष्टिकोण जो सभी मानक एसक्यूएल स्टेटमेंट्स के लिए काम करेगा, एक मेमोरी स्क्लाइट डेटाबेस को स्पिन करना होगा और इसके खिलाफ क्वेरी जारी करना होगा, अगर आप वापस आते हैं "तालिका मौजूद नहीं है "त्रुटि, तो आपकी क्वेरी ठीक से पार्स किया गया।

-1
public bool IsValid(string sql) 
{ 
string pattern = @"SELECT\s.*FROM\s.*WHERE\s.*"; 
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); 
return rgx.IsMatch(sql); 
} 
+4

बहुत सीमित वाक्यविन्यास सत्यापन और कोई स्पष्टीकरण नहीं ... – jessehouwing

+0

लेकिन एकमात्र ACTUAL प्रश्न का उत्तर देने का प्रयास करें: +1 –

0

सबसे अच्छा तरीका क्वेरी बनाने के बजाय क्वेरी बनाने के लिए उपयोग किए गए पैरामीटर को सत्यापित करने का सबसे अच्छा तरीका है। एक फ़ंक्शन जो चर प्राप्त करता है तारों, मान्य संख्याओं, मान्य ईमेल या जो भी हो, की लंबाई की जांच कर सकता है। आप इस सत्यापन को करने के लिए नियमित अभिव्यक्तियों का उपयोग कर सकते हैं।

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

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