Внедренный (встроенный) SQL. Добавляет к обычному языку программирования (C в наших примерах) определенные операторы представляющие SQL команды. Каждый внедренный SQL оператор отмечается ключевыми словами EXEC SQL, идущими перед оператором. Препроцессор преобразует C + SQL в чистый C. SQL операторы заменяются вызовами соответствующих процедур. Разделяемые (хост-) переменные. Специальное место для объявления переменных, которые доступны в SQL и C. Описание переменных помещается в специальную секцию между EXEC SQL BEGIN DECLARE SECTION; и EXEC SQL END DECLARE SECTION; В Oracle Pro/C выделение такой секции не обязательно (в С++ - обязательно). C переменные используются как обычно, в SQL командах перед именем переменной должно ставиться двоеточие (:). Пример. Найти цену данного пива в данном баре Sells(bar, beer, price). EXEC SQL BEGIN DECLARE SECTION; char theBar[21], theBeer[21]; float thePrice; int priceInd; EXEC SQL END DECLARE SECTION; ... /* присвоить значения theBar и theBeer */ ... EXEC SQL SELECT price INTO :thePrice FROM Sells WHERE beer = :theBeer AND bar = :theBar; ... Что произойдет, если цена NULL? Используется так называемая индикативная переменная EXEC SQL SELECT price INTO :thePrice :priceInd FROM Sells WHERE beer = :theBeer AND bar = :theBar; if (priceInd = = -1) { … /* обработка ситуации когда price=NULL */ }; ... Курсоры. Подобны PL/SQL курсорам с некоторыми синтаксическими отличиями. Пример. Печать меню бара Joe’s. Sells(bar, beer, price) EXEC SQL BEGIN DECLARE SECTION; char theBeer[21]; float thePrice; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE c CURSOR FOR SELECT beer, price FROM Sells WHERE bar = 'Joe''s Bar'; EXEC SQL OPEN CURSOR c; while(1) { EXEC SQL FETCH c INTO :theBeer, :thePrice; if(NOT FOUND) break; /* format and print beer and price */ } EXEC SQL CLOSE CURSOR c; Oracle в сравнении с SQL. SQL имеет FROM в fetch-утверждении перед именем курсора. SQL определяет массив символов SQLSTATE, получающий определенные значения каждый раз при вызове системы. Здесь присутствуют сигналы об ошибках. Сигнал о том, что курсор не находит более кортежей. Oracle предоставляет заголовочный файл sqlca.h, который определяет коммуникационную область (communication area) и набор макроопределений для доступа к этой области. В частности, NOT FOUND – это макроопределение, сигнализирующее о том, что был получен сигнал «больше-нет-кортежей» Динамический SQL. Мотивировка: Внедренный SQL удобен для устойчивых приложений, например, когда используется клерком для резервирования авиабилета. Однако он не может быть использован для написания программ типа sqlplus, поскольку требуется компилировать код для sqlplus перед тем, как станут известны SQL операторы, набранные в ответ на подсказку SQL> Два специальных оператора внедренного SQL: PREPARE преобразует (компилирует) символьную строку в SQL запрос. EXECUTE выполняет этот запрос. Пример: Набросок программы для Sqlplus EXEC SQL BEGIN DECLARE SECTION; char query[MAX_QUERY_LENGTH]; EXEC SQL END DECLARE SECTION; /* issue SQL> prompt */ /* read user's text into array query */ EXEC SQL PREPARE q FROM :query; EXEC SQL EXECUTE q; /* go back to reissue prompt */ Однажды скомпилированный (приготовленный) запрос может выполняться много раз. Во время компиляции запроса с помощью PREPARE происходит оптимизация запроса – поиск такого способа (плана) исполнения запроса, который бы использовал меньше процессорного времени и дисковых операций ввода/вывода. С другой стороны PREPARE и EXECUTE могут быть объединены в: EXEC SQL EXECUTE IMMEDIATE :query; Интерфейс CLI (Call-Level Interface). Более современным подходом к объединению процедурного языка программирования с SQL является интерфейс CLI, в котором C-программа (или программа на каком-либо другом языке) создает SQL операторы как символьные строки и передает их функциям, являющимся частью стандартной библиотеки. Это похоже на то, что в действительности происходит в приложениях, использующих внедренный SQL. Два основных подхода: SQL/CLI ( ODBC - open database connectivity- стандарт) и JDBC (Java database connectivity). CLI В C вызов библиотечной функции создает дескриптор оператора = структура, в которую можно поместить SQL оператор. Подробнее описано в книге. Вызов SQLPrepare(myHandle, <statement>,...) используется для передачи SQL оператора вторым аргументом и его компиляции. Вызов SQLExecute(myHandle) используется для выполнения скомпилированного оператора. Пример. SQLPrepare(handle1, "SELECT beer, price FROM Sells WHERE bar = 'Joe''s Bar'"); SQLExecute(handle1); Извлечение данных. Для получения доступа к данным, возвращенным исполняемым оператором, необходимо: 1. Связать переменные с номерами компонент возвращаемого кортежа. SQLBindCol использует дескриптор оператора, номер столбца, тип и имя переменной плюс некоторые другие аргументы. 2. Извлечь данные, используя оператор FETCH, в котором используется дескриптор SQL оператора. Пример. SQLBindCol(handle1, 1, SQL_CHAR, &theBar,...) SQLBindCol(handle1, 2, SQL_REAL, &thePrice,...) SQLExecute(handle1); ... while(SQLFetch(handle1) !=SQL_NO_DATA) { ... /* обработка извлеченных данных */ } Авторизация в SQL. Файловые системы задают некоторые привилегии для работы с файлами: r, w, x. При частичной аналогии SQL определяет 9 привилегий доступа для отношений, из которых наиболее важными являются: 1. SELECT = право на выполнение запроса для отношения. 2. INSERT = право вставлять кортежи в отношение - может относиться к отдельному атрибуту, в этом случае привилегия задает только одного столбца вставляемого кортежа 3. DELETE = право удалять кортежи из отношения 4. UPDATE = право обновлять кортежи отношения - может относиться к отдельному атрибуту. Выдача(делегирование) привилегий. Вы имеете все возможные привилегии для отношений, которые вы сами создаете. Вы можете делегировать привилегии любому другому пользователю, если вы имеете саму привилегию и право ее делегирования (привилегию с режимом grant). Вы имеете этот режим для ваших собственных отношений. Пример. 1. Sally может выполнять запросы для Sells и может изменять цены, но не может передать эту привилегию. GRANT SELECT ON Sells, UPDATE(price) ON Sells TO sally; 2. Sally может выборочно делегировать эти привилегии другому: GRANT SELECT ON Sells, UPDATE(price) ON Sells TO sally WITH GRANT OPTION; Лишение привилегий. Привилегия, делегированная вам кем-то другим, может быть отобрана. Синтаксис похож на оператор делегирования, но использует REVOKE ... FROM вместо GRANT ... TO. Определение, имеете ли вы конкретную привилегию, может быть нетривиальной задачей, использующей граф делегирования (подробнее см. книгу). Основными принципами здесь являются: a) если привилегия была делегирована вам несколькими пользователями, то для лишения этой привилегии все эти пользователи должны ее отобрать. b) Отбор привилегии является транзитивным. Если A делегировал P to B , который делегирована P to C , затем А отбирает P у B , то автоматически P будет отобрана у C .