Программирование >>  Sql: полное руководство 

1 ... 152 153 154 [ 155 ] 156 157 158 ... 264


/* Получить имена столбцов таблицы из системного каталога ♦/ exec sql open tblcurs; for (,-,-){

/* Получить имя следующего столбца и спросить пользователя, включить ли этот столбец в запрос */ exec sql fetch tblcurs into ;querycol; printf( Включить столбец %s (у/п)? , querycol); gets(inbuf); if (inbuf[0] == y) {

/* Пользователь выбрал столбец; добавить его имя в список возвращаемых столбцов */ if (colcount++ > 0)

strcat(stmtbuf, , ); strcat (stmtbuf, querycol);.--- ©

no more columns;

exec sql close tblcurs;

/* Закончить инструкцию SELECT предложением FROM */ strcat(stmtbuf, from ); strcat(stmtbuf, querytbl);

/* Выделить область SQLDA для динамического запроса */

qry da = (SQL *) malloc(sizeof(SQLDA) + colrount * sizeof(SQLVAR));

qry da -> sqln = colcount;

/* Подготовить запрос и попросить СУБД описать его */

exec sql prepare querystmt from : stmtbuf;.-®

exec sql describe querystmt into qry da;.-@

/* Просмотреть все структуры SQLVAR и выделить память под каждый столбец */ for (1 = 0; 1 < colcount; i++) { qry var = qry da -> sqlvar + i;

qry var -> sqldata = malloc (qry var -> sqllen) ;.4-©

qry var -> sqlind = malloc(sizeof(short));

/* Область SQLDA сформирована; выполнить запрос и получить его результаты */

exec sql open qrycurs;.---- ©

exec sql whenever not found goto no more data; for ( ; ; ) (

/* Прочитать строку данных и поместить ее в буферы */

exec sql fetch sqlcurs using descriptor qry da;----0

printf( \n ) ;

/* Цикл, выводящий данные для каждого столбца строки */ for (1 =0; 1 < colcount; i++) (

/* Найти структуру SQLVAR для данного столбца */ qry var = qry da -> sqlvar + i;

printf( Столбец f %d (%s): , i+l, qry var -> sqlname);

/* Проверить переменную-индикатор на равенство NULL */ If (*(qry var -> sqlind) =0) (

puts( равен NULLXn ); I

continue;

/* Возвращены фактические данные; данные каждого типа

Рис. 18.9. ыборкаанныхс помощью тнамического SQL



обрабатываются отдельно */ switch (qry var -> sqltype) {

case 448: case 449:

/* Тип данных VARCHAR - просто отобразить */

puts{qry var -> sqldata) ;

break;

case 496: case 497:

/* 4-байтовое целое число - преобразовать и отобразить */

prmtf { %ld , *((int *) (qry var -> sqldata)));

break;

case 500: case 501:

/* 2-байтовое целое число - преобразовать и отобразить */

prmtf ( %d , *( (short *) (qry var -> sqldata)));

break;

case 480: case 481:

/* Данные с плавающей запятой - преобразовать и отобразить */

prmtf ( %lf , *( (double *) {qry var -> sqldata)));

break;

no more data:

printf( ЧпКонец данных.\n );

/* Очистить память */

for (i 0; 1 < colcount; i++) qry var = qry da -> sqlvar -free(qry var -> sqldata); free (qry var -> sqlmd) ;

free(qry da);

close qrycurs; -

exit(0);

P c. 18.9. Выборка данных 2 помощью яинамичвасою SQL

Вначале программа, представленная на рис. 18.9, запрашивает у пользователя имя таблицы, а затем обращается к системному каталогу, чтобы узнать имена столбцов этой таблицы. Она просит пользователя выбрать столбцы, которые будут извлекаться, и на основе его ответов формирует динамическую инструкцию select. Последовательное, шаг за шагом, формирование списка выбираемых столбцов характерно для клиентских программ, использующих динамический SQL. В реаяьных приложениях этот список может включать выражения или статистические функции, поэтому в профамме может присутствовать дополнительный код, формирующий предложения GROUP BY, HAVING или ORDER BY. Заметьте, что создаваемая инструкция select идентична инструкции select, которая применялась бы для выполнения данного запроса в интерактивном режиме.



Обработка инструкций prepare и describe, выполняемая в этой программе, а также способ выделения памяти под извлекаемые данные являются характерными для профамм формирования динамических запросов Обратите внимание на то, как профамма использует описания столбцов, помещенные в массив сфуктур sqlvar чтобы выделить для каждого столбца блок памяти соответствующего размера. Дл каждого столбца профамма выделяет в памяти также и место для переменной-индикатора Адрес блока памяти для содержимого столбца и адрес переменной-индикатора профамма помещает обратно в сфуктуру sqlvar.

Как видно из данной профаммы, инсфукции open, fetch и close ифают в динамических запросах ту же роль, что и в статических Обратите внимание в инструкции fetch вместо списка базовых переменных задана область sqlda Так как профамма предварительно заполнила поля sqldata и sqlind в массиве sqlvar, СУБД знает , куда помещать каждый извлекаемый столбец данных.

Из этого примера следует, что профаммирование динамического запроса связано большей частью с созданием области sqlda и выделением памяти для нее и извлекаемых данных. Кроме того, в профамме необходимо отслеживать различные типы данных, которые могут быть возвращены запросом, и правильно их обрабатывать, учитывая возможность возвращения значений null. Эти характеристики профаммы, изображенной на рис 18.9, типичны для промышленных приложений, использующих динамические запросы. Несмофя на кажущуюся сложность, профаммировать динамические запросы на языках С, С++, Pascal, PL/1 или Java не очень фудно Исполюовать для профаммирования динамических запросов такие языки, как COBOL и FORTRAN, нельзя, т.к. в них отсутствует возможность динамического распределения памяти и использования сфуктур переменной длины.

В последующих парафафах рассмафиваются инсфукция describe и динамические версии ИНСфукЦИЙ declare cursor, open, fetch и close.

Инструкция DESCRIBE

Инструкция describe, синтаксическая диафамма которой изображена на рис. 18.10, применяется только в динамических запросах и служит для получения из СУБД описания динамического запроса Эта инсфукция вьшолняется после компиляции запроса инсфукцией prepare, но до его выполнения инсфукцией open Запрос, который должен быть описан, идентифицируется по имени инсфукции СУБД возвращает описание запроса в область sqlda, указанную профаммой.

DESCRIBE имя инструкции INTO имя дескриптора--

------ .

Рис. 18.10. Оттоксичерсая диаграмма шсгрути DESCRIBE

Как уже говорилось в настоящей главе и было показано на рис. 18.7, область sqlda - это Сфуктура переменной длины, содержащая массив, который состоит из одной или нескольких сфуктур sqlvar. Прежде чем использовать область sqlda в инструкции describe, профамма должна заполнить поле sqln в ее заголовке, информирующее СУБД о размере массива sqlvar в этой конкретной области. В качестве первого эгапа обработки инструкции describe СУБД заполняет поле sqld в заголовке области sqlda значением, соответствующим числу столбцов таблицы результатов запроса. Если размер массива sqlvar (указанный в поле sqln) слишком мал, чтобы вместить все описания столбцов, СУБД не заполняет оставшуюся часть



1 ... 152 153 154 [ 155 ] 156 157 158 ... 264

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика