Непосредственное исполнение предложений

Назначение

Исполнение предложения SQL без предварительной подготовки его оператором PREPARE (т.е. без создания переменной типа «предложение»).

Синтаксис

 
< непосредственное выполнение предложения >::=
  EXEC SQL [AT < имя соединения >][FOR :< число выполнений >]
  [ EXECUTE IMMEDIATE] ] < предложение >;
  < число выполнений >::= < переменная основного языка >
  < предложение >::=
  < предложение SQL >
  | < строковый литерал >
  |< переменная основного языка >

Описание

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

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

  3. Конструкция EXECUTE IMMEDIATE является необязательной и может использоваться для совместимости программ, написанных на встроенном SQL СУБД ЛИНТЕР, с программами других СУБД (в частности, Oracle). Кроме того, в случае задания числа повторений необходимо явно указать EXECUTE IMMEDIATE, если текст исполняемого предложения SQL содержится в переменной основного языка.

  4. Параметр < предложение > задает предложение встроенного SQL, которое должно быть выполнено. Если предложение SQL записано непосредственно, оно может содержать именованные параметры. Привязка их будет выполнена на этапе исполнения оператора. Предложением SQL может быть и select-запрос с указанием выходных параметров (INTO < список переменных основного языка >).

  5. Если предложение задано строковым литералом или переменной основного языка, оно не должно содержать параметров, т.к. препроцессору неизвестен его текст.

  6. Перед выполнением предложения входные переменные должны иметь необходимые значения; выходным переменным значение присваивается после успешного выполнения предложения. Если в качестве входной переменной используется массив, то при N-ном выполнении в текст предложения подставляется значение N-го элемента переменного массива.

  7. Если в качестве выходной переменной используется массив, то при N-ном выполнении предложения выбранное значение заносится в N-ный элемент массива.

  8. В одном предложении входные переменные могут одновременно включать скалярные переменные и массивы разной размерности, выходные переменные должны иметь всегда одинаковую структуру – быть либо только скалярными, либо только массивами. При циклическом выполнении предложения для входных скалярных переменных каждый раз подставляется одно и то же значение, для массивов каждый раз подставляется следующий элемент массива.

  9. Для select-предложений возможны 2 варианта выполнения:

    • если все входные переменные – скалярные, а все выходные – массивы, то выполняется последовательная выборка записей с помощью одного и того же предложения в выходные массивы; если же все выходные переменные – скалярные, то предложение выполняется один раз;

    • если хотя бы одна входная переменная – массив, то все выходные переменные должны также быть массивами, и каждый раз выполняется выборка одной записи с помощью нового оператора.

Примеры

  1. Однократное исполнение явно заданного предложения SQL без параметров

    EXEC SQL CREATE TABLE test (name CHAR(10), numb INTEGER);
  2. EXEC SQL BEGIN DECLARE SECTION;
    
      int I;
      int inp_arr1[10];
      int inp_arr2[12];
      int out_arr1[10];
      int out_arr2[12];
      char *query;
    EXEC SQL END DECLARE SECTION;
    
    
    EXEC SQL SELECT I FROM NUMS INTO :i WHERE S='A'; /* выборка в скалярную переменную i. Запрос выполнится один раз */
    …
    i = 10;
    EXEC SQL for :i UPDATE NUMS SET I=:inp_arr1 WHERE S=:inp_arr2; /* запрос выполнится 10 раз, каждый раз используя очередные элементы inp_arr1 и inp_arr2 */
    
    EXEC SQL UPDATE NUMS SET I=:inp_arr1 WHERE S=:inp_arr2; /* запрос вернет ошибку ErrPCI_IncDim */
    
    EXEC SQL SELECT I, s INTO :out_arr1, out_arr2 FROM NUMS WHERE S=:i; /* запрос вернет ошибку ErrPCI_IncDim */
    
    I = 5;
    EXEC SQL SELECT I INTO :out_arr1 FROM NUMS WHERE S=:i; /* запрос выполнится 10 раз используя каждый раз I= 5 */
    
    query = “DROP TABLE NUM;”;
    EXEC SQL :query; /* запрос выполнится, используя текст, содержащийся в query. */
    
    i=5;
    EXEC SQL FOR :I EXECUTE IMMEDIATE :query; /* запрос выполнится один раз, используя текст, содержащийся в query.
    Т.е. параметр FOR в этом случае игнорируется. */
    EXEC SQL “DROP TABLE NUN;”; /* запрос, заданный строковым литералом, выполнится один раз */
  3. #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";
      short i = 10;
      int tid = 0;
      int arr_i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
      char buf[51] = {0};
    EXEC SQL END DECLARE SECTION;
    
    #if defined(VXWORKS)
    MainStart(pcc_sample, 1024*32, UninitLinterClient)
    #else
    int main()
    #endif
    {
       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");
    
       printf("Вставка данных...");
       EXEC SQL WHENEVER SQLERROR GOTO not_inserted;
       EXEC SQL FOR :i EXECUTE IMMEDIATE insert into PRAC13_T1 (id, name) values (:arr_i, 'aaa');
       printf("done.\n");
    
       printf("Выборка count(*)...");
       EXEC SQL WHENEVER SQLERROR GOTO not_selected;
       EXEC SQL SELECT count(*) from PRAC13_T1 into :i;
       printf("В таблице %d записей.\n", i);
    
       printf("\nВведите Id  >");
       scanf("%d", &tid);
       printf("\nId=%d\n", tid);
       EXEC SQL EXECUTE IMMEDIATE SELECT NAME into :buf from PRAC13_T1 where ID = :tid;
       printf("(Id, Name) == (%d, %s).\n", i, buf);
    
       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;
    }