2008-12-09 13 views
6

बिना कॉलम नामों के एसक्लप्लस ट्रंकेशन को रोकना डिफ़ॉल्ट रूप से sqlplus कॉलम नामों को अंतर्निहित डेटा प्रकार की लंबाई तक छोटा करता है। हमारे डेटाबेस में कॉलम नामों में से कई तालिका नाम से पहले से चिपके हुए हैं, और इसलिए छंटनी के दौरान समान दिखते हैं।व्यक्तिगत कॉलम स्वरूपण

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

(मैं सेट मार्कअप HTML पर उपयोग कर रहा हूँ, हालांकि मैं कुछ अन्य साधन, csv, आदि के रूप में लंबे समय के रूप में यह बिना काट-छांट उत्पादन पैदावार इस्तेमाल कर सकते हैं।)

उत्तर

1

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

यह एक त्वरित सबूत अवधारणा-का-मैं एक साथ फेंक दिया है:

#!/usr/bin/python 

import sys 
import cx_Oracle 

response=raw_input("Enter schema.table_name: ") 
(schema, table) = response.split('.') 
schema = schema.upper() 
table = table.upper() 
sqlstr = """select column_name, 
        data_type, 
        data_length 
       from all_tab_cols 
      where owner  = '%s' 
       and table_name = '%s'""" % (schema, table) 

## open a connection to databases... 
try: 
    oracle = cx_Oracle.Connection(oracleLogin) 
    oracle_cursor = oracle.cursor() 

except cx_Oracle.DatabaseError, exc: 
    print "Cannot connect to Oracle database as", oracleLogin 
    print "Oracle Error %d: %s" % (exc.args[0].code, exc.args[0].message) 
    sys.exit(1) 

try: 
    oracle_cursor.execute(sqlstr) 

    # fetch resultset from cursor 
    for column_name, data_type, data_length in oracle_cursor.fetchmany(256): 
     data_length = data_length + 0 
     if data_length < len(column_name): 
      if data_type == "CHAR" or data_type == "VARCHAR2": 
       print "column %s format a%d" % (column_name.upper(), len(column_name)) 
      else: 
       print "-- Handle %s, %s, %d" % (column_name, data_type, data_length) 

except cx_Oracle.DatabaseError, e: 
    print "[Oracle Error %d: %s]: %s" % (e.args[0].code, e.args[0].message, sqlstr) 
    sys.exit(1) 

try: 
    oracle_cursor.close() 
    oracle.close() 
except cx_Oracle.DatabaseError, exc: 
    print "Warning: Oracle Error %d: %s" % (exc.args[0].code, exc.args[0].message) 

print "select *" 
print "from %s.%s" % (schema, table) 
+0

पायथन कोड के लिए धन्यवाद, दुर्भाग्यवश हमारे ग्राहक सख्ती से अपने उत्पादन वातावरण में किसी भी अन्य सॉफ्टवेयर की स्थापना को प्रतिबंधित करते हैं। यहां तक ​​कि grep या पूंछ भी नहीं। ओह। तो यह sqlplus या बस्ट है। –

+0

यह पूरी तरह से असंबंधित कारणों के लिए सहायक होने के लिए मिला। खुशी है कि आप इसे पोस्ट किया! :- डी –

3

एक बात तुम कोशिश कर सकते "कॉलम एक्स प्रारूप A20" आदेशों गतिशील उत्पन्न करने के लिए है। निम्न की तरह कुछ:

set termout off 
set feedback off 

spool t1.sql 
select 'column ' || column_name || ' format a' || data_length 
from all_tab_cols 
where table_name='YOUR_TABLE' 
/
spool off 

@t1.sql 
set pagesize 24 
set heading on 
spool result.txt 
select * 
from YOUR_TABLE; 
and rownum < 30; 
spool off 

ध्यान दें कि यह नमूना केवल VARCHAR2 के साथ काम करेगा। DATE या NUMBER के लिए जेनरेट किए गए "कॉलम" कमांड को बदलने के लिए आपको डीकोड जोड़ने की आवश्यकता होगी।

अद्यतन: यह पता चला है कि मूल एसक्यूएल वास्तव में एसक्यूएल * प्लस के व्यवहार को नहीं बदलता है।

column DEPT_NO heading "A" 
column NAME heading "B" 
column SUPERVIS_ID heading "C" 
column ADD_DATE heading "D" 
column REPORT_TYPE heading "E" 
:

