Материал: Graber_Martin_-_SQL_dlya_prostykh_smertnykh_-_2014

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
Они содержат значения, которые нужно вставить в таблицу

Глава 25. Использование SQL с другими языками программирования

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

Использование переменных языка высокого уровня cSQL

Части программы SQL и язык высокого уровня взаимодействуют в основном с помо­

щью значений переменных. Различные языки программирования распознают различ­

ные типы переменных. ANSI определяет эквиваленты SQL для четырех языков программирования - PUI, Pascal, COBOL, FORTRAN (детали представлены в прило­ жении В). Эквиваленты для других языков программирования определяются разработ­ чиками. Типы, подобные DATE, не распознаются ANSI; следовательно, в стандарте нет эквивалентных типов данных для языков высокого уровня. Более сложные типы данных языка высокого уровня, такие как матрицы, тоже не имеют эквивалентов в SQL.

Можно использовать переменные из основной программы во встроенных предло­ жениях SQL везде, где применяются выражения значений (SQL, о котором идет речь в этой главе, - это встроенный SQL, если не оговорено нечто иное). Текущее значение переменной - это то значение, которое будет использоваться в команде. Переменные

языка высокого уровня должны:

•Быть объявлены в SQL DECLARE SECTION (кратко обсуждае-~:ся далее);

•Быть совместимыми по типу данных с их функциями в команде SQL (например, иметь числовой тип, если они должны быть вставлены в числовое поле);

•Иметь значение к тому моменту времени, когда они используются в SQL- команде, независимо от того, что сама SQL-команда может назначать значение;

•Перед ними должно быть указано двоеточие (:)тогда, когда на нее ссылается SQL-команда.

Поскольку переменные языка высокого уровня отличаются от имен столбцов SQL

наличием двоеточия, при желании можно использовать переменные с теми же самыми

именами, что и имена столбцов.

Предположим, в программе есть четыре переменные, с именами id_num,

salesperson, loc, comm.

Salespeople. Можно ввести в программу следующую SQL-команду:

ЕХЕС SOL INSERT INTO Salespeople

VALUES (:id_num, :salesperson, :loc, :comm)

282

Использование 11ере.ме1111ых языка высокого уровня с SQL

Текущие значения этих переменных будут вставлены в таблицу. Переменная comm имеет то же самое имя, что и столбец. Именно это значение будет вставлено, осталь­ ные переменные вставляться не будут. Следует также заметить, что точка с запятой в

конце команды опущена, потому что соответствующее завершение для команды

встроенного SQL различно для разных языков программирования. Для Pascal и PLil - это точка с запятой; для COBOL - слово END-EXEC; для FORTRAN не ис­

пользуется никакого завершающего символа. В других языках программирования этот

символ зависит от конкретной реализации, но мы будем использовать двоеточие для совместимости встроенного SQL с Pascal. Для Pascal встроенные команды SQL и его собственные команды заканчиваются точкой с запятой.

Можно расширить функциональные возможности рассмотренной команды, вста­

вив ее в цикл и повторяя многократно с различными значениями переменных, напри­

мер:

while not end-of-file (input) do

begin

readln (id_num, salesperson, loc,comm);

ЕХЕС SQL INSERT INTO Salespeople

VALUES (:id_num, :salesperson, :loc, :comm);

end;

Этот фрагмент программы Pascal определяет цикл, который будет читать значения из файла, запоминать их в четырех переменных памяти и сохранять значения этих пе­ ременных в таблице Salespeople, после этого читать следующие четыре значения, по­ вторяя процесс до тех пор, пока не будет прочитано содержимое всего файла. Предполагается, что каждое множество значений вводится нажатием клавиши Enter (возврата каретки) (именно так принято в Pascal, функция readln читает входные дан­ ные и переходит к следующей строке). Это дает возможность передать данные из тек­ стового файла в реляционную структуру. Перед занесением данных в реляционную структуру можно предварительно их обработать средствами языка высокого уровня, например, исключить те данные (те сведения о продавцах), для которых комиссион­ ные меньше .12:

while not end-of-file (input) do begin

readln (id_num, salesperson, loc, comm); if comm >= .12 then

ЕХЕС SQL INSERT INTO Salespeople

VALUES (:id_num, :salesperson, :loc, :comm);

end;

Только те строки, которые удовлетворяют условию comm >= .12, вставляются в таблицу. Этот пример показывает, как можно использовать и циклы, и условия в языке высокого уровня в сочетании со средствами встроенного SQL.

283

Глава 25. Использование SQL с другими языками программирования

Объявление переменных

Все переменные, на которые есть ссылки в SQL-предложениях, прежде всего должны быть объявлены в SQL DECLARE SECTION с применением синтаксиса включающего языка. В программе может быть любое количество таких секций, и они могут располагаться в любом месте по тексту программы, но перед использованием

этих переменных все прочие ограничения определяются ограничениями включающе­

го языка. Секции объявлений должны начинаться и заканчиваться командами встроен­

ного SQL BEGIN DECLARE SECTION и END DECLARE SECTION, которым

предшествует, как и прежде, ЕХЕС SQL. Для объявления переменных, которые ис­

пользовались в предыдущем примере, можно ввести следующее:

ЕХЕС SQL BEGIN DECLARE SECTION;

Var

id-num:

integer;

Salesperson:

packed array (1 .. 10) of char;

loc:

packed array ( 1.. 10) of char;

comm:

real;

ЕХЕС SQL END DECLARE

SECTION;

Для тех, кто не знаком с языком программирования Pascal, следует заметить, что Var - это заголовок, который предшествует серии объявлений переменных и упако­ ванных (представленных компактно) (или неупакованных) массивов; VIассив - после­

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

