Исполнение заранее подготовленных предложений

Назначение

Выполнение подготовленного предложения SQL.

Синтаксис

 
< выполнение подготовленного предложения >::=
EXEC SQL [AT < имя соединения >] [FOR :< число выполнений >]
EXECUTE < предложение >
        < спецификация выходных параметров >
        < спецификация входных параметров >
        < спецификация выходных параметров >::= INTO < список параметров >
        < спецификация входных параметров >::= USING < список параметров >
< список параметров >::=
   < параметры-аргументы > | < параметр-дескриптор >
< параметры-аргументы >::=
   : < переменная основного языка > [ { , : < переменная основного языка > … } ]
< параметр-дескриптор >::=
   SQL DESCRIPTOR < имя дескриптора >

Описание

  1. < Имя соединения > задает соединение, по которому должно выполняться предложение. Соединение должно быть предварительно открыто. Значение параметра может быть задано переменной типа «соединение» либо символьной константой. В любом случае заданное значение должно быть ранее использовано в операторе CONNECT. Если параметр < имя соединения > опущен, предложение выполняется для неименованного канала.

  2. Конструкция FOR задает число повторений предложения. Переменная основного языка, задающая параметр цикла < число выполнений >, должна иметь тип данных short (значение в диапазоне от 1 до 32767). Если переменная другого типа, при претрансляции будет выдана ошибка «Ожидалась целая переменная». Циклическое выполнение предложения предназначено для того случая, когда часть параметров предложения задана массивами. Размеры массивов при этом должны быть не меньше числа повторений, иначе на этапе исполнения будет выдана ошибка ErrPCI_IncDim. Если конструкция FOR не указана, а параметры – переменные-массивы основного языка, то в качестве числа повторений берется размер массива. При этом размеры массивов входных и выходных переменных должны быть одинаковыми, иначе на этапе исполнения фиксируется ошибка ErrPCI_IncDim. Максимальный размер массива – 32767 элементов.

  3. Параметр < предложение > задает переменную типа «предложение» встроенного SQL, которое должно быть выполнено. Переменная, соответствующая параметру < предложение >, должна быть предварительно инициализирована (подготовлена) с помощью оператора PREPARE. Текст предложения может содержать как именованные, так и неименованные формальные параметры. Запрещается задавать имена объектов БД с помощью параметров.

  4. Параметр USING < список параметров > устанавливает соответствие между входными формальными и фактическими параметрами предложения. < Список параметров > должен содержать перечисленные через запятую переменные основного языка (возможно, с их индикаторными переменными). Имя каждой переменной в списке должно предваряться двоеточием. В процессе выполнения предложения каждый формальный параметр получает тип и значение соответствующего ему фактического параметра. Соответствие между формальными и фактическими параметрами является порядковым, т.е. первому формальному параметру соответствует первая переменная в конструкции USING, второму формальному параметру – вторая переменная и т.д. Если в процессе выполнения предложения обнаружится, что список формальных параметров длиннее списка переменных, фиксируется ошибка выполнения; если же список фактических параметров превышает список формальных, то лишние фактические параметры игнорируются. Ошибка выполнения предложения в этом случае не фиксируется. Если текст предложения SQL не содержит неименованных параметров, то конструкцию USING можно не использовать, т.к. переменные основного языка уже привязаны оператором PREPARE.

  5. Параметр INTO < список параметров > устанавливает соответствие между выходными формальными и фактическими параметрами предложения.

  6. Если предложение подготовлено оператором PREPARE, то оно может быть исполнено оператором EXECUTE встроенного языка один и более раз.

  7. Чтобы использовать дескриптор для задания параметров и получения результата, его необходимо определить автоматически с помощью оператора SQL DESCRIBE или вручную с помощью оператора SET DESCRIPTOR.

  8. Дескриптор надо привязать к переменным основного языка (SET DESCRIPTOR).

  9. Если дескриптор задан переменной типа «дескриптор» (DESCRIPTOR) основного языка, то перед любыми действиями его надо инициализировать оператором ALLOCATE DESCRIPTOR.

