平台:vc++6.0
数据库:oracle10.1
语言:C
系统配置文件pcscfg.cfg配置如下:
char_map=string
DYNAMIC=ANSI
mode=ANSI
parse=full
SQLCHECK=SEMANTICS
RELEASE_CURSOR=NO
HOLD_CURSOR=YES
VARCHAR=YES
userid=scott/scottpwd
include=C:\Program Files\Microsoft Visual Studio\VC98\Include
include=C:\oracle\product\10.1.0\db_1\precomp\public
include=C:\oracle\product\10.1.0\db_1\OCI\include
我在PC程序中使用ANSI动态SQL方法四时出现以上错误
ANSI动态SQL方法四代码如下:/*定义绑定变量值和数据值的最大长度*/
#define MAX_VAR_LEN 200
/*定义选择列表项名称的最大长度*/
#define MAX_NAME_LEN 31/*定义宿主变量用以存储动态SQL语句*/
EXEC SQL BEGIN DECLARE SECTION;
char sql_stat[100];
EXEC SQL END DECLARE SECTION; void dysql(void); //动态SQL
void process_input(void);
void process_output(void);int main(void)
{
dysql();
return 0;
}
void dysql(void)
 {  
EXEC SQL ALLOCATE DESCRIPTOR   'input_desc'; //分配输入描述区
EXEC SQL ALLOCATE DESCRIPTOR   'output_desc'; //分配输出描述区
printf("\n");
 /*循环处理动态SQL语句*/
for(;;)
{
printf("输入动态SQL语句(exit:退出):\n");
gets(sql_stat);
fflush(stdin);
/*exit(EXIT):退出*/
if((strncmp(sql_stat,"exit",4)==0) || (strncmp(sql_stat,"EXIT",4)==0))
break;
/*准备sql语句*/
EXEC SQL PREPARE S FROM :sql_stat;
/*定义游标*/
EXEC SQL DECLARE C CURSOR FOR S;
/*处理绑定变量*/
process_input();
/*
打开游标
select 语句:处理查询给果
其他sql语句:执行
*/
EXEC SQL OPEN C USING DESCRIPTOR 'input_desc';
if((strncmp(sql_stat,"select",6)==0) || (strncmp(sql_stat,"SELECT",6)==0))
process_output();
EXEC SQL CLOSE C;
}
EXEC SQL DEALLOCATE DESCRIPTOR   'input_desc'; //释放输入描述区
EXEC SQL DEALLOCATE DESCRIPTOR   'output_desc'; //释放输出描述区
EXEC SQL COMMIT;
printf("\n谢谢你使用动态SQL语句!.\n");
  printf("\n");
  /*
  出错原因为:SQL-02145: 动态描述符无效
  */
 }  //end function dysql() void process_input(void)
{
/*定义宿主变量*/
EXEC SQL BEGIN DECLARE SECTION;
int i;
char chname[31];
int input_count;
int input_len;
int occurs;
int ANSI_varchar_type;
char input_buf[MAX_VAR_LEN];
EXEC SQL END DECLARE SECTION;
/*绑定变量-->输入描述区*/
EXEC SQL DESCRIBE INPUT S
USING DESCRIPTOR 'input_desc';
/*取得绑定变量的个数*/
EXEC SQL GET DESCRIPTOR 'input_desc' :input_count = COUNT;
/*数值类型-->变长字符串*/
ANSI_varchar_type=12;
for(i=0;i<input_count;i++)
{
occurs=i+1;
/*绑定变量名-->宿主变量*/
EXEC SQL GET DESCRIPTOR 'input_desc' VALUE :occurs:chname=NAME;
/*显示绑定变量名*/
printf("\n输入%s的值: ",chname);
/*为输入宿主变量输入数据*/
gets(input_buf);
fflush(stdin);
/*设置变量-->null终止*/
input_len=strlen(input_buf);
input_buf[input_len]='\0';
/*设置绑定变量值*/
EXEC SQL SET DESCRIPTOR 'input_desc' VALUE :occurs TYPE= :ANSI_varchar_type,LENGTH= :input_len,DATA = :input_buf;
}
}
void process_output(void)
{
/*定义宿主变量*/
EXEC SQL BEGIN DECLARE SECTION;
int i;
int output_count;
int occurs;
int type;
int len;
short indi;
char data[MAX_VAR_LEN];
char chname[MAX_NAME_LEN];
size_t chlen;
EXEC SQL END DECLARE SECTION;
 /*选择列表项-->输出描述区*/
EXEC SQL DESCRIBE OUTPUT S USING DESCRIPTOR 'output_desc';
EXEC SQL GET DESCRIPTOR 'output_desc' :output_count= COUNT;
printf("\n");
chlen=0;
/*设置类型为变长字符串*/
type=12;
len=MAX_VAR_LEN;
for(i=0;i<output_count;i++)
{
occurs=i+1;
/*设置数据类型的长度*/
EXEC SQL SET DESCRIPTOR 'output_desc' VALUE :occurs TYPE=:type,LENGTH=:len;
/*取得选择列表项的名称*/
EXEC SQL GET DESCRIPTOR 'output=desc' VALUE :occurs:chname=NAME;
chlen=strlen(chname);
chname[chlen]='\0';
/*显示选择列表项的名称*/
printf("\t chname=%s ",chname);
}
printf("\n\n");
/*提取数据完毕-->退出循环*/
EXEC SQL WHENEVER NOT FOUND do break;
for(;;)
{
/*行数据-->输出描述区*/
EXEC SQL FETCH C INTO DESCRIPTOR 'output_desc';
for(i=0;i<output_count;i++)
{
occurs=i+1;
/*取得选择列表项的数据*/
EXEC SQL GET DESCRIPTOR 'output_desc' VALUE :occurs:data=DATA, :indi=INDICATOR;
chlen=strlen(data);
data[chlen]='\0';
if(indi == -1)
printf("\tdata=%s ","  "); /*null-->显示为空格*/
else
printf("\tdata=%s ",data); /*not null-->显示数据*/
}
printf("\n");
}
}
---------------------------------------------------------------------------------------
请高手指点指点...

