ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 12.04.2021

Просмотров: 1865

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

!

86

!

!

E-mail: market@relex.ru

ЗАО

НПП

 «

РЕЛЭКС

»

http://www.relex.ru

Практическое

занятие

 13

Использование

прекомпилятора

встроенного

 SQL 

Практика

 6 

часов

 (

Лекция

 11)

На

занятии

будут

приведены

примеры

иллюстрирующие

работу

прикладных

программ

с

СУБД

ЛИНТЕР

написанных

на

языке

 C 

с

использованием

встроенного

 SQL. 

Будут

рассмотрены

следующие

вопросы

выполнение

запросов

без

параметров

обработка

ошибок

выполнение

запросов

с

параметрами

получение

данных

из

выборки

обработка

результатов

запроса

с

неизвестным

форматом

ответа

выполнение

хранимых

процедур

13.1. 

Компиляция

примеров

Компиляция

программ

написанных

с

использованием

встроенного

  SQL, 

осуществляется

в

два

этапа

Препроцессор

  pcc 

поставляется

в

дистрибутиве

СУБД

ЛИНТЕР

Результатом

его

работы

является

  c-

файл

который

следует

компилировать

обычным

компилятором

prac13_e1: 

prac13_e1.pc 

$(LINTER)/bin/pcc prac13_e1.pc prac13_e1.c 

$(CC) -c $(CFLAGS) prac13_e1.c 

$(LINKER) prac13_e1.o $(LDKEY)prac13_e1 $(INTLIB) 

rm -f $@.o 

С

примерами

поставляется

 makefile. 

13.2. 

Соединение

выполнение

запросов

без

параметров

обработка

ошибок

Пример

  prac13_e1.pc 

иллюстрирует

работу

с

запросами

без

параметров

Его

алгоритм

таков

создается

соединение

делается

попытка

удаления

таблицы

 PRAC13_T1; 

создается

таблица

 PRAC13_T1; 

вставляются

данные

делается

выборка

количества

записей

в

переменную

делается

выборка

поля

 NAME 

в

переменную

 buf. 

Следует

обратить

внимание

на

то

что

вставка

данных

осуществляется

в

цикле

из

массива

EXEC SQL WHENEVER SQLERROR GOTO not_inserted; 

EXEC SQL FOR :i EXECUTE IMMEDIATE insert into PRAC13_T1 
(id, name) values (:arr_i, 'aaa');


background image

!

!

П

ра
кт

ич

ес

ко

е

за

ня

ти

е

13

Ис

по

ль

зо

ва

ни

е

пр

ек

ом
пи

ля

то

ра

вс

тр

ое

нн

ог

о

S

Q

L

!

87

 
 

E-

mai

l: 

ma

rke

t@

rele

x.r

u

для

этого

переменной

 i 

присваивается

количество

повторений

в

данном

случае

, 10. 

Обработка

ошибок

осуществляется

оператором

  WHENEVER. 

Для

продолжения

работы

используется

режим

  CONTINUE, 

для

перехода

на

метку

  –  GOTO, 

для

вызова

функции

 – CALL 

и

для

завершения

приложения

 – STOP. 

EXEC SQL WHENEVER SQLERROR CONTINUE; 

Выборка

данных

в

переменную

осуществляется

следующим

образом

EXEC SQL WHENEVER SQLERROR GOTO not_selected; 

EXEC SQL SELECT count(*) from PRAC13_T1 into :i; 

При

этом

переменная

 I 

должна

быть

описана

в

разделе

 DECLARE SECTION: 

EXEC SQL BEGIN DECLARE SECTION; 

  short i = 10; 

EXEC SQL END DECLARE SECTION; 

Разрешено

включать

в

запрос

переменные

EXEC SQL EXECUTE IMMEDIATE SELECT NAME into :buf from 
PRAC13_T1 where ID = :tid;

Задача

  1.

Модифицировать

данный

пример

таким

образом

чтобы

при

невозможности

соединения

приложение

завершало

свою

работу

.

Задача

 2.

Модифицировать

данный

пример

добавив

возможность

обновления

поля

NAME 

пользователем

в

строке

по

указанному

 ID.

Задача

  3.

Модифицировать

данный

пример

добавив

полноценный

обработчик

ошибок

анализирующий

переменную

 ErrPCI_. 

13.3. 

Запросы

с

параметрами

Для

выполнения

запроса

с

параметрами

необходимо

использовать

операторы

В

примере

 prac13_e2.pc 

для

вставки

строк

в

таблицу

и

для

построения

выборки

используются

запросы

с

параметрами

создается

соединение

делается

попытка

удаления

таблицы

 PRAC13_T1; 

создается

таблица

 PRAC13_T1; 

создаются

два

оператора

 – 

один

для

вставки

данных

другой

 – 

для

выборки

в

цикле

пользователь

вводит

данные

одной

строки

и

выполняется

оператор

вставки

причем

данные

передаются

как

параметры

выбирается

количество

записей

из

таблицы

пользователю

предлагается

указать

интервал

выводимых

записей

в

цикле

по

данному

интервалу

делается

выборка

одной

записи

чей

номер

принадлежит

интервалу

Подготовка

операторов

происходит

следующим

образом

EXEC SQL PREPARE ST_INS FROM INSERT INTO PRAC13_T1 (id, 
name) VALUES (:tid, :tname); 

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; 

Вставка

данных


background image

!

88

П

ра
кт

ич

ес

ко

е

за

ня

ти

е

13

Ис

по

ль