указанным в круглых скобках (например, третий символ в массиве !ос имеет офици­ альное имя lос(З)). Использование точки с запятой после определения каждой пере­ менной - это требование Pascal, а не SQL.

Поиск значений в списке переменных

Кроме ввода значений переменных в таблицу с применением SQL-команд, SQL можно применить для получения значений переменных из таблиц базы данных. Один из способов сделать это - использовать модификации команды SELECT, содержащей предложение INTO. В отличие от предыдущего примера, здесь введены значения строки, описывающей Рее!, из таблицы Salespeople и сохранены в наборе переменных

языка высокого уровня:

ЕХЕС SQL SELECT snum, sname, city, comm

INTO :id_num, :salesperson, :loc, :comm

FROM Salespeople

WHERE snum = 1001;

Выбранные значения размещаются (запоминаются, сохраняются) в перемен­ ных, имена которых указаны в предложении INTO в порядке, установленном в

284

Использование переменных языка высокого уровня с SQL

этом предложении. Переменные, имена которых указаны в предложении lNTO,

должны иметь соответствующие типы для сохранения этих значений; для каждого

выбираемого столбца должна быть предусмотрена переменная соответствующего

типа.

За исключением представленного предложения INTO, этот запрос ничем не отлича­ ется от рассмотренных ранее. Но предложение lNTO накладЬ1вает серьезное ограниче­ ние на запрос: результатом поиска в запросе может быть только одна строка. Если в

результате выполнения запроса получено несколько строк, то значения всех этих строк

не могут одновременно храниться в указанном наборе переменных. Команда признается ошибочной. По этой причине команду SELECT INTO можно выполнять только в том слу­

чае, если выполняются следующие условия:

•Когда предикат применяется для проверки значения, нужно иметь уверенность в том, что это значение уникально, как в рассмотренном примере. Значения, о

которых точно известно, что они уникальны, - это значения, удовлетворяю­

щие ограничению уникальности или уникального индекса (см. главы 17 и 18);

• Когда используются одна или более агрегатных функций, но не применяется

GROUP ВУ;

•Когда для внешнего ключа используется SELECT DISТINCT с предикатом, ссылающимся на единственное значение родительского ключа (при условии, что система поддерживает ссылочную целостность), как в примере:

ЕХЕС SQL SELECT DISTINCT snum

INTD :salesnum

FROM Customers

WHERE snum =

(SELECT snum

FROM Salespeople

WHERE sname = ·мotika');

Впредположении, что Salespeople.snaшe и Salespeople.snшn являются уникальным

ипервичным ключами соответственно для таблицы Salespeople и что Customers.snum является внешним ключом, ссылающимся на Salespeople.snum, есть гарантия того, что

результатом ответа на этот запрос является единственная строка.

Существуют и другие случаи, когда можно быть твердо уверенным в том, что ре­ зультат выполнения запроса - единственная строка выходных данных, но в общем

случае такие ситуации плохо поддаются описанию и часто зависят от конкретных дан­

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

кивать запросы, результатом выполнения которых является одна строка, как того

285

Глава 25. Использование SQL с другими языками программирования

требует SELECT INTO. Можно использовать и запросы, результатом выполнения ко­ торых является множество строк. Для этого следует использовать курсор.

Курсор

Сила SQL заключается и в его способности работать со множеством строк табли­ цы, удовлетворяющих какому-либо критерию, не уточняя заранее, о каком конкретно

количестве строк идет речь. Если десять строк удовлетворяют предикату, то результа­

том выполнения запроса будут эти десять строк. Если предикату удовлетворяют де­ сять миллионов строк, то результатом выполнения запроса будут все десять миллионов строк. Но это трудно себе представить, если имеется в виду взаимодейст­

вие с другими языками программирования. Как можно назначить выходные данные

запроса переменным, если неизвестно даже их количество? Решить эту проблему

можно с помощью курсора.

Курсор - зто мигающая метка текущей позиции на экране дисплея компьютера. Курсор SQL - устройство, аналогичное курсору на экране дисплея, которое помечает

выходные данные запроса, хотя такую аналогию следует признать весьма натянутой. Реально, разработчики SQL ввели понятие "курсор" безотносительно к использова­ нию этого понятия где-либо еще.

Курсор (cursor) - зто переменная, связанная с запросом. Значение этой перемен­ ной - каждая строка, удовлетворяющая запросу. Подобно переменным включающего языка, курсоры должны быть описаны перед их использованием. Это делается с помо­ щью команды DECLARE CURSOR следующим образом:

ЕХЕС SQL DECLARE CURSOR Londonsales FOR

SELECT •

FROM Salespeople

WHERE city = "London·;

Запрос не выполняется немедленно, а является лишь определением. Курсоры по­

добны представлениям в том, что содержат в своем определении запрос, а их содержи­ мое - выходные данные запроса, выполняющегося в момент открытия курсора. Но, в отличие от базовых таблиц или представлений, строки курсора упорядочены, различа­ ют первую, вторую, ... последнюю строки курсора. Этот порядок может либо явно за­ даваться с помощью предложения ORDER ВУ в запросе, либо может быть произвольным, в соответствии с соглашениями, принятыми в конкретной SQL-

системе.

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

открывается с помощью команды:

ЕХЕС SQL OPEN CURSOR Londonsales;

Значения курсора определяются на момент выполнения этой команды, а не на мо­

мент выполнения команды DECLARE или команды FETCH, которая извлекает выход­ ные данные запроса по одной строке на одно выполнение команды FETCH:

286

Источник: https://studfile.net/preview/16418473/