Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Плещёв БД 2013-06-02.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
26.54 Mб
Скачать

5.4.11. Внедрение sql, pl/sql в прикладные программы

Предкомпиляторы Oracle позволяют встраивать блоки PL/SQL в прог­раммы, написанные на любом из следующих языков высокого уров­­­ня: Ada, C, Cobol, Fortran, Pascal, PL/I, SQL*Plus. Такие программы и язы­ки на­зы­ваются соответственно хост-программами (прикладными прог­рам­мами) и хост-язы­ка­ми (базовыми языками). Написав прог­рамму, вы выполняете предкомпиляцию исходного файла. Предкомпиля­тор проверяет программу, а затем гене­ри­рует исходный файл, который можно ком­пи­ли­ро­вать, редактировать и выполнять обычным образом.

Хост-переменные используются для передачи данных из хост-прог­­­­раммы в блок PL/SQL и для передачи данных и информации сос­то­я­ния из блока PL/SQL в хост-программу. Как хост-язык, так и PL/SQL могут устанавливаться и обращаться к значению хост-переменной. Значение входной/выходной хост-пере­мен­ной устанавливается хост-прог­рам­мой/Oracle и используется Oracle/хост-программой. При обра­ще­нии к хост-переменной в блоке PL/SQL перед ее именем ставится двоеточие. Для объвления хост‑переменной в SQL*Plus используется команда:

Variable <имя хост‑переменной> <тип переменной>.

Внедренные операторы SQL, PL/SQL начинаются с префикса EXEC SQL. Рассмотрим операторы, обеспечивающих внедрение.

EXEC SQL BEGIN/END DECLARE SECTION ‑ начало и конец блока объявления хост‑переменных операторами хост‑языка.

EXEC SQL INCLUDE SQLCA ‑ включение области связи SQL, которая со­дер­­жит поля с данными об ошибках и состоянии. Прикладная программа мо­­жет анализировать эти данные после выполнения SQL‑оператора.

EXEC SQL WHENEVER { SQLERROR | SQLWARNING | NOT FOUND} {CONTINUE | GOTO <метка> } ‑ обработка ошибок (SQLERROR), предуп­реж­дений (SQLWARNING) или отсутствия записи (NOT FOUND) после вы­полнения любого оператора SQL, PL/SQL и задание возможных действий: иг­но­ри­рование (CONTINUE) или передача управления на указанную метку.

EXEC SQL CONNECT <пользователь> IDENTIFIED BY <пароль> ‑ под­клю­чение к Oracle c указанием имени пользователя и его пароля.

EXEC SQL COMMIT WORK RELEASE ‑ отключение от Oracle.

EXEC SQL EXECUTE, END-EXEC - начало и конец операторов внед­рен­ного блока PL/SQL. Предкомпилятор рассматривает блок PL/SQL как единое встроенное предложение SQL.

Индикаторная переменная (индикатор) используется совместно с хост‑пе­ре­менной и может принимать значения: 0 (связанная хост‑пе­ре­мен­ная содер­жит допустимое значение), меньше нуля (хост‑переменная условно имеет значение Null) и больше нуля (хост‑переменная содержит допустимое значение, ко­то­рое могло быть округлено или обрезано из‑за маленького размера хост‑переменной). Такие индикаторы решают проб­ле­му зна­че­ния Null для хост‑языков, в которых такое значение отсутствует. Ин­ди­ка­тор указывается во внедренном SQL‑операторе сразу после связан­ной с ним хост‑переменной и отделяемым от нее двоеточием. Для всех столбцов таблицы, которые могут содержать значение Null, при выборке необходимо указать свой индикатор, иначе ‑ СУБД фиксирует ошибку.

Пример использования хост‑переменной с индикатором.

EXEC SQL BEGIN DECLARE SECTION;/* начало объявления хост‑переменных*/

Char adres [51]; short adres_ind; /* хост‑переменная и ее индикатор*/

EXEC SQL END DECLARE SECTION; /* конец объявления хост‑переменных*/

aders_ind=-1; /* связанная хост‑переменная adres условно имеет значение Null*/

EXEC SQL UPDATE sotrudniki SET adres_sotr=:adress :adress_ind WHERE tn=11;

