Рано или поздно вам захочется вызвать код (скрипт) PL/SQL из кода C, Java, Perl, PHP или другого языка. Потребность вполне естественная, но если вам когда-нибудь приходилось создавать приложения с межъязыковыми вызовами, то вы наверняка сталкивались с различными нюансами преобразования типов данных разных языков (в первую очередь составных типов — массивов, записей, объектов и т. д.), не говоря уже о различиях в семантике параметров или специфичных для конкретного производителя расширений «стандартных» API, в частности Microsoft ODBC.
Рассмотрим несколько примеров использования PL/SQL во внешнем коде. Допустим, у нас имеется функция PL/SQL, которая получает код ISBN в строковом формате и возвращает заголовок соответствующей ему книги:
/* Файл в Сети: booktitle.fun */ FUNCTION booktitle (isbn_in IN VARCHAR2) RETURN VARCHAR2 IS l_title books.title%TYPE; CURSOR icur IS SELECT title FROM books WHERE isbn = isbn_in; BEGIN OPEN icur; FETCH icur INTO l_title; CLOSE icur; RETURN l_title; END;
В SQL*Plus существует несколько способов вызова этой функции. Простейший способ:
SQL> EXEC DBMS_OUTPUT.PUT_LINE(booktitle('0-596-00180-0')) Learning Oracle PL/SQL PL/SQL procedure successfully completed.
Давайте посмотрим, как вызвать эту функцию в следующих средах:
- C, с использованием прекомпилятора Oracle (Pro*C);
- Java, с использованием JDBC;
- Perl, с использованием интерфейсного модуля Perl DBI и драйвера DBD::Oracle;
- PHP;
- PL/SQL Server Pages.
Учтите, что примеры написаны исключительно в учебных целях — например, имя пользователя и пароль в них жестко закодированы, и программы просто направляют результат в стандартный выходной поток. Более того, я даже не стану подробно описывать каждую строку кода. Тем не менее эти примеры дают некоторое представление о том, какие схемы вызова PL/SQL могут использоваться в разных языках.
C, с использованием прекомпилятора Oracle (Pro*C)
Oracle предоставляет как минимум два разных внешних интерфейса для языка C: один называется OCI (Oracle Call Interface) и ориентируется в основном на программистов экстра-класса, а другой — Pro*C. В состав OCI входит множество функций для выполнения таких низкоуровневых операций, как открытие и разбор данных, привязка, выполнение, выборка... и все это для реализации лишь одного запроса! Поскольку простейшая программа на базе OCI, выполняющая не самую сложную задачу, содержит около 200 строк кода, мы рассмотрим пример использования Pro*C. Pro*C базируется на технологии прекомпиляции, позволяющей совмещать в исходном коде операторы языков C, SQL и PL/SQL. Такие файлы обрабатываются программой Oracle proc, которая преобразует их в код на языке C:
/* Файл в Сети: callbooktitle.pc */ #include #include EXEC SQL BEGIN DECLARE SECTION; VARCHAR uid[20]; VARCHAR pwd[20]; VARCHAR isbn[15]; VARCHAR btitle[400]; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA.H; int sqlerror(); int main() { /* Значения VARCHAR преобразуются в структуры из символьного массива и текущей длины */ strcpy((char *)uid.arr,"scott"); uid.len = (short) strlen((char *)uid.arr); strcpy((char *)pwd.arr,"tiger"); pwd.len = (short) strlen((char *)pwd.arr); /* Гибрид исключения и оператора goto */ EXEC SQL WHENEVER SQLERROR DO sqlerror(); /* Подключение к серверу Oracle с выполнением функции booktitle */ EXEC SQL CONNECT :uid IDENTIFIED BY :pwd; EXEC SQL EXECUTE BEGIN :btitle := booktitle('0-596-00180-0'); END; END-EXEC; /* Вывод результата */ printf("%s\n", btitle.arr); /* Отключение от сервера ORACLE. */ EXEC SQL COMMIT WORK RELEASE; exit(0); } sqlerror() { EXEC SQL WHENEVER SQLERROR CONTINUE; printf("\n% .70s \n", sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); }
Как видите, Pro*C вряд ли приведет в восторг блюстителей чистоты языка C. Однако во многих компаниях считают, что Pro*C (или Pro*Cobol, или прекомпиляторы для других поддерживаемых Oracle языков программирования) может служить разумной альтернативой Visual Basic (слишком медленный и неуклюжий) и OCI (слишком сложный).
Лучшим источником информации о Pro*C является документация Oracle.
Java, с использованием JDBC
Как и в случае с C, Oracle поддерживает несколько разных методов подключения к базе данных из кода Java. Один из них — встроенный синтаксис SQL, называемый SQLJ — близок к другим прекомпиляторным технологиям Oracle, хотя и более удобен для отладки. Большей популярностью пользуется метод доступа к базе данных, называемый JDBC (на самом деле это название ничего не означает, хотя его часто расшифровывают как «Java Database Connectivity»):
/* Файл в Сети: Book.java */ import java.sql.*; public class Book { public static void main(String[] args) throws SQLException { // Инициализация драйвера с попыткой подключения к базе данных DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:o92", "scott", "tiger"); // Метод prepareCall использует "call"-синтаксис ANSI92 CallableStatement cstmt = conn.prepareCall("{? = call booktitle(?)}"); // Связывание переменных и параметров cstmt.registerOutParameter(1, Types.VARCHAR); cstmt.setString(2, "0-596-00180-0"); // Теперь можно выполнить запрос и получить результат, // закрыть подключение и вывести результат. cstmt.executeUpdate(); String bookTitle = cstmt.getString(1); conn.close(); System.out.println(bookTitle); } }
В этом примере используется «тонкий» драйвер, отличающийся прекрасной совместимостью и простотой установки (все необходимое для сетевых протоколов имеется в библиотеке Java) — но за счет производительности передачи данных. В качестве альтернативы можно использовать так называемый драйвер OCI. Пусть вас не пугает название — он совсем не так сложен, как одноименный интерфейс, упоминавшийся в предыдущем разделе.
Perl, с использованием Perl DBI и DBD::Oracle
Столь популярный в сообществе системных администраторов язык Perl можно назвать прародителем всех языков с открытым исходным кодом. Сейчас, в версии 5.10, он может практически все и распространен, кажется, повсеместно. А благодаря таким удобным средствам, как CPAN (Comprehensive Perl Archive Network — обширный сетевой архив ресурсов для языка Perl), ничего не стоит установить интерфейсные модули типа DBI (DataBase Interface) и соответствующий драйвер Oracle, DBD::Oracle.
/* Файл в Сети: callbooktitle.pl */ #!/usr/bin/perl use strict; use DBI qw(:sql_types); # Установить подключение или аварийно завершить приложение my $dbh = DBI->connect( 'dbi:Oracle:o92', 'scott', 'tiger', { RaiseError => 1, AutoCommit => 0 } ) || die "Соединение с базой данных не установлено: $DBI::errstr"; my $retval; # Вызов Oracle для разбора инструкции eval { my $func = $dbh->prepare(q{ BEGIN :retval := booktitle(isbn_in => :bind1); END; }); # Связывание параметров и выполнение процедуры $func->bind_param(":bind1", "0-596-00180-0"); $func->bind_param_inout(":retval", \$retval, SQL_VARCHAR); $func->execute; }; if( $@ ) { warn "Хранимая процедура выполнена с ошибкой: $DBI::errstr\n"; $dbh->rollback; } else { print "Хранимая процедура вернула значение: $retval\n"; } # Не забыть отключиться $dbh->disconnect;
С другой стороны, код Perl часто оказывается совершенно неудобочитаемым. К тому же этот язык не отличается ни быстротой, ни компактностью кода, хотя компилируемые версии по крайней мере решают проблему быстродействия.
За дополнительной информацией о взаимодействии между Perl и Oracle обращайтесь к книге Programming the Perl DBI (автор Alligator Descartes и Tim Bunce). О языке Perl написано немало превосходных книг, не говоря уже о сетевых ресурсах perl.com (сайт O’Reilly), perl.org и cpan.org.
PHP, с использованием расширений Oracle
Многие разработчики, использующие бесплатный и невероятно популярный веб-сервер Apache, также являются завзятыми сторонниками бесплатного и невероятно популярного языка программирования PHP. Язык PHP, часто применяемый для построения динамических веб-страниц, также может использоваться для построения графических приложений или выполнения программ командной строки. Как и следовало ожидать, Oracle поддерживается в PHP наряду со многими другими базами данных. Более того, компания Oracle объединила усилия с Zend для включения «официально одобренной» поддержки Oracle в PHP1.
В следующем примере используется семейство функций PHP, объединенных общим названием OCI8. Пусть цифра «8» в названии вас не смущает; функции должны работать со всеми версиями Oracle, от Oracle7 до 11g.
/* Файл в Сети: callbooktitle.php */
<?PHP
// Создание подключения к базе данных o92
$conn = OCILogon ("scott", "tiger", "o92");
// Вызов Oracle для разбора инструкции
$stmt = OCIParse($conn,
"begin :res := booktitle('0-596-00180-0'); end;");
// Вывод информации об ошибках
if (!$stmt) {
$err = OCIError();
echo "Oops, you broke it: ".$err["message"];
exit;
}
// Привязка 200 символов переменной $result к заполнителю :res
OCIBindByName($stmt, "res", &$result, 200);
// Выполнение
OCIExecute($stmt);
// Сохранение значения в переменной
OCIResult($stmt,$result);
// Вывод в стандартный поток
echo "$result\n";
// Отключение от базы данных
OCILogoff($conn);
?>
При выполнении в командной строке результат выглядит примерно так:
$ php callbooktitle.php Learning Oracle PL/SQL
Кстати говоря, функции Oracle OCI недоступны в PHP по умолчанию. Тем не менее ваш системный администратор без труда построит PHP с расширениями Oracle.
За дополнительной информацией обращайтесь по адресу http://www.php.net или к многочисленным книгам издательства O’Reilly по этой теме. Рекомендации по работе с Oracle из PHP приведены на сайте Oracle Technology Network.
PL/SQL Server Pages
Хотя технология PL/SQL Server Pages (PSP) запатентована Oracle, я решил упомянуть о ней, потому что она позволяет быстро создать работоспособную веб-страницу. Она так-же основана на прекомпиляции и позволяет вставлять код PL/SQL в HTML-страницы.
Конструкция <%= %> означает: «обработать как фрагмент PL/SQL и включить результат в страницу».
/* Файл в Сети: favorite_plsql_book.psp */
<%@ page language="PL/SQL" %>
<%@ plsql procedure="favorite_plsql_book" %>
<HTML>
<HEAD>
<TITLE>My favorite book about PL/SQL</TITLE>
</HEAD>
<BODY>
<%= booktitle( '0-596-00180-0') %>
</BODY>
</HTML>
Если приведенная страница будет правильно установлена на веб-сервере, подключенном к базе данных Oracle, то страница будет выглядеть так, как показано на рис. 1.
Технология PL/SQL Server Pages пришлась по душе многим программистам и пользователям, так как она позволяет быстро и удобно создавать сайты.
За дополнительной информацией обращайтесь к книге Learning Oracle PL/SQL, написанной теми же авторами, что и книга, которую вы сейчас читаете.
Что же дальше?
Итак, вы познакомились ранее с примерами использования PL/SQL в SQL*Plus и в других распространенных средах и языках программирования. Кроме того, код PL/SQL можно:
- встраивать в программы на языках COBOL и FORTRAN с последующей обработкой прекомпилятором Oracle;
- вызывать из языка Visual Basic с помощью разновидности ODBC;
- вызывать из языка программирования Ada с помощью технологии, называемой SQL*Module;
- выполнять автоматически по триггерам событий, происходящих в базе данных Oracle (например, при обновлении таблицы);
- включать в расписание для выполнения в базе данных Oracle с использованием встроенного пакета DBMS_SCHEDULER;
- использовать для манипуляций с содержимым TimesTen — технологии работы с базой данных в памяти, приобретенной Oracle Corporation. С ее содержимым можно работать из кода PL/SQL, как и с реляционными базами данных.