select 'column ' || column_name || 
     ' heading "' || 
     chr(ascii('A') - 1 + column_id) || 
     '"' 
from all_tab_cols 
where table_name='YOUR_TAB_NAME' 

यह उत्पादन के समान उत्पन्न करेगा: केवल एक चीज मैं के बारे में सोच सकता है के लिए एक चरित्र .. महत्व देता ए, बी, सी, आदि निम्नलिखित तरीके से फ़ील्ड का नाम बदलना करने के लिए है

+0

हम्म, थोड़ा भारी हाथ, लेकिन मुझे लगता है कि काम कर सकता है। सिवाय इसके कि मुझे नहीं लगता कि आपका मतलब डेटा_लेथेंथ है। क्या यह केवल अंतर्निहित डेटा प्रकार की लंबाई नहीं होगी, और इसलिए डिफ़ॉल्ट sqlplus व्यवहार में परिणाम होगा? क्या शायद एक स्ट्रिंग लम्बाई ऑपरेशन है जिसे कॉलम नाम पर लागू किया जा सकता है? –

+0

क्रिस, आप सही हैं। मुझे अभी एहसास हुआ कि यह केवल मूल्यों के प्रारूप को प्रभावित करता है न कि शीर्षक के प्रारूप को। पोस्ट के अपडेट में थोड़ा अलग दृष्टिकोण के लिए स्टेटमेंट का चयन करें। –

+0

तो मैं ए, बी, सी, आदि लेबल वाले कॉलम दिखा रहा हूं ... लेकिन मेरा लक्ष्य आउटपुट के लिए मूल कॉलम नाम दिखाने के लिए है, अवांछित, ताकि मैं बता सकूं कि कौन सा कॉलम है। –

2

यह कुछ उचित स्वरूपण प्रदान करना चाहिए। आप निश्चित रूप से, चार कॉलम की अधिकतम चौड़ाई के लिए अपनी प्राथमिकताओं को प्रतिस्थापित करने के लिए स्वतंत्र हैं, और लंबे, रॉ और LOB कॉलम के साथ क्या करना है।

SELECT 'COLUMN ' || column_name || ' FORMAT ' || 
     CASE 
      WHEN data_type = 'DATE' THEN 
      'A9' 
      WHEN data_type LIKE '%CHAR%' THEN 
      'A' || 
      TRIM(TO_CHAR(LEAST(GREATEST(LENGTH(column_name), 
         data_length), 40))) || 
      CASE 
       WHEN data_length > 40 THEN 
       ' TRUNC' 
       ELSE 
       NULL 
      END 
      WHEN data_type = 'NUMBER' THEN 
      LPAD('0', GREATEST(LENGTH(column_name), 
      NVL(data_precision, data_length)), '9') || 
      DECODE(data_scale, 0, NULL, NULL, NULL, '.' || 
      LPAD('0', data_scale, '0')) 
      WHEN data_type IN ('RAW', 'LONG') THEN 
      'A1 NOPRINT' 
      WHEN data_type LIKE '%LOB' THEN 
      'A1 NOPRINT' 
      ELSE 
      'A' || TRIM(TO_CHAR(GREATEST(LENGTH(column_name), data_length))) 
     END AS format_cols 
    FROM dba_tab_columns 
WHERE owner = 'SYS' 
    AND table_name = 'DBA_TAB_COLUMNS'; 
1

अगर आप की जरूरत नहीं है या XML फ़ॉर्मेटिंग चाहते हैं, लेकिन आप DBMS_XMLGEN package उपयोग करने के लिए सक्षम होना चाहिए एक हैक का एक सा है। इस स्क्रिप्ट को टैग नाम के रूप में पूर्ण कॉलम नाम के साथ मनमानी क्वेरी के लिए आपको एक XML फ़ाइल देना चाहिए।

VARIABLE resultXML clob; 
SET LONG 100000; -- Set to the maximum size of the XML you want to display (in bytes) 
SET PAGESIZE 0; 

DECLARE 
    qryCtx DBMS_XMLGEN.ctxHandle; 
BEGIN 
    qryCtx := dbms_xmlgen.newContext('SELECT * from scott.emp'); 

    -- now get the result 
    :resultXML := DBMS_XMLGEN.getXML(qryCtx); 

    --close context 
    DBMS_XMLGEN.closeContext(qryCtx); 