Пример. Программа на Pro*C запрашивает у пользователя имя со­т­руд­ника и передает его встроенному блоку PL/SQL, который использует это имя в запросе по базе данных. Результаты запроса передаются обратно в хост-программу, которая распечатывает их. Хост-переменная empname устанавливается перед тем, как войти в блок PL/SQL, а остальные хост-переменные (jobtype, hired и т.д.) принимают значения внутри блока. Все необходимые преобразования данных между типами данных ORACLE и стандартными типами данных хост-языка выполняются автоматически.

#include <stdio.h> /* подключение модуля ввод/вывода */

EXEC SQL BEGIN DECLARE SECTION;/* начало объявления хост‑переменных*/

VARCHAR empname[11]; VARCHAR jobtype[9]; VARCHAR hired[9];

int salary; int dept; int worked_longer; int higher_sal; int total_in_dept;

VARCHAR uid[20]; VARCHAR pwd[20]; /* имя и пароль пользователя */

EXEC SQL END DECLARE SECTION; /* конец объявления хост‑переменных*/

EXEC SQL INCLUDE SQLCA; /* включение области связи SQL */

main() /* начало тела основной программы */

{ /* формирование имени и пароля пользователя */

strcpy (uid.arr,“Plehev“); uid.len = strlen(uid.arr); strcpy (pwd.arr,“PVV“);

pwd.len = strlen(pwd.arr); printf(“\n\n\tДемонстрация встраивания PL/SQL \n\n“);

printf(“Попытка подключения к Oracle“); /* вывод сообщения */

EXEC SQL WHENEVER SQLERROR GOTO errprint; /* обработчик исключений*/

EXEC SQL CONNECT :uid IDENTIFIED BY :pwd; /* подключение к Oracle*/

printf(“ Подключены к Oracle\n“); /* вывод сообщения */

for (;;) /* цикл обработки данных сотрудника */

{ printf(“\n** Имя сотрудника? (для выхода нажмите клавишу Enter)“);

gets(empname.arr); /* ввод имени сотрудника */

if (strlen(empname.arr) == 0) /* имя не введено */

{ EXEC SQL COMMIT WORK RELEASE; /* отключение от Oracle */

exit(0); /* выход из основной программы */

}

empname.len = strlen(empname.arr); jobtype.len = 9; hired.len = 9;

EXEC SQL EXECUTE /* начало PL/SQL‑блока */

BEGIN

/* специальность, стаж, оклад и подразделение сотрудника */

SELECT job,hiredate,sal,deptno INTO :jobtype, :hired, :salary, :dept

FROM emp WHERE ename = UPPER(:empname);

/* число сотрудников со стажем работы меньше, чем у сотрудника */

SELECT COUNT(*) INTO :worked_longer FROM emp WHERE hiredate< :hired;

/* число сотрудников с окладом больше, чем y сотрудника*/

SELECT COUNT(*) INTO :higher_sal FROM emp WHERE sal > :salary;

/* число сотрудников в подразделении, в котором он работает */

SELECT COUNT(*) INTO :total_in_dept FROM emp WHERE deptno = :dept;

END;

END-EXEC; /* конец PL/SQL‑блока */

jobtype.arr[jobtype.len] = '\0'; hired.arr[hired.len] = '\0'; /* вставка конца строки */

/* вывод полученной информации */

printf(“\n%s специальность: %s Стаж: %s\n“,empname.arr,jobtype.arr,hired.arr);

printf(“ %d число сотрудников с меньшим стажем\n“, worked_longer);

printf(“Оклад: %d\n“, salary);

printf(“%d число сотрудников с большим окладом\n“, higher_sal);

printf(“Подразделение: %d\n “, dept);

printf(“ %d Число сотрудников в подразделении\n“, total_in_dept);

} /* конец цикла обработки данных сотрудника */

errprint: /* метка начала обработки исключений */

EXEC SQL WHENEVER SQLERROR CONTINUE; /* игнорирование ошибок */

printf(“\n\nОшибки при выполнении программы:\n“); /* вывод сообщения */

printf(“%s\n“, sqlca.sqlerrm.sqlerrmc); /* вывод текста сообщения об ошибке */

EXEC SQL ROLLBACK RELEASE; /* отмена транзакции */

exit(1); /* выход из основной программы с кодом 1 */

} /* конец тела основной программы */