解决方案 »

  1.   

    官方文档:
    SQL-02145: Invalid dynamic descriptor 
    Cause: An attempt to access an unallocated or invalid descriptor was encountered.
    Action: For ANSI descriptors, check that descriptor name is valid and descriptor has been allocated and not previously deallocated. Or if using Oracle descriptors (sqlda) with mode=ansi also use dynamic=oracle.我自己乱翻译下:
    SQL-02145: 无效的动态描述符
    原因:  试图访问一个未分配的或无效的描述符
    动作:  对于ANSI的描述符, 检查这个描述符的名字是不是有效, 并且描述符是不是被分配并且没有在事先解除分配. 或者在ansi模式下使用Oracle的描述符(sqlda) 并且使用dynamic=oracle.楼主尝试使用下动作里的解决办法?
      

  2.   

    不好意思地问一下,
    动态描述符主要指哪一些???一下是分配描述符吗?
    EXEC SQL ALLOCATE DESCRIPTOR  'input_desc'; //分配输入描述区 
    EXEC SQL ALLOCATE DESCRIPTOR  'output_desc'; //分配输出描述区 一下是解除分配吗?
    EXEC SQL DEALLOCATE DESCRIPTOR  'input_desc'; //释放输入描述区 
    EXEC SQL DEALLOCATE DESCRIPTOR  'output_desc'; //释放输出描述区
    程序中没有用Oracle的描述符(sqlda),并且dynamic=ansi. 怎么回事???
    再指点指点......
      

  3.   

    我想,
    应该是指oracle关键字吧你使用了一个没有分配的关键字? 
    如果不是, 那么"在ansi模式下使用Oracle的描述符(sqlda) 并且使用dynamic=oracle"应该可以解决问题."在ansi模式下使用Oracle的描述符(sqlda)"
    这个怎么使用, 我也不知道, 呵呵
      

  4.   

    char_map=string
    DYNAMIC=ANSI
    mode=ANSI
    parse=full
     把第二行改为DYNAMIC=oracle
    并且执行"在ansi模式下使用Oracle的描述符(sqlda)" 动作里写的话不是出错的原因, 而是出错的解决办法
      

  5.   

    当改为 DYNAMIC=oracle 时,出现以下错误:PCC-S-02443, 只当指定 DYNAMIC=ANSI 时此用法有效
    在第 320 行, 第 11 列, 文件 .\democ.pc 有语义错误: 
            EXEC SQL ALLOCATE DESCRIPTOR   'output_desc_arer'; //分配输出描述区
    ..........1哈哈
    我已解决了。
    原因是:我把“分配输入/输出描述区 ”的名字给改成了'output_desc_arer'/'input_desc_arer',
    也许是名字冲突吧。
    不过非常感谢你的认真和帮助,
    以后还得多多请教。
    现在有问题如下:
    error   C2043:   illegal   break          
     if   (sqlca.sqlcode   ==   100)   break ;
    ------------------------------------------------------------
    程序代码如下(耐心点):
    出错语句. /* EXEC SQL SELECT COUNT(LoginID) into :ok from Teacher where LoginID=:logpwd; */ { 
      struct sqlexd sqlstm; 
      sqlstm.sqlvsn = 12; 
      sqlstm.arrsiz = 4; 
      sqlstm.sqladtp = &sqladt; 
      sqlstm.sqltdsp = &sqltds; 
      sqlstm.stmt = "select count(LoginID) into :b0  from Teacher where LoginID\ 
    =:b1"; 
      sqlstm.iters = (unsigned int  )1; 
      sqlstm.offset = (unsigned int  )562; 
      sqlstm.selerr = (unsigned short)1; 
      sqlstm.cud = sqlcud0; 
      sqlstm.sqlest = (unsigned char  *)&sqlca; 
      sqlstm.sqlety = (unsigned short)256; 
      sqlstm.occurs = (unsigned int  )0; 
      sqlstm.sqhstv[0] = (        void  *)&ok; 
      sqlstm.sqhstl[0] = (unsigned int  )sizeof(int); 
      sqlstm.sqhsts[0] = (        int  )0; 
      sqlstm.sqindv[0] = (        void  *)0; 
      sqlstm.sqinds[0] = (        int  )0; 
      sqlstm.sqharm[0] = (unsigned int  )0; 
      sqlstm.sqadto[0] = (unsigned short )0; 
      sqlstm.sqtdso[0] = (unsigned short )0; 
      sqlstm.sqhstv[1] = (        void  *)logpwd; 
      sqlstm.sqhstl[1] = (unsigned int  )9; 
      sqlstm.sqhsts[1] = (        int  )0; 
      sqlstm.sqindv[1] = (        void  *)0; 
      sqlstm.sqinds[1] = (        int  )0; 
      sqlstm.sqharm[1] = (unsigned int  )0; 
      sqlstm.sqadto[1] = (unsigned short )0; 
      sqlstm.sqtdso[1] = (unsigned short )0; 
      sqlstm.sqphsv = sqlstm.sqhstv; 
      sqlstm.sqphsl = sqlstm.sqhstl; 
      sqlstm.sqphss = sqlstm.sqhsts; 
      sqlstm.sqpind = sqlstm.sqindv; 
      sqlstm.sqpins = sqlstm.sqinds; 
      sqlstm.sqparm = sqlstm.sqharm; 
      sqlstm.sqparc = sqlstm.sqharc; 
      sqlstm.sqpadto = sqlstm.sqadto; 
      sqlstm.sqptdso = sqlstm.sqtdso; 
      sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); 
      if (sqlca.sqlcode == 100) break; //此为出错原因 
      if (sqlca.sqlcode < 0) sql_error(); 

    ------------------------------ 
    正确语句: /* EXEC SQL CALL  teacher_pack.islogin_proc(:logpwd,:logname,:ok); */ { 
      struct sqlexd sqlstm; 
      sqlstm.sqlvsn = 12; 
      sqlstm.arrsiz = 4; 
      sqlstm.sqladtp = &sqladt; 
      sqlstm.sqltdsp = &sqltds; 
      sqlstm.stmt = "call teacher_pack.islogin_proc(:b0,:b1,:b2)"; 
      sqlstm.iters = (unsigned int  )1; 
      sqlstm.offset = (unsigned int  )562; 
      sqlstm.cud = sqlcud0; 
      sqlstm.sqlest = (unsigned char  *)&sqlca; 
      sqlstm.sqlety = (unsigned short)256; 
      sqlstm.occurs = (unsigned int  )0; 
      sqlstm.sqhstv[0] = (        void  *)logpwd; 
      sqlstm.sqhstl[0] = (unsigned int  )9; 
      sqlstm.sqhsts[0] = (        int  )0; 
      sqlstm.sqindv[0] = (        void  *)0; 
      sqlstm.sqinds[0] = (        int  )0; 
      sqlstm.sqharm[0] = (unsigned int  )0; 
      sqlstm.sqadto[0] = (unsigned short )0; 
      sqlstm.sqtdso[0] = (unsigned short )0; 
      sqlstm.sqhstv[1] = (        void  *)logname; 
      sqlstm.sqhstl[1] = (unsigned int  )9; 
      sqlstm.sqhsts[1] = (        int  )0; 
      sqlstm.sqindv[1] = (        void  *)0; 
      sqlstm.sqinds[1] = (        int  )0; 
      sqlstm.sqharm[1] = (unsigned int  )0; 
      sqlstm.sqadto[1] = (unsigned short )0; 
      sqlstm.sqtdso[1] = (unsigned short )0; 
      sqlstm.sqhstv[2] = (        void  *)&ok; 
      sqlstm.sqhstl[2] = (unsigned int  )sizeof(int); 
      sqlstm.sqhsts[2] = (        int  )0; 
      sqlstm.sqindv[2] = (        void  *)0; 
      sqlstm.sqinds[2] = (        int  )0; 
      sqlstm.sqharm[2] = (unsigned int  )0; 
      sqlstm.sqadto[2] = (unsigned short )0; 
      sqlstm.sqtdso[2] = (unsigned short )0; 
      sqlstm.sqphsv = sqlstm.sqhstv; 
      sqlstm.sqphsl = sqlstm.sqhstl; 
      sqlstm.sqphss = sqlstm.sqhsts; 
      sqlstm.sqpind = sqlstm.sqindv; 
      sqlstm.sqpins = sqlstm.sqinds; 
      sqlstm.sqparm = sqlstm.sqharm; 
      sqlstm.sqparc = sqlstm.sqharc; 
      sqlstm.sqpadto = sqlstm.sqadto; 
      sqlstm.sqptdso = sqlstm.sqtdso; 
      sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); 
      if (sqlca.sqlcode < 0) sql_error(); 
    } 两条语句在同一个函数中: 
    main() 

    .... 
    switch(logflag[0]) 

    case 'm': 
    case 'M': 
    managerModern(logname,logpwd); //进入管理员模块 
    break; 
    case 't': 
    case 'T': 
    teacherFunc(logname,logpwd); //进入老师模块 
    break; 
    case 's': 
    case 'S': 
    studentFunc(logname,logpwd); //进入学生模块 
    break; 
    default: 
    printf("\n身份有误!\n"); 
    exit(1); 
    break; 

    .... 

    teacherFunc(logname,logpwd); //进入老师模块 

    ..... 
    //EXEC SQL SELECT COUNT(LoginID) into :ok from Teacher where LoginID=:logpwd; //出错语句 
    EXEC SQL CALL  teacher_pack.islogin_proc(:logpwd,:logname,:ok);  //检查此老师是否注册 
    .....