<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://camokathomelab.servebeer.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=SQLJ</id>
	<title>SQLJ - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://camokathomelab.servebeer.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=SQLJ"/>
	<link rel="alternate" type="text/html" href="https://camokathomelab.servebeer.com/mediawiki/index.php?title=SQLJ&amp;action=history"/>
	<updated>2026-07-16T12:48:44Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://camokathomelab.servebeer.com/mediawiki/index.php?title=SQLJ&amp;diff=44418&amp;oldid=prev</id>
		<title>imported&gt;Alex NB OT: замена имён и значений устаревшего неподдерживаемого InternetArchiveBot формата параметров доступности ссылок (4), замена устаревших имён параметров (12)</title>
		<link rel="alternate" type="text/html" href="https://camokathomelab.servebeer.com/mediawiki/index.php?title=SQLJ&amp;diff=44418&amp;oldid=prev"/>
		<updated>2025-07-16T10:13:55Z</updated>

		<summary type="html">&lt;p&gt;замена имён и значений устаревшего неподдерживаемого InternetArchiveBot формата параметров доступности ссылок (4), замена устаревших имён параметров (12)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;SQLJ&amp;#039;&amp;#039;&amp;#039; — подмножество [[стандарт]]а [[SQL]], направленное на объединение преимуществ синтаксиса языков SQL и [[Java]] ради удобства реализации бизнес-логики и работы с данными. Данный стандарт разработан консорциумом, состоящим из компаний [[IBM]], [[Micro Focus]], [[Microsoft]], [[Compaq]] (точнее, его подразделение, занимающееся СУБД, которое, скорее, можно отнести к приобретенной компании [[Tandem]]), [[Informix]], [[Oracle Corporation|Oracle]], [[Sun Microsystems|Sun]] и [[Sybase]].&lt;br /&gt;
