SQLJ — підмножина стандарту SQL, спрямована на об'єднання переваг синтаксису мов SQL та Java заради зручності реалізації бізнес-логіки та роботи з даними. Цей стандарт розроблено консорціумом, що складається з компаній IBM, , Microsoft, Compaq (точніше, його підрозділ, що займається СУБД, котрий, скоріш, можна віднести до придбаної компанії ), Informix, Oracle, Sun та Sybase.
Передісторія
На момент появи консорціуму JSQL (що згодом став однойменим зі розробленим ним стандартом) в 1997 році ідея про взаємодію реляційних СУБД і програм на Java була не нова. Компанією (дочірнім підрозділом компанії Sun) уже було розроблено інтерфейс JDBC (англ. Java DataBase Connectivity — «з'єднання з БД засобами Java»), включений у стандарт мови, починаючи з моменту випуску JDK 1.1. Однак унаслідок певних причин (див. «SQLJ і JDBC») можливостей, що надаються цим інтерфейсом, було недостатньо.
Специфікація стандарту SQLJ складається з трьох частин:
- Рівень 0 регламентує вбудовування SQL-операторів у текст програми на Java;
- Рівень 1 визначає зворотне включення, а саме, реалізацію в СУБД, що використовують SQL, збережених процедур і функцій на мові Java;
- Рівень 2 встановлює відповідність між типами даних.
До кінця 1998 року всі три рівні специфікації були завершені й подані до розгляду в ANSI як доповнення до стандарту SQL. Перші дві частини нового стандарту були включені відповідно в частини й стандарту SQL:1999; третя частина увійшла як окремий модуль до стандарту SQL:2003
Зазвичай у застосуванні до розробки додатків, що працюють з БД, під SQLJ здебільшого розуміють саме рівень 0.
Приклад коду
Наведемо простий приклад Java-класу, що використовує SQLJ для отримання результатів запиту з Oracle.
import java.sql.*; import oracle.sqlj.runtime.Oracle; public class SingleRowQuery extends Base { public static void main(String[] args) { try { connect(); singleRowQuery(1); } catch (SQLException e) { e.printStackTrace(); } } public static void singleRowQuery(int id) throws SQLException { String fullname = null; String street = null; #sql { SELECT fullname, street INTO :OUT fullname, :OUT street FROM customer WHERE ID = :IN id}; System.out.println("Customer with ID = " + id); System.out.println(); System.out.println(fullname + " " + street); } }
З розгляду наведеного коду зрозуміло, що в сам текст процедури singleRowQuery
вбудовується SQL-запит, і це вбудовування організовано за певними правилами:
- Текст запиту знаходиться всередині директиви
#sql {...}
; - Змінні, зовнішні відносно SQL-запиту, задаються в ньому всередині в певному форматі
Детально всі синтаксичні конструкції буде розглянуто далі.
SQLJ і JDBC
В чому ж причини створення двох паралельних стандартів для реалізації технологій доступу до СУБД?
Для початку слід зазначити, що SQLJ і JDBC належать до різних родин стандартів і концептуально вони різні. JDBC є API, що входить у стандарт мови Java й орієнтований на передачу сформованої програмою SQL-конструкції в БД, а також обробку результату. SQLJ же є підмножиною стандарту SQL — для нього первинним є поняття бази даних, а мова, в яку включаються SQL-конструкції, вторинний. Згідно з цим стандартом вбудовування SQL-операторів допускається не лише в Java, але й у мови програмування Ada, C, COBOL, Fortran, , (PL/1).
Далі, використання SQLJ насправді неявно означає виклик JDBC-методів, оскільки в даному випадку вони виконують роль відповідно високо- й низькорівневого API. Якщо заглибитися в подробиці реалізації технологій SQLJ і JDBC, то можна виявити, що будь-які SQLJ-директиви прозоро для програміста спеціальною підсистемою (SQLJ-препроцесором) транслюються в JDBC-виклики. Завдяки цьому можна спокійно поєднувати в одному фрагменті коду SQLJ- і JDBC-виклики, за необхідності використовуючи спільний контекст.
Насправді в кожному конкретному випадку, коли потрібне виконання SQL-оператора, вибір між SQLJ і JDBC слід робити, виходячи з характеру очікуваної операції. Якщо це складний пошуковий запит з можливими варіаціями за кількістю умов на пошук — тоді однозначно доцільніше формування текстового рядка запиту й подальше його виконання через JDBC; якщо ж потрібна просто підстановка якихось змінних або обчислюваних виразів — тоді ергономічніше з точки зору довжини коду буде написати SQLJ-директиву.
Синтаксис
Для того, щоб ефективно використовувати синтаксичні нововведення, внесені стандартом SQLJ, необхідно попередньо розібратися в їх особливостях, пов'язаних з процесом розбору SQLJ-конструкцій.
Будь-які SQLJ-конструкції починаються з директиви #sql
, зокрема, блоки, що містять власне SQL-запити, задаються як #sql {…}
.
Зовнішні змінні
В термінології SQLJ зовнішньою змінною (англ. host variable) називається змінна SQLJ-конструкції, використовувана для отримання значень чи передачі їх у зовнішнє відносно конструкції програмне середовище. Наприклад:
int i, j; i = 1; #sql {SELECT field INTO :OUT j FROM table WHERE id = :IN i }; System.out.println(j);
Зовнішні змінні для уникнення неоднозначностей мають задаватися в певному вигляді, а саме:
:[IN|OUT|INOUT] <ім'я змінної>
.
Модифікатори IN
, OUT
, INOUT
опціональні й використовуються для вказання змінних, котрі, власне, передають значення з-за меж усередину SQLJ-конструкції; повертають значення назовні й виконують обидві функції. Дані ключові слова вживаються не лише для цього — також вони задають метод доступу до зовнішніх змінних усередині SQLJ-конструкції: за наявності модифікатора IN
можливе лише читання значення змінної, за наявності OUT
— лише запис, за наявності INOUT
— повний доступ. За умовчанням (за відсутності явно заданого модифікатора) змінні оголошуються з неявним модифікатором INOUT
.
Зовнішні вирази
Замість просто змінних в SQLJ-конструкціях можна використовувати вирази, що містять зовнішні змінні, що частіше називаються просто зовнішніми виразами (англ. host expressions). Вони мають певний синтаксис:
:( <вираз> )
Основний нюанс при використанні зовнішніх виразів полягає в тому, що їх використання може потягнути за собою певні наслідки, пов'язані з тим, що розбір SQLJ-конструкції препроцесором за наявності кількох зовнішніх виразів іде в визначеному порядку, а при використанні в виразах присвоювань результат присвоєння може передаватися в програмне середовище.
Для ілюстрації цих двох моментів розберімо простий приклад використання зовнішніх виразів:
int i = 1; #sql {SELECT result FROM table1 WHERE field1 = :(x[i++]) AND field2 = :(y[i++]) AND field3 = :(z[i++]) }; System.out.println(i);
Виходячи з досвіду програмування, можна зробити припущення, що
- Значення змінної
i
в процесі розбору SQL-виразу не змінюватиметься; - Сформований запит буде мати вигляд
SELECT result FROM table1 WHERE field1 = :(x[1]) AND field2 = :(y[1]) AND field3 = :(z[1])
Однак і перше, і друге твердження — хибні. Для перевірки цього складімо просту схему, що прояснить порядок розбору даної конструкції SQLJ-препроцесором:
i = 1
x[i++] > x[1], i = 2
y[i++] > y[2], i = 3
z[i++] > z[3], i = 4
Отже:
- Після виконання SQLJ-директиви матиме місце
i = 4
; - Виконуватись буде запит
SELECT result FROM table1 WHERE field1 = :(x[1]) AND field2 = :(y[2]) AND field3 = :(z[3])
Контексти
В термінології SQLJ і JDBC контекстом підключення називається сукупність із трьох параметрів, що однозначно ними визначається:
- назва бази даних;
- ідентифікатор сесії;
- ідентифікатор активної транзакції.
Для будь-якої SQLJ-конструкції контекст, у якому вона буде виконуватись, можна визначити явно: #sql [<контекст>] {…}
.
В рамках директиви #sql
можна також створювати нові контексти для наступного використання: #sql context <контекст>
. Якщо контекст явно не задано, то конструкція вважається виконуваною в контексті за умовчанням (англ. default context). За необхідності контекст за умовчанням може бути зміненим.
Ітератори
Ітератором в термінології стандарту SQLJ називається об'єкт для зберігання результату запиту, що повертає більше одного запису. За своєю суттю й реалізацією він являє собою не просто множину записів, а множину деяким упорядкуванням у ній, що дозволяє обробляти отримані записи послідовно. В цьому плані ітератор має багато спільного з курсором.
Стандартом передбачені два типи ітераторів — різниця між ними достатньо цікава: ітератори з прив'язкою за позицією — вимагають більш SQL-подібного синтаксису, на відміну від ітераторів з прив'язкою за стовпчиками, котрі дуже близькі за способом використання до об'єктів.
Ітератори з прив'язкою за позицією
Першим типом ітератора є ітератор з прив'язкою за позиціями. Він оголошується так: #sql public iterator ByPos (String, int)
. Ясно видно, що в даному випадку прив'язка результатів запиту до ітератора здійснюється просто за збігом типів даних між ітератором і результатом запиту. Однак для цього потрібно, щоб типи даних у ітератора й результату запиту могли бути відображені один на одного відповідно до стандарту SQL/JRT.
Створімо просту таблицю:
CREATE TABLE people ( fullname VARCHAR(50), birthyear NUMERIC(4,0))
Тепер з допомогою ітератора першого типу й конструкції FETCH … INTO …
проведімо вибір даних з результату запиту:
ByPos positer; String name = null; int year = 0; #sql positer = {SELECT fullname, birthyear FROM people}; for(;;) { #sql {FETCH :positer INTO :name, :year}; if (positer.endFetch()) break; System.out.println(name + " was born in " + year); }
Першою директивою здійснюється прив'язка результату запиту до ітератора; другою з допомогою конструкції FETCH … INTO …
з результату послідовно зчитується по одному запису.
Ітератори з іменуванням стовпчиків
Другим типом ітератора, більш наближеного за використанням до звичайних об'єктів, є ітератор з іменуванням стовпчиків. Для вказаної таблиці створення ітератора другого типу буде виглядати так:
#sql public iterator ByName ( String fullNAME, int birthYEAR);
Використовується він як звичайний об'єкт, а саме, доступ до полів здійснюється через відповідні акцесорні методи:
ByName namiter; #sql namiter = {SELECT fullname, birthyear FROM people}; String s; int i; while (namiter.next()) { i = namiter.birthYEAR(); s = namiter.fullNAME(); System.out.println(s + " was born in "+i); }
Однак існує правило, яке має виконуватись — імена полів ітератора мають збігатися (без урахування регістру) з іменами полів у запиті. Це пов'язано з процесом розбору SQLJ-конструкції препроцесором. У випадку, якщо ім'я стовпчика в БД має назву, несумісну з правилами іменування змінних у Java, необхідно використовувати псевдоніми в запиті, що формує ітератор.
Виклики процедур і функцій
Виклики процедур дуже просто записуються з використанням зовнішніх змінних:
#sql {CALL proc (:myarg)};
Функції, в свою чергу, викликаються з використанням конструкції VALUE
int i; #sql i = {VALUES(func(34))};
Взаємодія з JDBC
Оскільки SQLJ-директиви при своєму використанні здійснюють JDBC-виклики, то цікавою є можливість використати ці технології разом. Досить легко перетворити ітератори в об'єкти ResultSet
і навпаки.
Перетворення об'єкта ResultSet
здійснюється дуже просто. Для цього спершу треба визначити ітератор з іменуванням стовпчиків (в нашому прикладі його буде позначено як Employees
), а потім виконати операцію CAST
:
#sql iterator Employees (String ename, double sal); PreparedStatement stmt = conn.prepareStatement(); String query = "SELECT ename, sal FROM emp WHERE "; query += whereClause; ResultSet rs = stmt.executeQuery(query); Employees emps; #sql emps = {CAST :rs}; while (emps.next()) { System.out.println(emps.ename() + " earns " + emps.sal()); } emps.close(); stmt.close();
Окремо варто зазначити, що після прив'язки результату запиту до ітератора окремо закривати результат запиту непотрібно — це за програміста зробить сам препроцесор.
Зворотний процес — перетворення ітератора в об'ект ResultSet
здійснюється з допомогою ітераторів особливого типу, так званих слабо типізованих (англ. weakly typed) ітераторів.
sqlj.runtime.ResultSetIterator iter; #sql iter = {SELECT ename FROM emp}; ResultSet rs = iter.getResultSet(); while (rs.next()) { System.out.println("employee name: " + rs.getString(1)); } iter.close();
В цьому випадку зв'язок між ітератором і результатом запиту також зберігається й закривати слід саме ітератор.
Плюси й мінуси SQLJ
Як уже згадувалось раніше, порівнювати SQLJ як технологію простіше всього з аналогічною Java-орієнтованою технологією того ж призначення, а саме — з JDBC. Ситуація ускладнюється тим, що ці технології не паралельні й не повністю взаємозамінні, а перебувають одна над одною архітектурно.
- Запит однакового призначення, записаний у JDBC-викликах і в SQLJ-директиві, в більшості випадків буде більш компактно записано в тексті програми саме у другому випадку, що зменшує розмір лістингу й імовірність помилки, пов'язаної зі збиранням підсумкового рядка запиту з невеликих фрагментів;
- Будь-яка SQLJ-директива на етапі компіляції розбирається й перевіряється препроцесором, отже, всі помилки синтаксису виявляються ще на цьому етапі, на відміну від JDBC, де контролюється правильність конструкцій тільки з точки зору синтаксису Java — за розбір і правильність власне запиту відповідає вже СУБД, що, звичайно ж, призводить до того, що такі помилки будуть виявлені вже на етапі запуску;
- Власне сам препроцесор (що здебільшого має назву
sqlj
) не входить до JDK; він і необхідні для його роботи бібліотеки звичайно надаються виробниками СУБД. Це закономірно — як показано вище, SQLJ значно ближчий до СУБД, ніж власне до мови Java; більше того, препроцесор має враховувати особливості SQL-синтаксису «своєї» СУБД; - В більшості випадків — особливо це стосується часто виконуваних складних запитів, що працюють з великими масивами даних, — SQLJ-директива буде виконуватись в середньому швидше, ніж аналогічний набір JDBC-викликів. Це пов'язано з тим, що план для відповідного запиту в випадку SQLJ-директиви буде побудовано лише один раз, а потім використовуватиметься повторно, на відміну від JDBC, де побудова плану здійснюватиметься при кожному виклику;
- Створюваний при трансляції SQLJ-директиви план запиту за необхідності може піддаватись налаштуванню з боку користувача; в випадку JDBC така можливість зі зрозумілих причин відсутня;
- Якщо запит вимагає значних змін у кожному конкретному випадку (простий приклад: пошуковий запит за набором полів, значення в частині яких можуть бути відсутніми), то простіше використати JDBC, оскільки переваг у використанні SQLJ тут нема;
- Оскільки при використанні JDBC не потрібен додатковий етап обробки коду — трансляція, то процес компіляції в цьому випадку буде швидшим.
Приклади
В наступних прикладах порівнюється синтаксис SQLJ з використанням JDBC.
JDBC | SQLJ |
---|---|
Багаторядковий запит | |
PreparedStatement stmt = conn.prepareStatement( "SELECT LASTNAME" + " , FIRSTNME" + " , SALARY" + " FROM DSN8710.EMP" + " WHERE SALARY BETWEEN ? AND ?"); stmt.setBigDecimal(1, min); stmt.setBigDecimal(2, max); ResultSet rs = stmt.executeQuery(); while (rs.next()) { lastname = rs.getString(1); firstname = rs.getString(2); salary = rs.getBigDecimal(3); // Print row... } rs.close(); stmt.close(); | #sql private static iterator EmployeeIterator( String, String, BigDecimal); ... EmployeeIterator iter; #sql [ctx] iter = { SELECT LASTNAME , FIRSTNME , SALARY FROM DSN8710.EMP WHERE SALARY BETWEEN :min AND :max }; do { #sql { FETCH :iter INTO :lastname, :firstname, :salary }; // Print row... } while (!iter.endFetch()); iter.close(); |
Однорядковий запит | |
PreparedStatement stmt = conn.prepareStatement( "SELECT MAX(SALARY), AVG(SALARY)" + " FROM DSN8710.EMP"); rs = stmt.executeQuery(); if (!rs.next()) { // Error—no rows found } maxSalary = rs.getBigDecimal(1); avgSalary = rs.getBigDecimal(2); if (rs.next()) { // Error—more than one row found } rs.close(); stmt.close(); | #sql [ctx] { SELECT MAX(SALARY), AVG(SALARY) INTO :maxSalary, :avgSalary FROM DSN8710.EMP }; |
команда INSERT | |
stmt = conn.prepareStatement( "INSERT INTO DSN8710.EMP (" + "EMPNO, FIRSTNME, MIDINIT, LASTNAME, HIREDATE, SALARY" + ") VALUES (?, ?, ?, ?, CURRENT DATE, ?)"); stmt.setString(1, empno); stmt.setString(2, firstname); stmt.setString(3, midinit); stmt.setString(4, lastname); stmt.setBigDecimal(5, salary); stmt.executeUpdate(); stmt.close(); | #sql [ctx] { INSERT INTO DSN8710.EMP (EMPNO, FIRSTNME, MIDINIT, LASTNAME, HIREDATE, SALARY) VALUES (:empno, :firstname, :midinit, :lastname, CURRENT DATE, :salary) }; |
Підтримка програмними засобами
Oracle
DB/2
Informix
http://www-01.ibm.com/software/data/informix/pubs/library/iif.html [ 12 лютого 2009 у Wayback Machine.]
Див. Embedded SQLJ User’s Guide
Посилання
- Эндрю Эйзенберг, Джим Мелтон. Связывания для объектных языков. Архів оригіналу за 25 серпня 2011. Процитовано 12 листопада 2008.
{{}}
: Cite має пусті невідомі параметри:|description=
та|datepublished=
() - Эндрю Эйзенберг, Джим Мелтон. SQLJ – Часть 1. Архів оригіналу за 25 серпня 2011. Процитовано 12 листопада 2008.
{{}}
: Cite має пусті невідомі параметри:|description=
та|datepublished=
() - IBM Redbooks. DB2 for z/OS and OS/390: Ready for Java. Архів оригіналу за 25 серпня 2011. Процитовано 12 листопада 2008.
{{}}
: Cite має пусті невідомі параметри:|description=
та|datepublished=
() - Oracle Database 11g. SQLJ Developer's Guide and Reference. Архів оригіналу за 25 серпня 2011. Процитовано 12 листопада 2008.
{{}}
: Cite має пусті невідомі параметри:|description=
та|datepublished=
()
Зовнішні посилання
- http://sqlj.org/ [ 4 січня 2014 у Wayback Machine.]
- IBM Redbook: DB2 for z/OS and OS/390: Ready for Java [ 18 травня 2011 у Wayback Machine.]
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
SQLJ pidmnozhina standartu SQL spryamovana na ob yednannya perevag sintaksisu mov SQL ta Java zaradi zruchnosti realizaciyi biznes logiki ta roboti z danimi Cej standart rozrobleno konsorciumom sho skladayetsya z kompanij IBM Microsoft Compaq tochnishe jogo pidrozdil sho zajmayetsya SUBD kotrij skorish mozhna vidnesti do pridbanoyi kompaniyi Informix Oracle Sun ta Sybase PeredistoriyaNa moment poyavi konsorciumu JSQL sho zgodom stav odnojmenim zi rozroblenim nim standartom v 1997 roci ideya pro vzayemodiyu relyacijnih SUBD i program na Java bula ne nova Kompaniyeyu dochirnim pidrozdilom kompaniyi Sun uzhe bulo rozrobleno interfejs JDBC angl Java DataBase Connectivity z yednannya z BD zasobami Java vklyuchenij u standart movi pochinayuchi z momentu vipusku JDK 1 1 Odnak unaslidok pevnih prichin div SQLJ i JDBC mozhlivostej sho nadayutsya cim interfejsom bulo nedostatno Specifikaciya standartu SQLJ skladayetsya z troh chastin Riven 0 reglamentuye vbudovuvannya SQL operatoriv u tekst programi na Java Riven 1 viznachaye zvorotne vklyuchennya a same realizaciyu v SUBD sho vikoristovuyut SQL zberezhenih procedur i funkcij na movi Java Riven 2 vstanovlyuye vidpovidnist mizh tipami danih Do kincya 1998 roku vsi tri rivni specifikaciyi buli zaversheni j podani do rozglyadu v ANSI yak dopovnennya do standartu SQL Pershi dvi chastini novogo standartu buli vklyucheni vidpovidno v chastini j standartu SQL 1999 tretya chastina uvijshla yak okremij modul do standartu SQL 2003 Zazvichaj u zastosuvanni do rozrobki dodatkiv sho pracyuyut z BD pid SQLJ zdebilshogo rozumiyut same riven 0 Priklad koduNavedemo prostij priklad Java klasu sho vikoristovuye SQLJ dlya otrimannya rezultativ zapitu z Oracle import java sql import oracle sqlj runtime Oracle public class SingleRowQuery extends Base public static void main String args try connect singleRowQuery 1 catch SQLException e e printStackTrace public static void singleRowQuery int id throws SQLException String fullname null String street null sql SELECT fullname street INTO OUT fullname OUT street FROM customer WHERE ID IN id System out println Customer with ID id System out println System out println fullname street Z rozglyadu navedenogo kodu zrozumilo sho v sam tekst proceduri singleRowQuery vbudovuyetsya SQL zapit i ce vbudovuvannya organizovano za pevnimi pravilami Tekst zapitu znahoditsya vseredini direktivi sql Zminni zovnishni vidnosno SQL zapitu zadayutsya v nomu vseredini v pevnomu formati Detalno vsi sintaksichni konstrukciyi bude rozglyanuto dali SQLJ i JDBCV chomu zh prichini stvorennya dvoh paralelnih standartiv dlya realizaciyi tehnologij dostupu do SUBD Dlya pochatku slid zaznachiti sho SQLJ i JDBC nalezhat do riznih rodin standartiv i konceptualno voni rizni JDBC ye API sho vhodit u standart movi Java j oriyentovanij na peredachu sformovanoyi programoyu SQL konstrukciyi v BD a takozh obrobku rezultatu SQLJ zhe ye pidmnozhinoyu standartu SQL dlya nogo pervinnim ye ponyattya bazi danih a mova v yaku vklyuchayutsya SQL konstrukciyi vtorinnij Zgidno z cim standartom vbudovuvannya SQL operatoriv dopuskayetsya ne lishe v Java ale j u movi programuvannya Ada C COBOL Fortran PL 1 Dali vikoristannya SQLJ naspravdi neyavno oznachaye viklik JDBC metodiv oskilki v danomu vipadku voni vikonuyut rol vidpovidno visoko j nizkorivnevogo API Yaksho zaglibitisya v podrobici realizaciyi tehnologij SQLJ i JDBC to mozhna viyaviti sho bud yaki SQLJ direktivi prozoro dlya programista specialnoyu pidsistemoyu SQLJ preprocesorom translyuyutsya v JDBC vikliki Zavdyaki comu mozhna spokijno poyednuvati v odnomu fragmenti kodu SQLJ i JDBC vikliki za neobhidnosti vikoristovuyuchi spilnij kontekst Naspravdi v kozhnomu konkretnomu vipadku koli potribne vikonannya SQL operatora vibir mizh SQLJ i JDBC slid robiti vihodyachi z harakteru ochikuvanoyi operaciyi Yaksho ce skladnij poshukovij zapit z mozhlivimi variaciyami za kilkistyu umov na poshuk todi odnoznachno docilnishe formuvannya tekstovogo ryadka zapitu j podalshe jogo vikonannya cherez JDBC yaksho zh potribna prosto pidstanovka yakihos zminnih abo obchislyuvanih viraziv todi ergonomichnishe z tochki zoru dovzhini kodu bude napisati SQLJ direktivu SintaksisDlya togo shob efektivno vikoristovuvati sintaksichni novovvedennya vneseni standartom SQLJ neobhidno poperedno rozibratisya v yih osoblivostyah pov yazanih z procesom rozboru SQLJ konstrukcij Bud yaki SQLJ konstrukciyi pochinayutsya z direktivi sql zokrema bloki sho mistyat vlasne SQL zapiti zadayutsya yak sql Zovnishni zminni V terminologiyi SQLJ zovnishnoyu zminnoyu angl host variable nazivayetsya zminna SQLJ konstrukciyi vikoristovuvana dlya otrimannya znachen chi peredachi yih u zovnishnye vidnosno konstrukciyi programne seredovishe Napriklad int i j i 1 sql SELECT field INTO OUT j FROM table WHERE id IN i System out println j Zovnishni zminni dlya uniknennya neodnoznachnostej mayut zadavatisya v pevnomu viglyadi a same IN OUT INOUT lt im ya zminnoyi gt Modifikatori IN OUT INOUT opcionalni j vikoristovuyutsya dlya vkazannya zminnih kotri vlasne peredayut znachennya z za mezh useredinu SQLJ konstrukciyi povertayut znachennya nazovni j vikonuyut obidvi funkciyi Dani klyuchovi slova vzhivayutsya ne lishe dlya cogo takozh voni zadayut metod dostupu do zovnishnih zminnih useredini SQLJ konstrukciyi za nayavnosti modifikatora IN mozhlive lishe chitannya znachennya zminnoyi za nayavnosti OUT lishe zapis za nayavnosti INOUT povnij dostup Za umovchannyam za vidsutnosti yavno zadanogo modifikatora zminni ogoloshuyutsya z neyavnim modifikatorom INOUT Zovnishni virazi Zamist prosto zminnih v SQLJ konstrukciyah mozhna vikoristovuvati virazi sho mistyat zovnishni zminni sho chastishe nazivayutsya prosto zovnishnimi virazami angl host expressions Voni mayut pevnij sintaksis lt viraz gt Osnovnij nyuans pri vikoristanni zovnishnih viraziv polyagaye v tomu sho yih vikoristannya mozhe potyagnuti za soboyu pevni naslidki pov yazani z tim sho rozbir SQLJ konstrukciyi preprocesorom za nayavnosti kilkoh zovnishnih viraziv ide v viznachenomu poryadku a pri vikoristanni v virazah prisvoyuvan rezultat prisvoyennya mozhe peredavatisya v programne seredovishe Dlya ilyustraciyi cih dvoh momentiv rozberimo prostij priklad vikoristannya zovnishnih viraziv int i 1 sql SELECT result FROM table1 WHERE field1 x i AND field2 y i AND field3 z i System out println i Vihodyachi z dosvidu programuvannya mozhna zrobiti pripushennya sho Znachennya zminnoyi i v procesi rozboru SQL virazu ne zminyuvatimetsya Sformovanij zapit bude mati viglyadSELECT result FROM table1 WHERE field1 x 1 AND field2 y 1 AND field3 z 1 Odnak i pershe i druge tverdzhennya hibni Dlya perevirki cogo skladimo prostu shemu sho proyasnit poryadok rozboru danoyi konstrukciyi SQLJ preprocesorom i 1 br x i gt x 1 i 2 br y i gt y 2 i 3 br z i gt z 3 i 4 br Otzhe Pislya vikonannya SQLJ direktivi matime misce i 4 Vikonuvatis bude zapitSELECT result FROM table1 WHERE field1 x 1 AND field2 y 2 AND field3 z 3 Konteksti V terminologiyi SQLJ i JDBC kontekstom pidklyuchennya nazivayetsya sukupnist iz troh parametriv sho odnoznachno nimi viznachayetsya nazva bazi danih identifikator sesiyi identifikator aktivnoyi tranzakciyi Dlya bud yakoyi SQLJ konstrukciyi kontekst u yakomu vona bude vikonuvatis mozhna viznachiti yavno sql lt kontekst gt V ramkah direktivi sql mozhna takozh stvoryuvati novi konteksti dlya nastupnogo vikoristannya sql context lt kontekst gt Yaksho kontekst yavno ne zadano to konstrukciya vvazhayetsya vikonuvanoyu v konteksti za umovchannyam angl default context Za neobhidnosti kontekst za umovchannyam mozhe buti zminenim Iteratori Iteratorom v terminologiyi standartu SQLJ nazivayetsya ob yekt dlya zberigannya rezultatu zapitu sho povertaye bilshe odnogo zapisu Za svoyeyu suttyu j realizaciyeyu vin yavlyaye soboyu ne prosto mnozhinu zapisiv a mnozhinu deyakim uporyadkuvannyam u nij sho dozvolyaye obroblyati otrimani zapisi poslidovno V comu plani iterator maye bagato spilnogo z kursorom Standartom peredbacheni dva tipi iteratoriv riznicya mizh nimi dostatno cikava iteratori z priv yazkoyu za poziciyeyu vimagayut bilsh SQL podibnogo sintaksisu na vidminu vid iteratoriv z priv yazkoyu za stovpchikami kotri duzhe blizki za sposobom vikoristannya do ob yektiv Iteratori z priv yazkoyu za poziciyeyu Pershim tipom iteratora ye iterator z priv yazkoyu za poziciyami Vin ogoloshuyetsya tak sql public iterator ByPos String int Yasno vidno sho v danomu vipadku priv yazka rezultativ zapitu do iteratora zdijsnyuyetsya prosto za zbigom tipiv danih mizh iteratorom i rezultatom zapitu Odnak dlya cogo potribno shob tipi danih u iteratora j rezultatu zapitu mogli buti vidobrazheni odin na odnogo vidpovidno do standartu SQL JRT Stvorimo prostu tablicyu CREATE TABLE people fullname VARCHAR 50 birthyear NUMERIC 4 0 Teper z dopomogoyu iteratora pershogo tipu j konstrukciyi FETCH INTO provedimo vibir danih z rezultatu zapitu ByPos positer String name null int year 0 sql positer SELECT fullname birthyear FROM people for sql FETCH positer INTO name year if positer endFetch break System out println name was born in year Pershoyu direktivoyu zdijsnyuyetsya priv yazka rezultatu zapitu do iteratora drugoyu z dopomogoyu konstrukciyi FETCH INTO z rezultatu poslidovno zchituyetsya po odnomu zapisu Iteratori z imenuvannyam stovpchikiv Drugim tipom iteratora bilsh nablizhenogo za vikoristannyam do zvichajnih ob yektiv ye iterator z imenuvannyam stovpchikiv Dlya vkazanoyi tablici stvorennya iteratora drugogo tipu bude viglyadati tak sql public iterator ByName String fullNAME int birthYEAR Vikoristovuyetsya vin yak zvichajnij ob yekt a same dostup do poliv zdijsnyuyetsya cherez vidpovidni akcesorni metodi ByName namiter sql namiter SELECT fullname birthyear FROM people String s int i while namiter next i namiter birthYEAR s namiter fullNAME System out println s was born in i Odnak isnuye pravilo yake maye vikonuvatis imena poliv iteratora mayut zbigatisya bez urahuvannya registru z imenami poliv u zapiti Ce pov yazano z procesom rozboru SQLJ konstrukciyi preprocesorom U vipadku yaksho im ya stovpchika v BD maye nazvu nesumisnu z pravilami imenuvannya zminnih u Java neobhidno vikoristovuvati psevdonimi v zapiti sho formuye iterator Vikliki procedur i funkcij Vikliki procedur duzhe prosto zapisuyutsya z vikoristannyam zovnishnih zminnih sql CALL proc myarg Funkciyi v svoyu chergu viklikayutsya z vikoristannyam konstrukciyi VALUE int i sql i VALUES func 34 Vzayemodiya z JDBCOskilki SQLJ direktivi pri svoyemu vikoristanni zdijsnyuyut JDBC vikliki to cikavoyu ye mozhlivist vikoristati ci tehnologiyi razom Dosit legko peretvoriti iteratori v ob yekti ResultSet i navpaki Peretvorennya ob yekta ResultSet zdijsnyuyetsya duzhe prosto Dlya cogo spershu treba viznachiti iterator z imenuvannyam stovpchikiv v nashomu prikladi jogo bude poznacheno yak Employees a potim vikonati operaciyu CAST sql iterator Employees String ename double sal PreparedStatement stmt conn prepareStatement String query SELECT ename sal FROM emp WHERE query whereClause ResultSet rs stmt executeQuery query Employees emps sql emps CAST rs while emps next System out println emps ename earns emps sal emps close stmt close Okremo varto zaznachiti sho pislya priv yazki rezultatu zapitu do iteratora okremo zakrivati rezultat zapitu nepotribno ce za programista zrobit sam preprocesor Zvorotnij proces peretvorennya iteratora v ob ekt ResultSet zdijsnyuyetsya z dopomogoyu iteratoriv osoblivogo tipu tak zvanih slabo tipizovanih angl weakly typed iteratoriv sqlj runtime ResultSetIterator iter sql iter SELECT ename FROM emp ResultSet rs iter getResultSet while rs next System out println employee name rs getString 1 iter close V comu vipadku zv yazok mizh iteratorom i rezultatom zapitu takozh zberigayetsya j zakrivati slid same iterator Plyusi j minusi SQLJYak uzhe zgaduvalos ranishe porivnyuvati SQLJ yak tehnologiyu prostishe vsogo z analogichnoyu Java oriyentovanoyu tehnologiyeyu togo zh priznachennya a same z JDBC Situaciya uskladnyuyetsya tim sho ci tehnologiyi ne paralelni j ne povnistyu vzayemozaminni a perebuvayut odna nad odnoyu arhitekturno Zapit odnakovogo priznachennya zapisanij u JDBC viklikah i v SQLJ direktivi v bilshosti vipadkiv bude bilsh kompaktno zapisano v teksti programi same u drugomu vipadku sho zmenshuye rozmir listingu j imovirnist pomilki pov yazanoyi zi zbirannyam pidsumkovogo ryadka zapitu z nevelikih fragmentiv Bud yaka SQLJ direktiva na etapi kompilyaciyi rozbirayetsya j pereviryayetsya preprocesorom otzhe vsi pomilki sintaksisu viyavlyayutsya she na comu etapi na vidminu vid JDBC de kontrolyuyetsya pravilnist konstrukcij tilki z tochki zoru sintaksisu Java za rozbir i pravilnist vlasne zapitu vidpovidaye vzhe SUBD sho zvichajno zh prizvodit do togo sho taki pomilki budut viyavleni vzhe na etapi zapusku Vlasne sam preprocesor sho zdebilshogo maye nazvu sqlj ne vhodit do JDK vin i neobhidni dlya jogo roboti biblioteki zvichajno nadayutsya virobnikami SUBD Ce zakonomirno yak pokazano vishe SQLJ znachno blizhchij do SUBD nizh vlasne do movi Java bilshe togo preprocesor maye vrahovuvati osoblivosti SQL sintaksisu svoyeyi SUBD V bilshosti vipadkiv osoblivo ce stosuyetsya chasto vikonuvanih skladnih zapitiv sho pracyuyut z velikimi masivami danih SQLJ direktiva bude vikonuvatis v serednomu shvidshe nizh analogichnij nabir JDBC viklikiv Ce pov yazano z tim sho plan dlya vidpovidnogo zapitu v vipadku SQLJ direktivi bude pobudovano lishe odin raz a potim vikoristovuvatimetsya povtorno na vidminu vid JDBC de pobudova planu zdijsnyuvatimetsya pri kozhnomu vikliku Stvoryuvanij pri translyaciyi SQLJ direktivi plan zapitu za neobhidnosti mozhe piddavatis nalashtuvannyu z boku koristuvacha v vipadku JDBC taka mozhlivist zi zrozumilih prichin vidsutnya Yaksho zapit vimagaye znachnih zmin u kozhnomu konkretnomu vipadku prostij priklad poshukovij zapit za naborom poliv znachennya v chastini yakih mozhut buti vidsutnimi to prostishe vikoristati JDBC oskilki perevag u vikoristanni SQLJ tut nema Oskilki pri vikoristanni JDBC ne potriben dodatkovij etap obrobki kodu translyaciya to proces kompilyaciyi v comu vipadku bude shvidshim PrikladiV nastupnih prikladah porivnyuyetsya sintaksis SQLJ z vikoristannyam JDBC JDBC SQLJBagatoryadkovij zapitPreparedStatement stmt conn prepareStatement SELECT LASTNAME FIRSTNME SALARY FROM DSN8710 EMP WHERE SALARY BETWEEN AND stmt setBigDecimal 1 min stmt setBigDecimal 2 max ResultSet rs stmt executeQuery while rs next lastname rs getString 1 firstname rs getString 2 salary rs getBigDecimal 3 Print row rs close stmt close sql private static iterator EmployeeIterator String String BigDecimal EmployeeIterator iter sql ctx iter SELECT LASTNAME FIRSTNME SALARY FROM DSN8710 EMP WHERE SALARY BETWEEN min AND max do sql FETCH iter INTO lastname firstname salary Print row while iter endFetch iter close Odnoryadkovij zapitPreparedStatement stmt conn prepareStatement SELECT MAX SALARY AVG SALARY FROM DSN8710 EMP rs stmt executeQuery if rs next Error no rows found maxSalary rs getBigDecimal 1 avgSalary rs getBigDecimal 2 if rs next Error more than one row found rs close stmt close sql ctx SELECT MAX SALARY AVG SALARY INTO maxSalary avgSalary FROM DSN8710 EMP komanda INSERTstmt conn prepareStatement INSERT INTO DSN8710 EMP EMPNO FIRSTNME MIDINIT LASTNAME HIREDATE SALARY VALUES CURRENT DATE stmt setString 1 empno stmt setString 2 firstname stmt setString 3 midinit stmt setString 4 lastname stmt setBigDecimal 5 salary stmt executeUpdate stmt close sql ctx INSERT INTO DSN8710 EMP EMPNO FIRSTNME MIDINIT LASTNAME HIREDATE SALARY VALUES empno firstname midinit lastname CURRENT DATE salary Pidtrimka programnimi zasobamiOracle DB 2 Informix http www 01 ibm com software data informix pubs library iif html 12 lyutogo 2009 u Wayback Machine Div Embedded SQLJ User s GuidePosilannyaEndryu Ejzenberg Dzhim Melton Svyazyvaniya dlya obektnyh yazykov Arhiv originalu za 25 serpnya 2011 Procitovano 12 listopada 2008 a href wiki D0 A8 D0 B0 D0 B1 D0 BB D0 BE D0 BD Cite web title Shablon Cite web cite web a Cite maye pusti nevidomi parametri description ta datepublished dovidka Endryu Ejzenberg Dzhim Melton SQLJ Chast 1 Arhiv originalu za 25 serpnya 2011 Procitovano 12 listopada 2008 a href wiki D0 A8 D0 B0 D0 B1 D0 BB D0 BE D0 BD Cite web title Shablon Cite web cite web a Cite maye pusti nevidomi parametri description ta datepublished dovidka IBM Redbooks DB2 for z OS and OS 390 Ready for Java Arhiv originalu za 25 serpnya 2011 Procitovano 12 listopada 2008 a href wiki D0 A8 D0 B0 D0 B1 D0 BB D0 BE D0 BD Cite web title Shablon Cite web cite web a Cite maye pusti nevidomi parametri description ta datepublished dovidka Oracle Database 11g SQLJ Developer s Guide and Reference Arhiv originalu za 25 serpnya 2011 Procitovano 12 listopada 2008 a href wiki D0 A8 D0 B0 D0 B1 D0 BB D0 BE D0 BD Cite web title Shablon Cite web cite web a Cite maye pusti nevidomi parametri description ta datepublished dovidka Zovnishni posilannyahttp sqlj org 4 sichnya 2014 u Wayback Machine IBM Redbook DB2 for z OS and OS 390 Ready for Java 18 travnya 2011 u Wayback Machine