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

1 ... 140 141 142 [ 143 ] 144 145 146 ... 264


в стандарте SQLl описано предупреждение not found, но в нем не определено соответствующее ему конкретное возвращаемое значение. В DB2 используется значение + 100, и большинство других СУБД также придерживаются этого значения, включая остальные СУБД компании IBM, а также Ingres и SQLBase. Это значение определено и в стандарте SQL2, но, как уже отмечалось ранее, стандарт SQL2 настоятельно рекомендует применять новую переменную sqlstate вместо устаревшей sqlcode.

Выборка значений NULL

Если записи, которые должны быть извлечены из базы данных, могут содержать значения null, то одиночная инструкция select должна обеспечить передачу значений null из СУБД в прикладную программу. Для этого в предложении into используются переменные-индикаторы, точно так же как они использовались в

предложении values инструкции insert и в предложении set инструкции update.

Если в предложении into имеется базовая переменная, то сразу же за нею должно следовать имя сопутствующей переменной-индикатора. На рис 17.21 изображена измененная программа, представленная ранее на рис. 17.20. В этом варианте программы используется базовая переменная repquota и переменная-индикатор гер-quota ind. Так как в определении таблицы salesreps столбцы name и sales объявлены как not null, они не могут содержать значений null, и поэтому переменные-индикаторы для этих столбцов не требуются.

main ()

exec sql include sqlca;

exec sql begin declare section;

int repnum; /* идентификатор служащего (вводит пользователь) */

char repname[16]; /* полученное имя служащего */

float repquota; /* полученный план */

float repsales; /* полученный объем продаж */

short repquota ind; /* индикатор нулевого плана */ exec sql end declare section;

/* Запросить у пользователя идентификатор служащего */ printf( Введите идентификатор служащего: ); scanf( %d , Srepnum);

/* Выполнить SQL-запрос */

exec sql select name, quota, sales

from salesreps where empl num = : repnum

into :repname, :repquota :repquota ind, :repsales;

/* Отобразить полученные данные */ If (sqlca.sqlcode == 0) {

printf( Имя: %s\n , repname);

if (repquota ind < 0)

printf( План не назначен.\n );

else

printf( План: %f\n , repquota); printf( Объем продаж: %f\n , repsales);

else If (sqlca.code == 100)

printf( Неправильный идентификатор служащего.\n );

else

printf( Ошибка SQL: %ld\n , sqlca.sqlcode); exit(0);

Рис 17.21. Одиночная инсгрукщы SELECT с переменными-индикаторами



Содержимое переменной-индикатора после выполнения инструкции select информирует программу о том, как интерпретировать возвращаемые данные:

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

Отрицательное значение индикатора означает, что извлеченное значение - это null. Содержимое базовой переменной не соответствует извлеченному значению и не должно использоваться прикладной программой.

Положительное значение индикатора означает какое-либо предупреждение, например об округлении чисел или усечении строк.

Так как заранее неизвестно, когда будет извлечено значение null, для каждого столбца результатов запроса, который может содержать значение null, в предложении into должна быть задана переменная-индикатор. Если инструкция select извлекает столбец со значением null, а переменная-индикатор для данного столбца в инструкции отсутствует, то СУБД трактует это как ощибку и возвращает отрицательную переменную sqlcode. Таким образом, для успещного извлечения строк со значениями null обязательно должны применяться переменные-индикаторы.

Хотя основным применением переменньцс-индикаторов является обработка значений null, переменные-индикаторы используются в СУБД также и для сигнализации о ненормальных ситуациях. Например, если в результате арифметического переполнения или деления на ноль содержимое какого-нибудь столбца результатов запроса становипгся недействительным, DB2 возвращает в переменную sqlcode значение +802, означающее предупреждение, и устанавливает значение переменной-индикатора равным -2. В ответ на это прикладная программа просматривает переменные-индикаторы, чтобы определить, какой столбец содержит недействительные данные.

С помощью переменных-индикаторов СУБД сигнализирует также об усечении символьньцс данньцс. Если какой-нибудь столбец результатов запроса содержит слишком длиннью строки и они не умещаются в соответствующей базовой переменной, DB2 копирует в базовую переменную первую часть строки символов и заносит в соответствующую переменную-индикатор полную длину строки. Прикладная программа может просмотреть переменную-ивдикатор и при необходимости повторить инструкцию select с другой базовой переменной, вмещающей более длинную строку.

Такое дополнительное использование переменных-индикаторов является обычным делом в коммерческих СУБД, однако конкретные коды предупреждений в разных СУБД различны. Они не устанавливаются стандартом ANSI/ISO. Вместо этого стандарт SQL2 определяет классы и подклассы ошибок, а прикладная программа должна выполнять инструкцию get diagnostics, чтобы получить детальную информацию о базовой переменной, породившей ошибку.

Выборка данных с использованием структур

В некоторых языках программирования существуют структуры данных, которые представляют собой именованные коллекции переменных. Для этих языков в предложении into можно указывать всю структуру как одну составную базовую переменную. Вместо того чтобы задавать отдельную базовую переменную для каждого столбца результатов запроса, можно задать структуру, в которую будет помещена вся запись целиком. На рис. 17.22 изображена программа, представленная на рис. 17.21, Но измененная так, чтобы в ней использовалась базовая переменная типа struct языка С.



main О

exec sql include sqlca;

exec sql begin declare section;

int repnum; /* идентификатор служащего (вводит пользователь) */

struct (

char name [16]; /* полученное имя служащего */ float quota; /* полученный план */ float sales; /* полученный объем продаж */ Irepinfo;

short rep ind[3]; /* массив индикаторов */ exec sql end declare section;

/* Запросить у пользователя идентификатор служащего */ printf( Введите идентификатор служащего: ); scanf( %d , Srepnum);

/* Выполнить SQL-запрос */

exec sql select name, quota, sales

from salesreps where empl num = :repnum

into :repinfo :rep ind,

/* Отобразить полученные данные */ if (sqlca.sqlcode ==0) (

printf( Имя: %s\n , repinfo.name);

If (rep ind[l] < 0)

printf( План не назначен.\n );

else

printf( План: %f\n , repinfо.quota); printf( Объем продаж: %f\n , repinfо.sales);

else if (sqlca.sqlcode == 100)

printf( Неправильный идентификатор служащего \n ); else

printf( Ошибка SQL: %ld\r , sqlca.sqlcode); exit(O);

Когда препроцессор встречает в предложении into ссылку на структуру, он заменяет ссылку списком переменных, входящих в структуру; переменные в списке располагаются в том порядке, в каком они объявлялись в этой структуре. Таким образом, число элементов структуры и их типы данных должны соответствовать столбцам результатов запроса. Структура данных в предложении into фактически является лищь компактным контейнером базовых переменных и никаких фундаментальных изменений в это предложение не вносит.

Поддержка структур в качестве базовых переменных по-разному реализуется в различных СУБД. Кроме того, структуры можно применять не во всех языках программирования. Например, DB2 поддерживает структуры в языках С и PL/I и не поддерживает в языке ассемблера и в COBOL.

Входные и выходные базовые переменные

Базовые переменные обеспечивают двустороннюю связь между программой и СУБД-В программе, представленной на рис. 17.21, две базовые переменные, repnum и repname, иллюстрируют две различные роли, которые могут играть базовые переменные: Переменная repnum - это входная базовая переменная, используемая для передачи

данньцс из программы в СУБД. Программа присваивает переменной значение переД



1 ... 140 141 142 [ 143 ] 144 145 146 ... 264

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