Примеры

  1. EXEC SQL BEGIN DECLARE SECTION;
    Char *query;
    Int I;
    Char s[32];
    Char Make[10][32];
    EXEC SQL END DECLARE SECTION;
    
    Exec sql prepape ST_0 from SELECT MAKE INTO :make FROM AUTO;
    Exec sql execute ST_0; /* запрос выберет первые 10 записей из таблицы AUTO */
    
    Exec sql execute ST using INTO :s; /* запрос выберет первую запись из таблицы MAKE */
    
    Query = “SELECT I FROM NUM WHERE S=?;”;
    exec sql prepare st from :query; /* предложение задано переменной основного языка и его значение неизвестно во время
    претрансляции */
    
    
    exec sql execute st using :s INTO :i; /* явно задаем входные и выходные параметры при исполнении предложения */
    
  2. #include < stdlib.h >
    #include < stdio.h >
    #include < string.h >
    #if defined(VXWORKS)
    #include "vxstart.h"
    #endif
    
    #ifdef _DOS_
    #include < conio.h >
    #endif
    
    EXEC LINTER IFDEF SQL;
    EXEC SQL INCLUDE SQLCA;
    EXEC LINTER ENDIF;
    
    EXEC SQL BEGIN DECLARE SECTION;
      char *user = "SYSTEM";
      char *pswd = "MANAGER8";
      int i = 0;
      int n1 = 0, n2 = 0;
      int tid = 0;
      int rowCount = 0;
      int arr_i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
      char tname[51] = {0};
    EXEC SQL END DECLARE SECTION;
    
    #if defined(VXWORKS)
    MainStart(pcc_sample, 1024*32, UninitLinterClient)
    #else
    int main()
    #endif
    {
       char c = 0;
       int I = 5;
    
       printf("Создание соединения...");
       EXEC SQL WHENEVER SQLERROR GOTO not_conn;
       EXEC SQL CONNECT AUTOCOMMIT :user IDENTIFIED BY :pswd;
       printf("готово.\n");
    
       printf("Удаление таблицы\n");
       EXEC SQL WHENEVER SQLERROR CONTINUE;
       EXEC SQL EXECUTE IMMEDIATE drop table PRAC13_T1;
    
       printf("Создание таблицы...");
       EXEC SQL WHENEVER SQLERROR GOTO not_created;
       EXEC SQL EXECUTE IMMEDIATE create table PRAC13_T1(id int, name char(50));
       printf("готово.\n");
    
       EXEC SQL WHENEVER SQLERROR GOTO not_st_opened1;
       EXEC SQL PREPARE ST_INS FROM INSERT INTO PRAC13_T1 (id, name) VALUES (:tid, :tname);
       EXEC SQL WHENEVER SQLERROR GOTO not_st_opened2;
       EXEC SQL PREPARE ST_SEL FROM SELECT id, name into :tid, :tname from (SELECT id, name, rownum as rn FROM PRAC13_T1)
       WHERE Rn = :i;
    
       /* вставка данных с использованием оператора*/
       EXEC SQL WHENEVER SQLERROR GOTO not_inserted;
       printf("Insert data...");
       do
       {
         printf("\nВведите значения полей Id и Name через пробел \n");
         scanf("%d %s", &tid, tname);
         EXEC SQL EXECUTE ST_INS USING :tid, :tname;
         printf("Данные вставлены в таблицу. Еще? (Y/N)  > ");
         c = 0;
         while (!isalpha(c))
           scanf("%c", &c);
       }
       while (c == 'Y' || c == 'y');
    
       printf("Выборка count(*)...");
       EXEC SQL WHENEVER SQLERROR GOTO not_selected;
       EXEC SQL SELECT count(*) from PRAC13_T1 into :rowCount;
       printf("В таблице %d записей.\n", rowCount);
    
       printf("Введите через пробел диапазон выводимых записей n1 n2\n");
       scanf("%d %d", &n1, &n2);
       if (n1 <  1) n1 = 1;
       if (n2  > rowCount) n2 = rowCount;
       printf("Содержимое таблицы PRAC13_T1. От %d до %d\n", n1, n2);
       for (i = n1; i < = n2; i++)
       {
         EXEC SQL EXECUTE ST_SEL USING :i into :tid, :tname;
         printf("\t%d.\t%d\t%s\n", i, tid, tname);
       }
    
       return 0;
    
    not_conn:
      printf("Не удалось создать соединение\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    not_inserted:
      printf("Не удалось вставить данные\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    not_created:
      printf("Не удалось создать таблицу\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    not_selected:
      printf("Не удалось создать выборку\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    not_st_opened1:
      printf("Оператор 1 не открыт\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    not_st_opened2:
      printf("Оператор 2 не открыт\n");
      printf("Код ошибки: %d\n", ErrPCI_);
      return 1;
    }