&lt;br /&gt;
== Предыстория ==&lt;br /&gt;
На момент появления консорциума JSQL (впоследствии ставшего одноимённым с разрабатываемым им стандартом) в [[1997 год]]у идея о взаимодействии реляционных [[СУБД]] и программ на Java была не нова. Компанией [[JavaSoft]] (дочерним подразделением компании Sun) уже был разработан интерфейс [[JDBC]] ({{lang-en|Java DataBase Connectivity}} — «соединение с БД средствами Java»), включённый в стандарт языка, начиная с момента выпуска [[Java Development Kit|JDK]] 1.1. Однако в силу определённых причин (см. «[[SQLJ#SQLJ и JDBC|SQLJ и JDBC]]») возможностей, предоставляемых этим интерфейсом было недостаточно.&lt;br /&gt;
&lt;br /&gt;
Спецификация стандарта SQLJ состоит из трех частей:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Уровень 0&amp;#039;&amp;#039;&amp;#039; регламентирует встраивание SQL-операторов в текст программы на Java;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Уровень 1&amp;#039;&amp;#039;&amp;#039; определяет обратное включение, а именно, реализацию в использующих SQL СУБД хранимых процедур и функций на языке Java;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Уровень 2&amp;#039;&amp;#039;&amp;#039; устанавливает соответствие между типами данных.&lt;br /&gt;
&lt;br /&gt;
К концу [[1998 год]]а все три уровня спецификации были завершены и представлены для рассмотрения в [[ANSI]] в качестве дополнений к стандарту SQL. Первые две части нового стандарта были включены соответственно в части [[SQL/OLB]] и [[SQL/PSM]] стандарта [[SQL:1999]]; третья часть вошла как отдельный модуль [[SQL/JRT]] в стандарт [[SQL:2003]]&lt;br /&gt;
&lt;br /&gt;
Обычно применительно к разработке приложений, работающих с БД, под SQLJ обычно понимается именно уровень 0.&lt;br /&gt;
&lt;br /&gt;
== Пример кода ==&lt;br /&gt;
Приведем простой пример Java-класса, использующего SQLJ для получения результатов запроса из [[Oracle (СУБД)|Oracle]].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
import java.sql.*;&lt;br /&gt;
import oracle.sqlj.runtime.Oracle;&lt;br /&gt;
public class SingleRowQuery extends Base {&lt;br /&gt;
   public static void main(String[] args) {&lt;br /&gt;
      try {&lt;br /&gt;
         connect();&lt;br /&gt;
         singleRowQuery(1);&lt;br /&gt;
      } catch (SQLException e) {&lt;br /&gt;
         e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   public static void singleRowQuery(int id) throws SQLException {&lt;br /&gt;
      String fullname = null;&lt;br /&gt;
      String street = null;&lt;br /&gt;
      #sql {&lt;br /&gt;
         SELECT fullname,&lt;br /&gt;
            street INTO :OUT fullname,&lt;br /&gt;
            :OUT street FROM customer WHERE ID = :IN id};&lt;br /&gt;
      System.out.println(&amp;quot;Customer with ID = &amp;quot; + id);&lt;br /&gt;
      System.out.println();&lt;br /&gt;
      System.out.println(fullname + &amp;quot; &amp;quot; + street);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
Из рассмотрения приведённого кода ясно, что в сам текст процедуры &amp;lt;code&amp;gt;singleRowQuery&amp;lt;/code&amp;gt; встраивается SQL-запрос, и встраивание это организовано по определённым правилам:&lt;br /&gt;
* Текст запроса находится внутри директивы &amp;lt;code&amp;gt;#sql {...}&amp;lt;/code&amp;gt;;&lt;br /&gt;
* Переменные, внешние по отношению к SQL-запросу, задаются внутри него в определенном формате&lt;br /&gt;
Подробно все синтаксические конструкции будут рассмотрены далее.&lt;br /&gt;
&lt;br /&gt;
== SQLJ и JDBC ==&lt;br /&gt;
Логично возникновение вопроса о причинах создания двух параллельных стандартов для реализации технологий доступа к СУБД.&lt;br /&gt;
&lt;br /&gt;
Для начала стоит отметить, что SQLJ и JDBC относятся к разным семействам стандартов и концептуально они разные. JDBC является API, входящим в стандарт языка Java и ориентированным на передачу сформированной программой SQL-конструкции в БД, а также обработку результата. SQLJ же является подмножеством стандарта SQL [[SQL/OLB]] — для него первичным является понятие базы данных, а язык, в который включаются SQL-конструкции, вторичен. Согласно этому стандарту встраивание SQL-операторов допускается не только в Java, но и в языки программирования [[Ада (язык программирования)|Ada]], [[Си (язык программирования)|C]], [[КОБОЛ|COBOL]], [[Фортран|Fortran]], [[MUMPS]], [[ПЛ/1|PL/I]].&lt;br /&gt;
&lt;br /&gt;
Далее, использование SQLJ на самом деле неявно подразумевает вызов JDBC-методов, так как в данном случае они выполняют роль соответственно высоко- и низкоуровневого [[Интерфейс программирования приложений|API]]. Если углубиться в подробности реализации технологий SQLJ и JDBC, то можно обнаружить, что любые SQLJ-директивы прозрачно для программиста специальной подсистемой, называемой &amp;#039;&amp;#039;&amp;#039;SQLJ-препроцессором&amp;#039;&amp;#039;&amp;#039;, транслируются в JDBC-вызовы. Благодаря этому можно спокойно сочетать в одном фрагменте кода SQLJ- и JDBC-вызовы, при необходимости используя общий контекст.&lt;br /&gt;
&lt;br /&gt;
На самом деле, в каждом конкретном случае, когда требуется выполнение SQL-оператора, выбор между SQLJ и JDBC стоит делать, исходя из характера предполагаемой операции. Если это сложный поисковый запрос с возможными вариациями по количеству условий на поиск — тогда однозначно более целесообразно будет формирование текстовой строки запроса и последующее его выполнение через JDBC; если же требуется просто подстановка каких-то переменных либо вычислимых выражений — тогда эргономичнее в части длины кода будет написать SQLJ-директиву.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
Для того, чтобы эффективно использовать синтаксические новшества, вносимые стандартом SQLJ, необходимо предварительно разобраться в их особенностях, связанных с процессом разбора SQLJ-конструкций.&lt;br /&gt;
&lt;br /&gt;
Любые SQLJ-конструкции начинаются с директивы &amp;lt;code&amp;gt;#sql&amp;lt;/code&amp;gt;, в частности, блоки, содержащие внутри себя собственно SQL-запросы, задаются как &amp;lt;code&amp;gt;#sql {…}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Внешние переменные ===&lt;br /&gt;
В терминологии SQLJ &amp;#039;&amp;#039;&amp;#039;внешней переменной&amp;#039;&amp;#039;&amp;#039; ({{lang-en|host variable}}) называется переменная SQLJ-конструкции, используемая для получения значений или передачи их во внешнюю относительно конструкции программную среду. К примеру:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
int i, j;&lt;br /&gt;
i = 1;&lt;br /&gt;
#sql {	SELECT field INTO :OUT j&lt;br /&gt;
            FROM table&lt;br /&gt;
            WHERE id = :IN i };&lt;br /&gt;
System.out.println(j);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Внешние переменные для избежания неоднозначностей должны задаваться в определённом виде, а именно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;:[IN|OUT|INOUT] &amp;lt;имя переменной&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Модификаторы &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OUT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INOUT&amp;lt;/code&amp;gt; опциональны и используются для указания переменных, соответственно, передающих значение извне в SQLJ-конструкцию; возвращающих значение вовне и выполняющих обе функции. Данные ключевые слова используются не только для этого — также они задают метод доступа к внешним переменным внутри SQLJ-конструкции: при наличии модификатора &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; возможно только чтение значения переменной, при наличии &amp;lt;code&amp;gt;OUT&amp;lt;/code&amp;gt; — только запись, при наличии &amp;lt;code&amp;gt;INOUT&amp;lt;/code&amp;gt; — полный доступ. По умолчанию (при отсутствии явно заданного модификатора) переменные объявляются с неявным модификатором &amp;lt;code&amp;gt;INOUT&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Внешние выражения ===&lt;br /&gt;
Вместо просто переменных в SQLJ-конструкциях можно использовать выражения, содержащие внешние переменные, чаще называемые просто &amp;#039;&amp;#039;&amp;#039;внешними выражениями&amp;#039;&amp;#039;&amp;#039; ({{lang-en|host expressions}}). Они имеют определённый синтаксис:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;:( &amp;lt;выражение&amp;gt; )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Основной нюанс при использовании внешних выражений заключается в том, что их использование может повлечь за собой определённые последствия, связанные с тем, что разбор SQLJ-конструкции препроцессором при наличии нескольких внешних выражений идёт в определённом порядке, а при использовании в выражениях присваиваний результат присваивания может быть передан в программную среду.&lt;br /&gt;
&lt;br /&gt;
Для иллюстрации данных двух моментов разберем простой пример использования внешних выражений:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
int i = 1;&lt;br /&gt;
#sql {	SELECT result&lt;br /&gt;
	    FROM  table1&lt;br /&gt;
	    WHERE field1 = :(x[i++]) AND field2 = :(y[i++]) AND field3 = :(z[i++]) };&lt;br /&gt;
System.out.println(i);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Исходя из опыта программирования, можно попытаться предположить, что&lt;br /&gt;
# Значение переменной &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; в процессе разбора SQL-выражения не будет изменяться;&lt;br /&gt;
# Сформированный запрос будет иметь вид&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT result&lt;br /&gt;
    FROM    table1&lt;br /&gt;
    WHERE   field1 = :(x[1]) AND field2 = :(y[1]) AND field3 = :(z[1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Однако и первое, и второе утверждения — неверны. Для проверки этого составим простую схему, проясняющую порядок разбора данной конструкции SQLJ-препроцессором:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
i = 1 &amp;lt;br /&amp;gt;&lt;br /&gt;
x[i++] → x[1], i = 2 &amp;lt;br /&amp;gt;&lt;br /&gt;
y[i++] → y[2], i = 3 &amp;lt;br /&amp;gt;&lt;br /&gt;
z[i++] → z[3], i = 4 &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следовательно:&lt;br /&gt;
# После выполнения SQLJ-директивы будет иметь место &amp;lt;code&amp;gt;i = 4&amp;lt;/code&amp;gt;;&lt;br /&gt;
# Выполняться будет запрос&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT result&lt;br /&gt;
    FROM    table1&lt;br /&gt;
    WHERE   field1 = :(x[1]) AND field2 = :(y[2]) AND field3 = :(z[3])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Контексты ===&lt;br /&gt;
В терминологии SQLJ и JDBC &amp;#039;&amp;#039;&amp;#039;контекстом&amp;#039;&amp;#039;&amp;#039; подключения называется совокупность из трёх параметров, однозначно ими определяемая:&lt;br /&gt;
# название базы данных;&lt;br /&gt;
# идентификатор сессии;&lt;br /&gt;
# идентификатор активной транзакции.&lt;br /&gt;
Для любой SQLJ-конструкции контекст, в котором она будет исполняться, можно определить явно: &amp;lt;code&amp;gt;#sql [&amp;lt;контекст&amp;gt;] {…}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В рамках директивы &amp;lt;code&amp;gt;#sql&amp;lt;/code&amp;gt; можно также создавать новые контексты для последующего использования: &amp;lt;code&amp;gt;#sql context &amp;lt;контекст&amp;gt;&amp;lt;/code&amp;gt;. Если контекст явно не задан, то конструкция считается выполняемом в &amp;#039;&amp;#039;&amp;#039;контексте по умолчанию&amp;#039;&amp;#039;&amp;#039; ({{lang-en|default context}}).&lt;br /&gt;
При необходимости контекст по умолчанию может быть изменён.&lt;br /&gt;
&lt;br /&gt;
=== Итераторы ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Итератором&amp;#039;&amp;#039;&amp;#039; в терминологии стандарта SQLJ называется объект для хранения результата запроса, возвращающего более одной записи. По своей сути и реализации он представляет собой не просто множество записей, а множество с некоторым упорядочением на нём, позволяющим использовать полученные записи последовательно. В этом плане итератор имеет много общего с [[Курсор (базы данных)|курсором]].&lt;br /&gt;
&lt;br /&gt;
Стандартом предусмотрены два типа итераторов — разница между ними достаточно интересна: итераторы с привязкой по позиции в использовании требуют более SQL-подобного синтаксиса, в отличие от итераторов с привязкой по столбцам, которые очень близки по использованию к объектам.&lt;br /&gt;
&lt;br /&gt;
==== Итераторы с привязкой по позиции ====&lt;br /&gt;
Первым типом итератора является итератор с привязкой по позициям. Он объявляется следующим образом: &amp;lt;code&amp;gt;#sql public iterator ByPos (String, int)&amp;lt;/code&amp;gt;. Ясно видно, что в данном случае привязка результатов запроса к итератору осуществляется просто по совпадению типов данных между итератором и результатом запроса. Однако для этого требуется, чтобы типы данных у итератора и результата запроса могли быть отображены друг на друга согласно стандарту SQL/JRT.&lt;br /&gt;
&lt;br /&gt;
Создадим простую таблицу:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
CREATE TABLE people (&lt;br /&gt;
	fullname VARCHAR(50),&lt;br /&gt;
	birthyear NUMERIC(4,0))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь с помощью итератора первого типа и конструкции &amp;lt;code&amp;gt;FETCH … INTO …&amp;lt;/code&amp;gt; произведем выборку данных из результата запроса:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;ByPos positer;&lt;br /&gt;
String name = null;&lt;br /&gt;
int year = 0;&lt;br /&gt;
#sql positer = {SELECT fullname, birthyear FROM people};&lt;br /&gt;
for(;;)&lt;br /&gt;
{&lt;br /&gt;
	#sql {FETCH :positer INTO :name, :year};&lt;br /&gt;
	if (positer.endFetch())&lt;br /&gt;
		break;&lt;br /&gt;
	System.out.println(name + &amp;quot; was born in &amp;quot; + year);&lt;br /&gt;
		&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
Первой директивой осуществляется привязка результата запроса к итератору; второй с помощью конструкции &amp;lt;code&amp;gt;FETCH … INTO …&amp;lt;/code&amp;gt; из результата последовательно считывается по одной записи.&lt;br /&gt;
&lt;br /&gt;
==== Итераторы с именованием столбцов ====&lt;br /&gt;
Вторым типом итератора, более приближенного по использованию к обычным объектам, является итератор с именованием столбцов. Для указанной таблицы создание итератора второго типа будет выглядеть следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
#sql public iterator ByName (&lt;br /&gt;
	String fullNAME,&lt;br /&gt;
	int birthYEAR);&amp;lt;/source&amp;gt;&lt;br /&gt;
Используется он как обычный объект, а именно, доступ к полям осуществляется через соответствующие &amp;#039;&amp;#039;&amp;#039;акцессорные&amp;#039;&amp;#039;&amp;#039; методы:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ByName namiter;&lt;br /&gt;
#sql namiter = {SELECT fullname, birthyear FROM people};&lt;br /&gt;
String s;&lt;br /&gt;
int i;&lt;br /&gt;
while (namiter.next())&lt;br /&gt;
{&lt;br /&gt;
	i = namiter.birthYEAR();&lt;br /&gt;
	s = namiter.fullNAME();&lt;br /&gt;
	System.out.println(s + &amp;quot; was born in &amp;quot;+i);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Однако существует правило, которое должно быть соблюдено — &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;имена полей итератора должны совпадать (без учёта регистра) с именами полей в запросе&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;. Это связано с процессом разбора SQLJ-конструкции препроцессором. В случае, если имя столбца в БД имеет название, несовместимое с правилами именования переменных в Java, необходимо использовать в запросе, формирующем итератор, псевдонимы.&lt;br /&gt;
&lt;br /&gt;
=== Вызовы процедур и функций ===&lt;br /&gt;
Вызовы процедур очень просто записываются с использованием внешних переменных&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;#sql {CALL proc (:myarg)};&amp;lt;/source&amp;gt;&lt;br /&gt;
Функции, в свою очередь, вызываются с использованием конструкции &amp;lt;code&amp;gt;VALUE&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
#sql i = {VALUES(func(34))};&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Взаимодействие с JDBC ==&lt;br /&gt;
Так как SQLJ-директивы при своём использовании используют JDBC-вызовы, то представляет интерес возможность использовать эти технологии совместно. Достаточно легко преобразовывать итераторы в объекты &amp;lt;code&amp;gt;ResultSet&amp;lt;/code&amp;gt; и наоборот.&lt;br /&gt;
&lt;br /&gt;
Преобразование объекта &amp;lt;code&amp;gt;ResultSet&amp;lt;/code&amp;gt; осуществляется очень просто. Для этого сначала нужно определить итератор с именованием столбцов (в нашем примере он будет обозначаться &amp;lt;code&amp;gt;Employees&amp;lt;/code&amp;gt;, а затем выполнить операцию &amp;lt;code&amp;gt;CAST&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
#sql iterator Employees (String ename, double sal);&lt;br /&gt;
&lt;br /&gt;
PreparedStatement stmt = conn.prepareStatement();&lt;br /&gt;
String query = &amp;quot;SELECT ename, sal FROM emp WHERE &amp;quot;;&lt;br /&gt;
query += whereClause;&lt;br /&gt;
ResultSet rs = stmt.executeQuery(query);&lt;br /&gt;
Employees emps;&lt;br /&gt;
#sql emps = {CAST :rs};&lt;br /&gt;
while (emps.next()) {&lt;br /&gt;
      System.out.println(emps.ename() + &amp;quot; earns &amp;quot; + emps.sal());&lt;br /&gt;
}&lt;br /&gt;
emps.close();&lt;br /&gt;
stmt.close();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отдельно стоит обратить внимание, что после привязки результата запроса к итератору отдельно закрывать результат запроса нет надобности — это за программиста сделает сам препроцессор.&lt;br /&gt;
&lt;br /&gt;
Обратный процесс — преобразование итератора в объект &amp;lt;code&amp;gt;ResultSet&amp;lt;/code&amp;gt; производится с помощью итераторов особого типа, так называемых слабо типизированных ({{lang-en|weakly typed}}) итераторов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java5&amp;quot;&amp;gt;&lt;br /&gt;
sqlj.runtime.ResultSetIterator iter;&lt;br /&gt;
#sql iter = {SELECT ename FROM emp};&lt;br /&gt;
&lt;br /&gt;
ResultSet rs = iter.getResultSet();&lt;br /&gt;
while (rs.next()) {&lt;br /&gt;
      System.out.println(&amp;quot;employee name: &amp;quot; + rs.getString(1));&lt;br /&gt;
}&lt;br /&gt;
iter.close();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В этом случае связь между итератором и результатом запроса также сохраняется и закрывать следует именно итератор.&lt;br /&gt;
&lt;br /&gt;
== Особенности SQLJ ==&lt;br /&gt;
Как уже упоминалось ранее, сравнивать SQLJ как технологию проще всего с аналогичной Java-ориентированной технологией того же назначения, а именно — с JDBC. Ситуация усложняется тем, что эти технологии не параллельны и не вполне взаимозаменяемы, а находятся друг над другом архитектурно.&lt;br /&gt;
&lt;br /&gt;
# Запрос одинакового назначения, записанный в JDBC-вызовах и в SQLJ-директиве, в большинстве случаев будет более компактно записан в тексте программы именно во втором случае, что уменьшает размер листинга и вероятность ошибки, связанной со сборкой итоговой строки запроса из небольших фрагментов;&lt;br /&gt;
# Любая SQLJ-директива на этапе компиляции разбирается и проверяется препроцессором, следовательно, все ошибки синтаксиса выявляются ещё на этом этапе, в отличие от JDBC, где контролируется правильность конструкций только с точки зрения синтаксиса Java — за разбор и правильность собственно запроса отвечает уже СУБД, что, естественно, приводит к тому, что ошибки такого рода будут выявлены уже на этапе запуска;&lt;br /&gt;
# Собственно сам препроцессор (обычно имеющий название &amp;lt;code&amp;gt;sqlj&amp;lt;/code&amp;gt;) не входит в [[JDK]]; он и необходимые для его работы библиотеки обычно предоставляются производителем СУБД. Это закономерно — как показано выше, SQLJ гораздо более близок к СУБД, чем собственно к языку Java; более того, препроцессор должен учитывать особенности SQL-синтаксиса «своей» СУБД;&lt;br /&gt;
# В большинстве случаев — особенно это касается часто выполняющихся сложных запросов, работающих с большими массивами данных, — SQLJ-директива будет выполняться в среднем быстрее аналогичного набора JDBC-вызовов. Это связано с тем, что план для соответствующего запроса в случае SQLJ-директивы будет строиться только один раз, а затем использоваться повторно, в отличие от JDBC, где построение плана будет осуществляться при каждом вызове;&lt;br /&gt;
# Создаваемый при трансляции SQLJ-директивы план запроса при необходимости может быть подвергнут настройке со стороны пользователя; в случае JDBC такая возможность по понятным причинам отсутствует;&lt;br /&gt;
# Если запрос требует значительных изменений в каждом конкретном случае (простой пример: поисковый запрос по набору полей, значения в части которых могут отсутствовать), то проще использовать JDBC, так как преимуществ в использовании SQLJ здесь нет;&lt;br /&gt;
# Так как при использовании JDBC нет надобности в дополнительном этапе обработки кода — трансляции, то процесс компиляции в этом случае будет быстрее.&lt;br /&gt;
&lt;br /&gt;
== Недостатки SQLJ ==&lt;br /&gt;
# SQLJ требует дополнительного шага препроцессирования.&lt;br /&gt;
# Большинство IDE не имеют поддержки SQLJ.&lt;br /&gt;
# SQLJ не имеет поддержки в большинстве ORM-фреймворков, таких как Hibernate.&lt;br /&gt;
&lt;br /&gt;
== Поддержка программными средствами ==&lt;br /&gt;
&lt;br /&gt;
=== Oracle ===&lt;br /&gt;
&lt;br /&gt;
=== DB/2 ===&lt;br /&gt;
&lt;br /&gt;
=== Informix ===&lt;br /&gt;
http://www-01.ibm.com/software/data/informix/pubs/library/iif.html&lt;br /&gt;
&lt;br /&gt;
см. Embedded SQLJ User’s Guide&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
# {{cite web| author        =Эндрю Эйзенберг, Джим Мелтон| author-link        =| datepublished        =| url        =http://www.osp.ru/os/1999/04/179794/| title        =Связывания для объектных языков| format        =| work        =| publisher        =| access-date        =2008-11-12| lang        =| description        =| url-status        =dead| archive-date        =2011-09-17| archive-url        =https://web.archive.org/web/20110917013354/http://www.osp.ru/os/1999/04/179794/}}&lt;br /&gt;
# {{cite web| author        =Эндрю Эйзенберг, Джим Мелтон| author-link        =| datepublished        =| url        =http://www.osp.ru/os/1999/09-10/177849/| title        =SQLJ – Часть 1| format        =| work        =| publisher        =| access-date        =2008-11-12| lang        =| description        =| url-status        =dead| archive-date        =2009-02-13| archive-url        =https://web.archive.org/web/20090213034456/http://www.osp.ru/os/1999/09-10/177849/}}&lt;br /&gt;
# {{cite web| author          =[[IBM]] Redbooks| author-link          =| datepublished          =| url          =http://www.redbooks.ibm.com/abstracts/sg246435.html?Open| title          =DB2 for z/OS and OS/390: Ready for Java| format          =| work          =| publisher          =| access-date          =2008-11-12| lang          =| description          =| archive-url          =https://www.webcitation.org/61CEVZKSG?url=http://www.redbooks.ibm.com/abstracts/sg246435.html?Open| archive-date          =2011-08-25| url-status          =dead}}&lt;br /&gt;
# {{cite web| author          =Oracle Database 11g| author-link          =| datepublished          =| url          =http://www.oracle.com/pls/db111/to_toc?pathname=java.111/b31227/toc.htm| title          =SQLJ Developer&amp;#039;s Guide and Reference| format          =| work          =| publisher          =| access-date          =2008-11-12| lang          =| description          =| archive-url          =https://www.webcitation.org/61CEW5DxO?url=http://www.oracle.com/pls/db111/to_toc?pathname=java.111%2Fb31227%2Ftoc.htm| archive-date          =2011-08-25| url-status          =dead}}&lt;br /&gt;
&lt;br /&gt;
[[Категория:Java]]&lt;br /&gt;
[[Категория:Стандарты языка SQL]]&lt;br /&gt;
[[Категория:Стандарты ISO]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Alex NB OT</name></author>
	</entry>
</feed>