tags:

views:

146

answers:

2

My goal is to execute a query (SELECT), fetch results and output them as text. Query is given as a parameter and can be e.g. select * from t.

I use OCIStmtPrepare and OCIStmtExecute, then I can describe columns of the query by OCIParamGet and series of OCIAttrGet. Suppose I get OCI_ATTR_DATA_TYPE = 12 (DATE) for one of the columns. Then OCI_ATTR_DATA_SIZE = 7 -- this is size of internal DATE representation.

I want to get this DATE as text, with respect to currect NLS settings. For that I use OCIDefineByPos with dty = SQLT_STR. It works alright, but I also need to supply a buffer for fetching. The question is: what size of buffer do I need?


Evidently it depends on NLS_DATE_FORMAT. I believe that Oracle knows this value:

SQL> create table x as select to_char(sysdate) d from dual;

Table created.

SQL> select value from nls_session_parameters where parameter='NLS_DATE_FORMAT';

VALUE                                                                           
----------------------------------------                                        
DD.MM.RR                                                                        

SQL> select data_length from dba_tab_columns where table_name='X';

DATA_LENGTH                                                                     
-----------                                                                     
          8

This is the exact length. Only when date format is masked from Oracle (by a function, for example), it uses absolute maximum (?) value of 75:

SQL> create or replace function get_date_format return varchar2 is
  2  begin
  3    return 'DD.MM.RR';
  4  end;
  5  /

Function created.

SQL> create table x as select to_char(sysdate,get_date_format) d from dual;

Table created.

SQL> select data_length from dba_tab_columns where table_name='X';

DATA_LENGTH                                                                     
-----------                                                                     
         75

All said above applies to NUMBER as well.
So, is it possible to get length of text representation of a column in OCI?

+1  A: 

The maximum buffer size for any date is 75. The maximum buffer size for any number is 42.

I hope that helps.

Philip Schlump
42? Fan of Douglas Adams? :) Seriously, how did you get it? The same trick with "create table" gave me 40 on 9.2.0.7. Anyway, it is waste of memory to allocate maximum size...
egorius
I was the chief technical architect for a project for IBM where we internationalized a product using Oracle for the back end (It used DB2 also) and that was the size that we used. It was in some Oracle documentation on internationalization.
Philip Schlump
+1  A: 

You can determine needed buffer size by calling OCIAttrGet for OCI_ATTR_DISP_SIZE attribute. It returns 40 for NUMBER, 75 for DATE, N for VARCHAR2(N). Add 1 byte for Null-termination and you good to go.

Nikolai
Thanks Nikolai, it's better than hardcoding maximum sizes for different datatypes. Still its waste of memory, and I want to get actual size (regarding to NLS parameters).
egorius