Collection Contents Précédent Suivant PDF

ASA - Guide de programmation

Programmation avec Embedded SQL

Lecture de données

Extraction simultanée de plusieurs lignes


Il est possible de modifier l'instruction FETCH afin d'extraire plusieurs lignes simultanément, ce qui peut améliorer les performances. On parle alors d'extraction étendue ou de lecture de tableau.

Adaptive Server Anywhere prend également en charge des instructions PUT et INSERT étendues. Pour plus d'informations sur ces instructions, reportez-vous aux sections Instruction PUT [ESQL] et Instruction EXECUTE [ESQL].

Pour effectuer des extractions étendues en Embedded SQL, vous devez inclure l'instruction FETCH dans votre code comme suit :

EXEC SQL FETCH . . . ARRAY nnn

où ARRAY nnn est le dernier élément de l'instruction. Le nombre d'extractions nnn peut être une variable hôte. Le nombre de variables de la SQLDA doit correspondre au produit de nnn et du nombre de colonnes par ligne. La première ligne est placée dans les variables SQLDA 0 (zéro) à (colonnes par ligne)-1, etc.

Le type de chaque colonne doit être identique dans chaque ligne de la SQLDA. Dans le cas contraire, une erreur SQLDA_INCONSISTENT est renvoyée.

Le serveur renvoie dans SQLCOUNT le nombre d'enregistrements extraits, qui est toujours supérieur à zéro, sauf s'il y a des erreurs ou des avertissements. Dans le cas d'une extraction étendue, une valeur SQLCOUNT égale à  1 sans condition d'erreur indique qu'une ligne correcte a été extraite.

Exemple 

L'exemple suivant illustre l'utilisation d'extractions étendues. Ce code figure dans le fichier samples\ASA\esqlwidefetch\widefetch.sqc du répertoire SQL Anywhere.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqldef.h"
EXEC SQL INCLUDE SQLCA;

EXEC SQL WHENEVER SQLERROR { PrintSQLError();
              goto err; };

static void PrintSQLError()
/*************************/
{
    char buffer[200];

    printf( "SQL error %d -- %s\n",
       SQLCODE,
       sqlerror_message( &sqlca,
               buffer,
               sizeof( buffer ) ) );
}
static SQLDA * PrepareSQLDA(
   a_sql_statement_number   stat0,
   unsigned      width,
   unsigned      *cols_per_row )
/*********************************************/
/* Allocate a SQLDA to be used for fetching from
   the statement identified by "stat0". "width"
   rows will be retrieved on each FETCH request.
   The number of columns per row is assigned to
   "cols_per_row". */
{
    int                     num_cols;
    unsigned                row, col, offset;
    SQLDA *                 sqlda;
    EXEC SQL BEGIN DECLARE SECTION;
    a_sql_statement_number  stat;
    EXEC SQL END DECLARE SECTION;
    stat = stat0;
    sqlda = alloc_sqlda( 100 );
    if( sqlda == NULL ) return( NULL );
    EXEC SQL DESCRIBE :stat INTO sqlda;
    *cols_per_row = num_cols = sqlda->sqld;
    if( num_cols * width > sqlda->sqln ) {
        free_sqlda( sqlda );
        sqlda = alloc_sqlda( num_cols * width );
        if( sqlda == NULL ) return( NULL );
        EXEC SQL DESCRIBE :stat INTO sqlda;
    }
    // copy first row in SQLDA setup by describe
    // to following (wide) rows
    sqlda->sqld = num_cols * width;
    offset = num_cols;
    for( row = 1; row < width; row++ ) {
        for( col = 0;
        col < num_cols;
             col++, offset++ ) {
            sqlda->sqlvar[offset].sqltype =
                  sqlda->sqlvar[col].sqltype;
            sqlda->sqlvar[offset].sqllen =
                 sqlda->sqlvar[col].sqllen;
       // optional: copy described column name
            memcpy( &sqlda->sqlvar[offset].sqlname,
                    &sqlda->sqlvar[col].sqlname,
                    sizeof( sqlda->sqlvar[0].sqlname ) );
        }
    }
    fill_s_sqlda( sqlda, 40 );
    return( sqlda );
err:
    return( NULL );
}
static void PrintFetchedRows( SQLDA * sqlda,
               unsigned cols_per_row )
/******************************************/
/* Print rows already wide fetched in the SQLDA */
{
    long                    rows_fetched;
    int             row, col, offset;

    if( SQLCOUNT == 0 ) {
       rows_fetched = 1;
    } else {
         rows_fetched = SQLCOUNT;
    }
    printf( "Fetched %d Rows:\n", rows_fetched );
    for( row = 0; row < rows_fetched; row++ ) {
        for( col = 0; col < cols_per_row; col++ ) {
          offset = row * cols_per_row + col;
          printf( " \"%s\"",
            (char *)sqlda->sqlvar[offset]
               .sqldata );
         }
         printf( "\n" );
    }
}
static int DoQuery( char * query_str0,
               unsigned fetch_width0 )
/*****************************************/
/* Wide Fetch "query_str0" select statement
 * using a width of "fetch_width0" rows" */
{
    SQLDA *                 sqlda;
    unsigned          cols_per_row;
    EXEC SQL BEGIN DECLARE SECTION;
    a_sql_statement_number  stat;
    char *          query_str;
    unsigned          fetch_width;
    EXEC SQL END DECLARE SECTION;

    query_str = query_str0;
    fetch_width = fetch_width0;

    EXEC SQL PREPARE :stat FROM :query_str;
    EXEC SQL DECLARE QCURSOR CURSOR FOR :stat
           FOR READ ONLY;
    EXEC SQL OPEN QCURSOR;
    sqlda = PrepareSQLDA( stat,
           fetch_width,
           &cols_per_row );
    if( sqlda == NULL ) {
        printf( "Error allocating SQLDA\n" );
        return( SQLE_NO_MEMORY );
    }
    for( ;; ) {
        EXEC SQL FETCH QCURSOR INTO DESCRIPTOR sqlda
           ARRAY :fetch_width;
        if( SQLCODE != SQLE_NOERROR ) break;
            PrintFetchedRows( sqlda, cols_per_row );
    }
    EXEC SQL CLOSE QCURSOR;
    EXEC SQL DROP STATEMENT :stat;
    free_filled_sqlda( sqlda );
err:
    return( SQLCODE );
}
void main( int argc, char *argv[] )
/*********************************/
/* Optional first argument is a select statement,
 * optional second argument is the fetch width */
{
    char *query_str =
     "select emp_fname, emp_lname from employee";
    unsigned fetch_width = 10;

    if( argc > 1 ) {
        query_str = argv[1];
        if( argc > 2 ) {
          fetch_width = atoi( argv[2] );
          if( fetch_width < 2 ) {
              fetch_width = 2;
          }
        }
    }
    db_init( &sqlca );
    EXEC SQL CONNECT "dba" IDENTIFIED BY "sql";

    DoQuery( query_str, fetch_width );

    EXEC SQL DISCONNECT;
err:
    db_fini( &sqlca );
}
Remarques sur l'utilisation des extractions étendues 

Collection Contents Précédent Suivant PDF