从用户输入获取 SQL 标识符

如果准备好的语句需要标识符,但在您编写准备好的语句时该标识符未知,则您可构造从用户输入接收 SQL 标识符的语句。

下列 GBase 8s ESQL/C 示例提示用户输入表的名称,并在 SELECT 语句中使用该名称。由于此名称在运行时之前未知,因此该表列的数目和数据类型也未知。因此,程序不可提前分配主变量来接收每一行的数据。取而代之的是,此程序片断描述语句到一 sqlda 描述符内并以该描述符访存每一行。该访存将每一行放入程序动态地提供的内存位置内。

如果程序检索活动集合中的所有行,则 FETCH 将置于被访存的每一行的循环中。如果 FETCH 语句检索超过一个数据值(列),则在 FETCH 之后存在另一循环,对每一数据值执行一些活动:
#include <stdio.h>
EXEC SQL include sqlda;
EXEC SQL include sqltypes;
char *malloc( );

main()
{
   struct sqlda *demodesc;
   char tablename[19];
   int i;
EXEC SQL BEGIN DECLARE SECTION;
   char demoselect[200];
EXEC SQL END DECLARE SECTION;

/*  该程序选择给定的 tablename 的所有列。
       交互地提供该 tablename。 */

EXEC SQL connect to 'stores_demo';
printf( "This program does a select * on a table\n" );
printf( "Enter table name: " );
scanf( "%s", tablename );
sprintf(demoselect, "select * from %s", tablename );

EXEC SQL prepare iid from :demoselect;
EXEC SQL describe iid into demodesc;

/* 打印描述返回的内容 */

for ( i = 0;  i < demodesc->sqld; i++ )
   prsqlda (demodesc->sqlvar + i);
/* 指定数据指针。 */

for ( i = 0;  i < demodesc->sqld; i++ ) 
   {
   switch (demodesc->sqlvar[i].sqltype & SQLTYPE) 
      {
      case SQLCHAR:
         demodesc->sqlvar[i].sqltype = CCHARTYPE;
         /* 为空结束符制造空间 */
         demodesc->sqlvar[i].sqllen++;
         demodesc->sqlvar[i].sqldata = 
            malloc( demodesc->sqlvar[i].sqllen );
         break;

      case SQLSMINT:    /* 失败 */
      case SQLINT:      /* 失败 */
      case SQLSERIAL:
         demodesc->sqlvar[i].sqltype = CINTTYPE;
         demodesc->sqlvar[i].sqldata = 
            malloc( sizeof( int ) );
         break;
      /*  对每一类型亦然。  */
      }
   }

/* 为选择声明和打开游标。 */
EXEC SQL declare d_curs cursor for iid;
EXEC SQL open d_curs;

/* 每次将被选择的行访存到 demodesc 内。 */
for( ; ; ) 
   {
   printf( "\n" );
   EXEC SQL fetch d_curs using descriptor demodesc;
   if ( sqlca.sqlcode != 0 )
       break;
   for ( i = 0;  i < demodesc->sqld; i++ ) 
      {
      switch (demodesc->sqlvar[i].sqltype) 
         {
         case CCHARTYPE:
            printf( "%s: \"%s\n", demodesc->sqlvar[i].sqlname,
               demodesc->sqlvar[i].sqldata );
            break;
         case CINTTYPE:
            printf( "%s: %d\n", demodesc->sqlvar[i].sqlname,
               *((int *) demodesc->sqlvar[i].sqldata) );
            break;
         /* 对每一类型亦然…… */
            }
      }
   }
EXEC SQL close d_curs;
EXEC SQL free d_curs;
/*  释放数据内存。  */

for ( i = 0;  i < demodesc->sqld; i++ )
   free( demodesc->sqlvar[i].sqldata );
free( demodesc );

printf ("Program Over.\n");
}

prsqlda(sp)
   struct sqlvar_struct *sp;
   
   {
   printf ("type = %d\n", sp->sqltype);
   printf ("len = %d\n", sp->sqllen);
   printf ("data = %lx\n", sp->sqldata);
   printf ("ind = %lx\n", sp->sqlind);
   printf ("name = %s\n", sp->sqlname);
   }