зо

ва

ни

е

пр

ек

ом
пи

ля

то

ра

вс

тр

ое

нн

ог

о

S

Q

L

!

!

 
 

E-

mai

l: 

ma

rke

t@

rele

x.r

u

  scanf("%d %s", &tid, tname); 

  EXEC SQL EXECUTE ST_INS USING :tid, :tname; 

Выборка

данных

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); 

13.4. 

Получение

структуры

ответа

Получение

структуры

ответа

во

встроенном

  SQL 

осуществляется

при

помощи

дескрипторов

Работа

с

дескрипторами

показана

в

файле

примера

 prac13_e3.pc.  

Алгоритм

работы

примера

таков

создается

соединение

резервируется

память

под

дескриптор

EXEC SQL ALLOCATE DESCRIPTOR :selectOutDesc; 

пользователь

вводит

 SELECT-

запрос

по

запросу

создается

оператор

EXEC SQL PREPARE ST_SEL FROM :szSQL; 

делается

описание

выходных

данных

оператора

в

дескриптор

EXEC SQL DESCRIBE OUTPUT ST_SEL INTO SQL 
DESCRIPTOR :selectOutDesc; 

выводится

тип

и

длина

полей

ответа

привязывается

к

дескриптору

буфер

в

который

следует

помещать

ответ

for (i = 1; i <= colCount; i++) 

  p = &(buf[shift]); 

  EXEC SQL GET DESCRIPTOR :selectOutDesc VALUE :i :length = 
LENGTH; 

  EXEC SQL SET DESCRIPTOR :selectOutDesc VALUE :i DATA 
= :p; 

  shift += align4(length); 

описывается

и

открывается

статический

курсор

EXEC SQL DECLARE CUR_SEL CURSOR FOR ST_SEL; 

EXEC SQL OPEN CUR_SEL; 

осуществляется

проход

по

выборке


background image

!

!

П

ра
кт

ич

ес

ко

е

за

ня

ти

е

13

Ис

по

ль

зо

ва

ни

е

пр

ек

ом
пи

ля

то

ра

вс

тр

ое

нн

ог

о

S

Q

L

!

89

 
 

E-

mai

l: 

ma

rke

t@

rele

x.r

u

for (i = 1; ;i++) 

  memset(buf, 0, sizeof(buf)); 

  EXEC SQL FETCH CUR_SEL ABSOLUTE :i USING 
DESCRIPTOR :selectOutDesc; 

  if (ErrPCI_) 

  { 

    if (ErrPCI_ == 3000) printf("No more records\n");  

    else printf("Error code: %d\n", ErrPCI_); 

    break; 

  } 

  printAnswer(); 

В

примере

присутствует

функция

для

определения

имени

типа

по

его

номеру

возвращенного

дескриптором

  (

нумерация

описана

в

разделе

пользовательской

документации

  «

Встроенный

  SQL»). 

Для

совместимости

со

  Sparc-

платформами

предназначена

функция

 align4, 

вычисляющая

адрес

нацело

делящийся

на

 4.

Задача

  4.

Модифицировать

пример

  prac13_e2.pc, 

изменив

алгоритм

выборки

пользовательский

интервал

учитывается

параметрами

в

операторе

  (WHERE  Rn  >=  :num1 

and Rn <= :num1). 

Движение

по

выборке

осуществлять

при

помощи

оператора

 FETCH.

Задача

  5.

Модифицировать

пример

  prac13_e3.pc, 

добавив

обработку

типов

  byte, 

varbyte, varchar, date, decimal, boolean. 

13.5. 

Вызовы

хранимых

процедур

Встроенный

  SQL 

позволяет

выполнять

хранимые

процедуры

Для

этого

предназначен

оператор

 EXECUTE PROCEDURE. 

Работа

данного

оператора

иллюстрируется

в

примере

  prac13_e4.pc. 

Для

демонстрации

данного

примера

необходимо

создать

тестовую

процедуру

при

помощи

например

утилиты

 inl: 

create procedure STRADD(in ch1 char(10); in ch2 char(10)) 
result int 

code  

  return tointeger(ch1) + tointeger(ch2); 

end  

Алгоритм

работы

примера

таков

создается

соединение

объявляется

процедура

EXEC SQL DECLARE PROCEDURE STRADD(in ch1 char(10); in ch2 
char(10)) result int; 

пользователь

вводит

две

строки

в

которых

находятся

целые

числа


background image

!

90

П

ра
кт

ич

ес

ко

е

за

ня

ти

е

13

Ис

по

ль

зо

ва

ни

е

пр

ек

ом
пи

ля

то

ра

вс

тр

ое

нн

ог

о

S

Q

L

!

!

 
 

E-

mai

l: 

ma

rke

t@

rele

x.r

u

вызывается

процедура

с

этими

параметрами

EXEC SQL EXECUTE PROCEDURE :res = STRADD(:ch1, :ch2); 

выводится

на

экран

возвращенное

значение

Важно

что

типы

фактических

параметров

принимающих

результаты

  (

в

примере

  – 

переменная

  int  res), 

должны

совпадать

с

типами

формальных

параметров

  (

в

примере

  – 

result int – 

результат

процедуры

).

Задача

  6.

На

основе

примера

  prac13_e4.pc, 

написать

программу

проверяющую

наличие

таблицы

представления

или

синонима

по

маске

заданной

пользователем

  (

в

хранимой

процедуре

использовать

запрос

select  *  from  $$$SYSRL  where  $$

$S13 = :s;

).