我的目标是执行查询(SELECT),获取结果并将其作为文本输出 。查询作为参数给出,并且可以是例如select * from t
。
我使用OCIStmtPrepare
和OCIStmtExecute
,然后我可以按OCIParamGet
和OCIAttrGet
系列来描述查询的列。假设我为其中一列获得OCI_ATTR_DATA_TYPE
= 12(DATE)。然后OCI_ATTR_DATA_SIZE
= 7 - 这是内部DATE表示的大小。
关于当前的NLS设置,我希望将此DATE作为文本。为此,我使用OCIDefineByPos
和dty = SQLT_STR
。它工作正常,但我还需要提供一个缓冲区来获取。问题是:我需要多大的缓冲区?
显然这取决于NLS_DATE_FORMAT
。我相信Oracle知道这个价值:
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
这是确切的长度。只有当从Oracle(例如函数)屏蔽日期格式时,它才使用绝对最大值(?)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
上述所有内容也适用于NUMBER 那么,是否可以在OCI中获取列的文本表示长度?
答案 0 :(得分:1)
任何日期的最大缓冲区大小为75.任何数字的最大缓冲区大小为42。
我希望有所帮助。
答案 1 :(得分:1)
您可以通过为OCIAttrGet
属性调用OCI_ATTR_DISP_SIZE
来确定所需的缓冲区大小。它为NUMBER
返回40,DATE
返回75,VARCHAR2(N)
返回N.为Null-termination添加1个字节,你就可以了。
答案 2 :(得分:0)
是的 - 技巧是在C中,字符串实际上是指向字符数组的指针,所以你会说char* mystring = OCIStringPtr(envhp, x);
其中x是指向OCIString
的指针,你可以回来通过与OCI_OBJECT
集关联并要求SQLT_VST
代替SQLT_STR
。字符串的实际内存由OCI在幕后为全局环境分配。