Вызов кода PL/SQL из других языков: Java, Perl, PHP, C

Как запустить скрипт PL/SQL из других языков: Java, Perl, PHP, CРано или поздно вам захочется вызвать код (скрипт) 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 в html странице

Технология 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, как и с реляционными базами данных.

Вас заинтересует / Intresting for you:

Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 6926 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 3071 просмотров Stas Belkov Thu, 16 Jul 2020, 06:20:48
Тип данных RAW в PL/SQL
Тип данных RAW в PL/SQL 5681 просмотров Doctor Thu, 12 Jul 2018, 08:41:33
Символьные функции и аргументы...
Символьные функции и аргументы... 10771 просмотров Анатолий Wed, 23 May 2018, 18:54:01
Войдите чтобы комментировать

ildergun аватар
ildergun ответил в теме #8971 13 март 2018 17:57
Новым для меня была описанная возможность вызова кода PL/SQL из Си. Спасибо.
apv аватар
apv ответил в теме #8889 25 янв 2018 11:35
Прикольный обзор! Особенно ценны примеры вызова блоков PL/SQL из php, java и perl.