मेरे पास हाल ही में एक डेवलपर ने मुझसे एक दिलचस्प सवाल पूछा था। वह एक ऐसी समस्या पर काम कर रहा था जहां संख्यात्मक मान एक तालिका में संग्रहीत किए गए थे, लेकिन जब उन्होंने पीएल/एसक्यूएल डेवलपर में उस तालिका से पूछताछ की, तो यह अंतिम अंक के बाद पिछला शून्य दिखाएगा। उन्होंने सोचा कि क्या यह उस समस्या में योगदान दे रहा है जिसे वह डीबग करने का प्रयास कर रहा था। डेवलपर को यह जानना आवश्यक था कि क्या Oracle उन अनुगामी शून्यों को संग्रहीत कर रहा है।
मेरी प्रतिक्रिया थी कि Oracle अनुगामी शून्यों को संग्रहीत नहीं करता है। Oracle केवल संख्या के प्रतिपादक और मंटिसा को संग्रहीत करता है। Oracle शून्य के साथ संख्यात्मक मान को राइट-पैड नहीं करता है। डेवलपर को अब पता चल गया था कि उसकी समस्या डेटाबेस में डेटा के साथ नहीं थी, बल्कि कुछ ऐसा था जो उसका विकास मंच कर रहा था।
लेकिन क्या मेरी बात सच थी? कई बार मैंने इस बारे में एक बयान दिया है कि ओरेकल आंतरिक रूप से कैसे काम करता है, लेकिन फिर वापस जाकर अपने बयान को मान्य करना पड़ा या साबित करना पड़ा कि यह गलत था जो अनिवार्य रूप से सही बयान की ओर जाता है।
अपने कथन का परीक्षण करने के लिए, मैंने एक साधारण तालिका बनाई और उसमें डेटा डाला।
SQL> create table test_tab (val number(38,5)); Table created. SQL> insert into test_tab values (25); 1 row created. SQL> insert into test_tab values (25.0); 1 row created. SQL> insert into test_tab values (25.2); 1 row created. SQL> insert into test_tab values (25.20); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; VAL ---------- 25 25 25.2 25.2
एसक्यूएल*प्लस में, हम कोई पिछला शून्य नहीं देखते हैं, भले ही मैंने उन्हें स्पष्ट रूप से जोड़ा है। मान 25 और 25.0 के साथ-साथ 25.2 और 25.20 सभी समान दिखते हैं। लेकिन हो सकता है कि एसक्यूएल * प्लस मूल्यों को प्रदर्शित कर रहा हो। तो चलिए डेटा ब्लॉक को डंप करते हैं यह देखने के लिए कि Oracle इन मानों को कैसे संग्रहीत कर रहा है।
SQL> select file_id,block_id,blocks 2 from dba_extents where segment_name='TEST_TAB'; FILE_ID BLOCK_ID BLOCKS ---------- ---------- ---------- 6 128 8 SQL> alter system dump datafile 6 block min 128 block max 135; System altered.
मुझे अपने द्वारा बनाए गए सेगमेंट के लिए फ़ाइल और ब्लॉक नंबर निर्धारित करना था। फिर मैंने डेटा ब्लॉक की सामग्री को ट्रेस फ़ाइल में डंप करने का आदेश जारी किया। जब आप ट्रेस फ़ाइल में देखते हैं, तो "block_row_dump" कीवर्ड खोजें और आप इन पंक्तियों की सामग्री को नीचे डंप में देख सकते हैं:
block_row_dump: tab 0, row 0, @0x1f92 tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 1a tab 0, row 1, @0x1f8c tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 1a tab 0, row 2, @0x1f85 tl: 7 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 3] c1 1a 15 tab 0, row 3, @0x1f7e tl: 7 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 3] c1 1a 15 end_of_block_dump
हम ब्लॉक डंप से देख सकते हैं कि पहला मान 2 बाइट लंबा है और इसमें हेक्स वर्ण "C1 1A" शामिल हैं। दूसरी पंक्ति में समान सटीक मान हैं! यह महत्वपूर्ण है क्योंकि यह मेरे प्रारंभिक दावे की पुष्टि करता है कि Oracle तालिका में दूसरी पंक्ति के लिए कोई अतिरिक्त शून्य संग्रहीत नहीं कर रहा है। यदि कोई अतिरिक्त शून्य होता, तो लंबाई 2 बाइट्स नहीं होती। तीसरी और चौथी पंक्ति के लिए, हम देख सकते हैं कि हेक्स मान समान हैं, "C1 1A 15"।
लेकिन आइए सुनिश्चित करें कि ये हेक्स मान हमारे डेटा के अनुरूप हैं। ऐसा करने के लिए, हम DBMS_STATS.CONVERT_RAW_VALUE प्रक्रिया का उपयोग करेंगे।
SQL> set serveroutput on SQL> declare 2 n number; 3 begin 4 dbms_stats.convert_raw_value('C11A',n); 5 dbms_output.put_line(n); 6 end; 7 / 25 PL/SQL procedure successfully completed. SQL> declare 2 n number; 3 begin 4 dbms_stats.convert_raw_value('C11A15',n); 5 dbms_output.put_line(n); 6 end; 7 / 25.2 PL/SQL procedure successfully completed.
तो हेक्स मान "C1 1A" '25' का आंतरिक (कच्चा) प्रतिनिधित्व है और "C1 1A 15" 25.2 है जैसा कि हमने उम्मीद की थी।
इस कहानी का नैतिक यह है कि कभी-कभी जब आपको लगता है कि आप जानते हैं कि ओरेकल आंतरिक रूप से कैसे काम कर रहा है, तब भी आपको अपने बयानों को मान्य करने के लिए एक परीक्षण केस तैयार करना पड़ सकता है।