END; 
/

print resultXML 
0

मैं एक ही VoraX में इस सुविधा को लागू करने की कोशिश कर समस्या थी। अगले संस्करण में मेरे मन में निम्नलिखित समाधान है:

set feedback off 
set serveroutput on 
declare 
    l_c number; 
    l_col_cnt number; 
    l_rec_tab DBMS_SQL.DESC_TAB2; 
    l_col_metadata DBMS_SQL.DESC_REC2; 
    l_col_num number; 
begin 
    l_c := dbms_sql.open_cursor; 
    dbms_sql.parse(l_c, '<YOUR QUERY HERE>', DBMS_SQL.NATIVE); 
    DBMS_SQL.DESCRIBE_COLUMNS2(l_c, l_col_cnt, l_rec_tab); 
    for colidx in l_rec_tab.first .. l_rec_tab.last loop 
    l_col_metadata := l_rec_tab(colidx); 
    dbms_output.put_line('column ' || l_col_metadata.col_name || ' heading ' || l_col_metadata.col_name); 
    end loop; 
    DBMS_SQL.CLOSE_CURSOR(l_c); 
end; 
इसके बजाय स्तंभ आकार में सुधार करने, स्वरूपण और सामान बस स्तंभ स्तंभ नाम आप चाहते हैं के साथ शीर्षक लागू की

। मुझे लगता है कि एक ही दृष्टिकोण DBA_TAB_COLUMNS समाधान के साथ भी काम करेगा, लेकिन मैं डीबीएमएस_SQL एक को प्राथमिकता देता हूं क्योंकि यह उपनामों को भी मानता है और यह केवल आपके द्वारा पूछे जाने वाले कॉलम प्राप्त करता है।

संपादित करें: केवल "कॉलम शीर्षक" का उपयोग करना काम नहीं करता है। "कॉलम प्रारूप" कथन का उपयोग करने के लिए अभी भी इसकी आवश्यकता है। तो, कृपया मेरे पिछले जवाब को अनदेखा करें।

2

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

उदा।

SET ECHO OFF 
SET PAGESIZE 32766 
SET LINESIZE 32766 
SET NUMW 20 
SET VERIFY OFF 
SET TERM OFF 
SET UNDERLINE OFF 
SET MARKUP HTML ON 
SET PREFORMAT ON 
SET WORD_WRAP ON 
SET WRAP ON 
SET ENTMAP ON 
spool '/tmp/Example.html' 
select 
    (s.ID||'     ') AS ID, 
    (s.ORDER_ID||'     ') AS ORDER_ID, 
    (s.ORDER_NUMBER||'     ') AS ORDER_NUMBER, 
    (s.CONTRACT_ID||'     ') AS CONTRACT_ID, 
    (s.CONTRACT_NUMBER||'     ') AS CONTRACT_NUMBER, 
    (s.CONTRACT_START_DATE||'     ') AS CONTRACT_START_DATE, 
    (s.CONTRACT_END_DATE||'     ') AS CONTRACT_END_DATE, 
    (s.CURRENCY_ISO_CODE||'     ') AS CURRENCY_ISO_CODE, 
from Example s 
order by s.order_number, s.contract_number; 
spool off; 

बेशक आप कुछ बेहतर करने के लिए एक संग्रहीत प्रक्रिया लिख ​​सकता है, लेकिन वास्तव में यह इस सरल परिदृश्य के लिए overkill की तरह लगता है।

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

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

SET ECHO OFF 
SET TERMOUT OFF 
SET FEEDBACK OFF 
SET PAGESIZE 32766 
SET LINESIZE 32766 
SET MARKUP HTML OFF 
SET HEADING OFF 

spool /tmp/columns_EXAMPLE.sql 
select 'column ' || column_name || ' format A32766' 
from all_tab_cols 
where data_type = 'VARCHAR2' and table_name = 'EXAMPLE' 
/
spool off 

SET HEADING ON 
SET NUMW 40 
SET VERIFY OFF 
SET TERM OFF 
SET UNDERLINE OFF 
SET MARKUP HTML ON 
SET PREFORMAT ON 
SET WORD_WRAP ON 
SET WRAP ON 
SET ENTMAP ON 
@/tmp/columns_EXAMPLE.sql 
spool '/tmp/Example.html' 
select * 
from Example s 
order by s.order_number, s.contract_number; 
spool off; 
संबंधित मुद्दे