[Содержание_документа] [Конец_документа]

[Выше] [Начало_этой_части] [Конец_этой_части] [Далее]

===========================================

Глава 8 - Встроенный SQL

 В этой главе обсуждаются следующие темы:

 Использование встроенного SQL в методах

 Использование макрокоманд во встроенном SQL

 Курсор (Cursor) и не-курсор (Non-Cursor) SQL

 Сохранение данных SQL-запроса

 Вставка и обновление данных в реляционных таблицах

 Расширения Cache для SQL

 Зарезервированные имена переменных

 Проверка статуса ошибки с помощью SQLCODE

Чтобы упростить процесс создания приложений для баз данных, Cache поддерживает встроенный SQL для методов и программ. Встроенный язык запросов дает возможность соединить высокоэффективную объектную технологию с гибкостью SQL.

Встроенный SQL позволяет использовать преимущества многих мощных расширений SQL. В рамках Cache ObjectScript можно:

 Исполнять комплексные запросы данных

 Сохранять результаты в переменных Cache ObjectScript

Эта глава описывает работу встроенного SQL в Cache ObjectScript. Предполагается, что читатель знаком с концепциями объектов Cache, языком Cache ObjectScript и стандартом ANSI SQL.

Использование встроенного SQL в методах

Использование встроенного SQL в методах и программах ограничено рамками функции препроцессора &sql (...). Например:

METHOD MethodName(methodargs)

{

CODE =

{

&sql(SELECT * FROM Table)

}

}

Используя синтаксис языка CDL, можно определить класс Patient со следующими атрибутами:

class Patient

{

DESCRIPTION = "Patient Info";

SUPER = %Persistent;

PERSISTENT;

ATTRIBUTE Name {TYPE = %String;}

ATTRIBUTE Number {TYPE = %Integer;}

ATTRIBUTE PIN {TYPE = %String;}

INDEX Keys {ATTRIBUTE = PIN;IDKEY;}

}

Тогда можно создать метод FindPatient класса, который содержит встроенный SQL, который находит пациента по имени и возвращает OREF объекта:

METHOD FindPatient(name:%String)

{

DESCRIPTION = "Finds a patient and returns its OREF";

RETURNTYPE = Patient;

CLASSMETHOD;

CODE =

{

NEW id,SQLCODE

&sql(SELECT ID

INTO :id

FROM Patient

WHERE Name = :name)

IF SQLCODE QUIT $$$NULLREF

QUIT ..%OpenId(id)

}

}

Примечание: $$$NULLREF устанавливает объектный дескриптор в пустое значение.

Точно так же можно определить метод ListPatients, содержащий встроенный SQL, который использует курсор для печати списка имен пациентов, номеров и PIN:

METHOD ListPatients()

{

DESCRIPTION = "Prints patient info";

CLASSMETHOD;

CODE =

{

NEW name,num,pin,SQLCODE

&sql(DECLARE PatCur CURSOR for

SELECT Name,Number,PIN INTO :name,:num,:pin

FROM Patient)

&sql(OPEN PatCur)

FOR &sql(FETCH PatCur) QUIT:SQLCODE

WRITE name," ",num," ",pin,!

&sql(CLOSE PatCur)

QUIT

}

}

Можно также создать метод Insert класса, который использует встроенный SQL для вставки новых записей в набор пациентов:

METHOD Insert(name:%String,num:%Integer,pin:%String)

{

CLASSMETHOD;

CODE =

{

NEW SQLCODE

&sql(INSERT INTO Patient (Name,Number,PIN)

VALUES (:name,:num,:pin))

QUIT

}

}

Как другая альтернатива, можно создать метод класса, использующий встроенный SQL для определения таблицы, используя Язык Описания Данных SQL (DDL – Data Definition Language):

METHOD DefineTable()

{

RETURNTYPE = "%Status";

CLASSMETHOD;

CODE =

{

NEW SQLCODE

&sql(CREATE TABLE NewTable(Name CHAR(30),

Title CHAR(30)))`

IF SQLCODE<0 QUIT $$$ERROR($$$SQLError,SQLCODE)

QUIT $$$OK

}

}

 

Форматы данных

Данные, найденные через запросы SQL, могут быть возвращены в любом из следующих форматов данных:

 Логический – (значение по умолчанию) возвращает внутренние значения полей без преобразования констант или переменных

 ODBC – значения преобразуются в форматы ODBC

 Дисплей – преобразование внутреннего формата к внешнему формату применяется к спискам выбора, но не к константам или переменным

Можно определить формат данных через макро-флажок #SQLCOMPILE препроцессора. Если используется встроенный SQL и объекты привязываются к переменным Cache ObjectScript, следует использовать логическую установку компилятора SQL. Эта директива компилятора определяет формат для данных, найденных через внедренный SQL. Например,

#sqlcompile select=logical

 Использование макрокоманд во встроенном SQL

Встроенный SQL может содержать макро-ссылки. Препроцессор макрокоманд Cache ObjectScript разворачивает макро-ссылки прежде, чем переводит их в текст SQL. Поэтому можно использовать макрокоманды, чтобы генерировать части текста SQL. Макро-препроцессор поддерживает три вида конструкций:

Конструкция

Символ

Описание

Команды Препроцессора

#

Выполнение команды препроцессора

Функции Препроцессора

## или &

Расширение до обозначенного кода

Макро-Ссылки

$$$

Обращение к предварительно определенной макрокоманде

Приводимый ниже пример показывает ряд макроопределений, сопровождаемых инструкцией SQL – ссылки на макрокоманду:

#define TABLE Patients

#define FIELDS Name,Phone

#define VARS :n,:p

#define COND Name %STARTSWITH "JO"

...

&sql(SELECT $$$FIELDS INTO $$$VARS

FROM $$$TABLE WHERE $$$COND)

Наоборот, можно использовать макро-ссылку, чтобы вставить функцию препроцессора &sql:

#define GETNEXT &sql(FETCH xcurs INTO :a,:y)

...

FOR i=1:1 $$$GETNEXT QUIT:SQLCODE=100 DO object.method()

При обработке последней строки, макро-препроцессор заменяет макро-ссылку $$$GETNEXT &sql(FETCH ...); тогда вместо встроенного выражения SQL будет следующий текст:

FOR i=1:1 &sql(FETCH xcurs INTO :a,:y) QUIT:SQLCODE=100 DO object.method()

Курсор Cursor) и не-курсор (Non-Cursor) SQL

Cache ObjectScript поддерживает два вида встроенных инструкций SQL:

  Не-курсор SQL

  Курсор SQL

Не-курсор SQL

Не-курсор SQL состоит из индивидуальных инструкций SELECT, INSERT, UPDATE и DELETE. Не-курсор встроенная инструкция запроса SQL всегда возвращает одиночную строку данных. Эти запросы возвращают первую строку, которая удовлетворяет критериям SELECT. Например:

&sql(SELECT Name FROM Person INTO :name)

копирует значение поля Name в переменную name из первой строки, найденной в таблице.

Курсор SQL

Курсор SQL позволяет отыскивать множественные строки в наборе результатов запроса. При использовании курсора необходимо выполнить следующую последовательность задач:

  Объявить курсор

  Открыть курсор

  Выбрать данные из курсора

  Закрыть курсор

Действия курсора подобно указателю – он сосредотачивается на доступе и обработке сначала одной строки, затем перемещается от этой строки к следующей в последовательности строк.

Объявление курсора

Чтобы объявить курсор, используется инструкция SQL DECLARE. Инструкция DECLARE содержит имя курсора и инструкцию SELECT, которая определяет курсор.

Имя курсора может состоять из любого числа алфавитно-цифровых символов; существенны только первые 29 символов, а первый символ должен быть алфавитным. Инструкция DECLARE для курсора должна предшествовать любым другим инструкциям, включающим этот курсор. Как только курсор объявлен, он может использовать одну или более инструкций OPEN, FETCH и CLOSE. Все операции курсора для данного имени курсора должны постоянно находится в одиночной программе Cache ObjectScript. Например,

&sql(DECLARE PatCur CURSOR FOR

SELECT Name,Telephone FROM Patients

WHERE Name="Boswell")

Пример объявляет курсор PatCur, который отыскивает имена и номера телефонов во всех строках в таблице Patients с именем Boswell. Инструкция DECLARE самостоятельно не выполняет никакой код.

Cache SQL расширяет поддерживаемую SQL инструкцию DECLARE с предложением INTO, чтобы связать результаты курсор-основанной выборки с локальными переменными.

Открытие курсора

Перед использованием курсора в программе его нужно открыть с помощью инструкции OPEN следующим образом:

&sql(OPEN PatCur)

Выбор данных из курсора

В запросе SQL можно использовать инструкцию FETCH с предложением INTO, чтобы отыскать результаты в переменных. Например,

&sql(FETCH PatCur INTO :name,:tel)

Выбирает следующую строку, как выбрано инструкцией DECLARE курсора, в переменных name и tel.

Используя собственное предложение INTO, каждая инструкция FETCH может читать один и тот же курсор в различные наборы переменных.

Закрытие курсора

Когда завершено использование курсора в программе, его следует закрыть следующим образом:

&sql(CLOSE PatCur)

Сохранение данных SQL-запроса

 Встроенные инструкции SQL могут сохранять данные в переменных и массивах Cache ObjectScript. Однако, Cache ObjectScript не поддерживает объектный синтаксис во встроенном SQL. Поэтому следует связать объектные свойства с SQL, используя переменные Cache ObjectScript.

Сначала нужно сохранить данные запроса SQL в локальных переменных. Затем следует установить объектные свойства в локальные переменные.

Сохранение данных SQL-запроса в локальных переменных

Чтобы сохранить данные запроса SQL в переменных Cache ObjectScript, используется предложение INTO. В курсор-основанном SQL разработчик определяет предложение INTO как часть инструкции DECLARE для курсора. Например,

&sql(DECLARE state CURSOR for

SELECT Name,Abbreviation,Capitol

INTO :name,:abbr,:capitol

FROM state)

...

&sql(FETCH state)

В этом примере инструкция FETCH сохраняет значения в переменных name, abbr и capitol. Можно также определить предложение INTO как часть каждой инструкции FETCH, использующей курсор:

&sql(DECLARE state CURSOR FOR

SELECT Name,Abbreviation,Capital

FROM state)

...

&sql(FETCH state INTO :name,:abbr,:capital)

Используя собственное предложение INTO, каждая инструкция FETCH может читать один и тот же курсор в различные наборы переменных.

Следует обратить внимание, что INTO может только сохранять данные в локальных переменных, но не объектные свойствах. Это означает, что данные хранятся в локальной переменной; для сохранения значения нужно установить объектное свойство непосредственно в локальную переменную:

set state.Name=name

Сохранение данных SQL-запроса в локальных массивах

Можно также сохранять результаты запроса SQL в узле переменной (в массиве) Cache ObjectScript. Cache SQL позволяет предложению INTO в инструкции SELECT сохранять значения из одиночной таблицы в массиве.

Чтобы сделать это, предложение INTO сохраняет значения в узле переменной Cache ObjectScript, у которой последний индекс Cache ObjectScript неопределен. Например,

INTO :a("Emp",)

помещает каждое найденное значение поля в элемент массива:

a("Emp",col)

где col – столбцы поля как определено модификатором свойства CDL sqlcolumnnumber, как описано в следующем разделе.

Если выполняется запрос:

&sql(SELECT *

INTO :emp()

FROM Employee

WHERE Name = "Smith")

для следующей таблицы Employee:

Столбец #

Имя

1

Employee (поле ID)

2

Name

3

Address (многострочный)

4

Department

то поле Employee читается в emp(1), поле Name – в emp(2), и так далее.

Так как Address – это поле списка, данные сохраняются в узеле emp(3) в формате строки $List или $Piece. Если разделитель не определен, используется формат $List; если разделитель определен, используется формат $Piece.

Если формат $List:

emp(3)=$LISTBUILD(instance1,instance2,...instanceN)

Если формат $Piece:

emp(3)=instance1^instance2^...^instanceN)

где ^ – разделитель списка SQL.

Вставка и обновление данных в реляционных таблицах

Как правило, запросы INSERT используют следующий синтаксис:

INSERT INTO <tablename> (<fieldname>,<fieldname>,...)

VALUES (...,...)

Запросы UPDATE используют следующий синтаксис:

UPDATE <tablename> (<fieldname>,<fieldname>,...)

VALUES (...,...)

В этих инструкциях элементы в предложении VALUES последовательно соответствуют полям, указанныv после имени таблицы.

Cache SQL позволяет запросам INSERT и UPDATE использовать любой синтаксис без требования явного определения списка имен полей после имени таблицы.

Примечание: Если имеется только один элемент значения, указанный в предложении VALUES, нельзя элемент заключать в круглые скобки.

Чтобы не выполнять определение списка имен поля после имени таблицы, запрос должен удовлетворять следующим двум критериям:

 Число значений, указанных в предложении VALUES, – такое же, как число полей в таблице, исключая поле RowID и любой скрытый (частный атрибут) поля.

 Значения в предложении VALUES перечислены в порядке внутренних номеров столбца полей.

Например, запрос

INSERT INTO tabl1 VALUES (5,"John")

эквивалентен запросу

INSERT INTO tabl1 (age,name) VALUES (5,"John")

если таблица "tabl1" имеет только два поля данных.

В этом примере, значение 5 назначено для поля с более низким номером столбца, а значение John назначено для другого поля.

Вставка и обновление с использованием переменных

Можно устанавливать значение переменной и затем обновлять реляционную базу Cache, используя следующий синтаксис:

Set sname="Montana”

&sql(INSERT INTO State VALUES :sname)

Это допустимо для локальных переменных, объектных свойств и любых других переменных.

Примечание: Переменные типа sname не используют точечный синтаксис.

Вставка и обновление с использованием массивов

Cache SQL позволяет использовать переменную ссылку с неопределенным последним нижним индексом, чтобы передать массив значений запросам INSERT или UPDATE встроенного SQL. Например, встроенный SQL-запрос:

&sql(INSERT INTO Employee VALUES :emp("profile",))

устанавливает каждое поле во вставленной строке Employee в:

emp("profile",col)

где col – номер столбца поля в таблице Employee, как определено в Словаре Классов (Class Dictionary).

Следует обратить внимание, что, если используется ссылка на массив, Cache SQL не требует списка имен полей после имени таблицы. Присутствие и отсутствие элементов массива определяют поля, в которые запрос вставляет значения. Это дает возможность по содержанию массива определять поля, которые получают значения вставки.

Это означает что инструкция Cache SQL:

INSERT INTO Employee VALUES :emp("profile",)

является эквивалентной инструкции SQL стандарта ANSI:

INSERT INTO Employee (Name,Telephone) VALUES (:name,:tel)

Расширения Cache для SQL

В Cache ObjectScript имеется ряд полезных расширений стандарта ANSI SQL DML (DML (Data Manipulation Language) – Язык Манипуляций Данными). Эти расширения помогают интегрировать SQL с Cache ObjectScript и относятся к ряду категорий:

 Операторы Cache ObjectScript

 Списковые поля (List Fields)

 Объединения (Joins)

 Ссылки

 Зависимые отношения

Операторы Cache ObjectScript

В Cache имеются расширения SQL для некоторых операторов Cache ObjectScript. Это увеличивает выразительную мощь SQL и помогает лучше интегрировать эти два языка.

Символы, показанные в следующей таблице, представляют расширения Cache для SQL:

Символ

Описание

=*

Одностороннее внешнее объединение

->

Неявное объединение (ссылка)

_ #

Скалярные операторы Cache ObjectScript

? [

Операторы сравнения Cache ObjectScript

& !

Операторы И и ИЛИ Cache ObjectScript

[

Опрератор СОДЕРЖИТСЯ Cache ObjectScript

]

Оператор СЛЕДУЕТ Cache ObjectScript

Cache SQL разрешает использование двойных кавычек ("..."), чтобы разграничивать литеральные значения, в дополнение к символу апострофа ("..."), используемого ANSI-Стандартом SQL.

Можно использовать префиксы "не" и "НЕ" для отрицания сравнения и логических операторов. Например,

не= (эквивалентно <>)

не< (эквивалентно >=)

не> (эквивалентно <=)

Примечание: Конструкции "! = " и " НЕ = " эквивалентны.

Списковые поля (List Fields)

Cache SQL расширяет реляционную модель базы данных, разрешая создание многозадачных полей, называемых полями списка Cache ObjectScript. Такие поля полезны для сохранения информации об одиночном объекте, который содержит несколько частей данных. Типично поле списка могло бы содержать адрес или блок текста комментария.

Поле cписка ищется как одиночная строка данных в преобразованном в последовательную форму формате. Она может быть сохранена в одном из двух форматов:

 Формат $LIST – формат, определенный функцией $LIST Cache ObjectScript (значение по умолчанию)

 Разграниченная строка – формат, в котором список является простой строкой c разделителем, указанным в определении поля. Если разделитель не определен, поля списка сохранены в формате $LIST.

Cache SQL позволяет использовать поля списка и в запросах SELECT, INSERT и UPDATE.

Использование списковых полей в запросах SELECT

В запросе SELECT можно ссылаться на поля списка в инструкции SELECT, используя предложение INTO. Оно (предложение) выполняет копирование содержимого поля в переменную. Когда предложение INTO копирует поле списка в переменную, создается переменная, представляющая собой одиночную строку данных в преобразованном в последовательную форму формате.

Например, если поле Patient.Adress для строки 758 содержит части данных:

426 Sunday

DriveApt. 12C

Roberta, CA 90126

то следующий встроенный запрос размещает значения списка в addr как одну строку данных:

&sql(SELECT Address INTO :addr

FROM Patient

WHERE Patient = 758)

Если нужно определить одну часть поля списка из addr, следует использовать функцию $LIST. Для разграниченных строк нужно использовать функцию $PIECE.

Объединения (Joins)

Cache SQL расширяет стандартный SQL включением двух дополнительных типов объединений:

 Односторонние внешние объединения (One-Way Outer Joins)

 Неявные объединения (Implicit Joins)

Односторонние внешние объединения (One-Way Outer Joins)

В стандартных внутренних объединениях строки одной таблицы связаны со строками второй таблицы, и строка в первой таблице, которая не находит никакой соответствующей строки во второй таблице, исключается из таблицы вывода.

В односторонних внешних объединениях все строки из первой таблицы включаются в таблицу вывода, даже если не имеется никакого соответствия ей во второй таблице. Первая таблица перемещает уместную информацию из второй таблицы, но никогда не жертвует своими собственными строками из-за отсутствия соответствия во второй таблице.

При определении одностороннего внешнего объединения, порядок, в котором вызываются таблицы в предложении FROM, очень важен. Первая определяемая таблица – исходная таблица для объединения. Определить внешнее объединение можно, используя символ = * на месте = в предложении WHERE запроса SQL.

Например, таблица Suppliers определена как исходная таблица для односторонней внешней операции объединения (= *) с таблицей Parts, где поле SCity соответствует полю Pcity:

SELECT SName,PName,SCity

FROM Suppliers,Parts

WHERE Suppliers.SCity=*Parts.PCity

Предложение SELECT определяет поля, которые будут включены в проецируемую таблицу. Таблица Cartesian Product получена из таблиц, названных в предложении FROM вышеупомянутой инструкции SQL, и объединяет таблицы Suppliers и Parts. Предложение WHERE в вышеупомянутой инструкции (Suppliers.SCity =*Parts. PCity) определяет одностороннее внешнее условие объединения.

Этот запрос возвращает все строки от таблицы источника Suppliers, также как любых строк из таблицы Parts, где поле SCity соответствует полю PCity.

Неявные объединения (Implicit Joins)

Cache SQL поддерживает два типа неявных объединений - ссылки и зависимые отношения:

 Ссылка – это связь между двумя независимыми таблицами. Например, чтобы не помещать в каждую запись о посещении каждым пациентом врача детальной первичной информации о враче, можно создать две таблицы, Patient (Пациент) и Doctor (Доктор), и установить ссылку между записью о посещении каждым пациентом врача и соответствующей информацией о враче из таблицы Doctor. У многих пациентов есть запись о посещении одного и того же доктора. Таблицы Patient и Doctor независимы: можно иметь запись о посещении без указания доктора; также можно сделать так, чтобы доктор делал запись без указания соответствующей информации о пациентах.

 Зависимые отношения – связь между двумя таблицами, родителем и ребенком. Дочерняя (порожденная) таблица зависима от родительской таблицы. Например, вместо того, чтобы помещать все счета в запись о заказчике, можно создать две таблицы, Заказчик (родитель) и Счет (ребенок), и установить зависимые отношения между записью о каждом заказчике и его соответствующими счетами. Эти таблицы зависимы: можно сделать запись о заказчике без указания счетов, но не возможно иметь счет без соответствующего заказчика.

Ссылки

Ссылка – связь "многие к одному" между таблицами. Ссылка, как считают, не зависимая связь, потому что строки в ссылающейся таблице существуют независимо от строк в таблице, на которую делается ссылка. В Cache SQL таблица, на которую производится ссылка, имеет указатель на ссылающуюся таблицу. В Cache поле, которое определяет другую таблицу, называется полем ссылки.

Чтобы определить ссылку, можно в определении запроса использовать неявный синтаксис объединения Cache SQL.

Например, если поле A.b определяет таблицу B, и x – поле в таблице B, ссылка

A.b->x

Указывает на значение x в строке таблицы B передающий к A.b. Это интерпретируется как ссылка к B.x с B, добавленным неявно к предложению FROM и дополнительному внешнему условию объединения, добавленному неявно к предложению WHERE.

Следующий запрос отыскивает имя пациента и имя доктора для каждого пациента, живущего в Бостоне:

SELECT Patient.Pname, Patient.Doctor->Dname

FROM Patient

WHERE Patient.City = "Boston"

Предположение Patient.Doctor – ссылка к таблице Doctor, вышеупомянутый запрос эквивалентен такому:

SELECT Patient.Pname,Doctor.Dname

FROM Patient,Doctor

WHERE Patient.City = "Boston"

AND Patient.Doctor = *Doctor.ID

 Зависимые отношения

Зависимые отношения – связь между таблицами, в которых строки в одной таблице (дочерняя (порожденная) таблица) не могут существовать без строк в другой таблице (родительская таблица), так, что родительские строки имеют отношения "один ко многим" с дочерними (порожденными) строками. Дочерняя (порожденная) таблица всегда определяет ее родительскую таблицу. По этой причине, о зависимых отношениях можно думать как, о своего рода, ссылках. Однако, зависимые отношения более ограничены, чем ссылки, так как условие объединения определяет, что все строки дочерней (порожденной) таблицы должны определять ту же самую родительскую строку таблицы. Таким образом, зависимые отношения удовлетворяют реляционному определению внутреннего объединения.

В объектах Cache отношения родитель/ребенок называются идентифицирующими отношениями и определены параметром класса IDENTIFIEDBY.

Например, язык CDL создает зависимые отношения между родительской таблицей Invoice и дочерней (порожденной) таблицей InvoiceLine:

CLASS Invoice

{

SUPER = %Persistent;

ATTRIBUTE InvoiceNumber {TYPE = %String;}

INDEX MyKey {attribute = InvoiceNumber;IDKEY;}

...

}

CLASS InvoiceLine

{

PARAMETER IDENTIFIEDBY {DEFAULT = "InvoiceParent";}

SUPER = %Persistent;

ATTRIBUTE InvoiceParent {TYPE = Invoice;}

...

}

Получаются две таблицы в SQL: Invoice и InvoiceLine. RowID в Invoice называется ID (Идентификатор) (если поле не было переименовано, используя модификатор класса SQLROWIDNAME) и основаны на InvoiceNumber. InvoiceLine - ребенок Invoice, а его RowID называется InvoiceLine. RowID InvoiceLine основан на InvoiceParent и автоматически сгенерированном столбце childsub. Если с SQL используется %CacheSQLStorage или %CustomStorage, нужно создать собственное поле childsub и сформировать индекс idkey, который использует поле.

Имеются два типа зависимых отношений: Child-Parent (Ребенок-Родитель) и Parent-Child (Родитель-Ребенок). Обозначения зависимых отношений в Cache SQL используют неявный синтаксис объединения.

Отношения Ребенок-Родитель (Child-Parent)

Если P – ссылка к родителю C, а x – поле в P, неявный синтаксис объединения:

C.P->x

для данной строки указывает на значение поля x в родительской строке этой строки. Это интерпретируется как ссылка к P.x с P, добавленная неявно к предложению FROM, и дополнительное внешнее условие объединения, добавленное неявно к предложению WHERE.

Например, учитывая родительскую таблицу Customer и дочернюю (порожденную) таблицу Invoice, следующий запрос:

SELECT Invoice.Customer->Name

FROM Invoice

WHERE Invoice.Number = 51140

будет эквивалентен такому:

SELECT Customer.Name

FROM Invoice,Customer

WHERE Invoice.Number = 51140

AND Invoice.Customer = Customer.ID

Отношения Родитель-Ребенок (Parent-Child)

Если P – ссылка к родителю C, а x – поле в C, неявный синтаксис объединения:

P.C->x

для данной строки P указывает на значение поля x в дочерней (порожденной) строке этой родительской строки. Это интерпретируется как ссылка к C.x с C, добавленная неявно к предложению FROM, и дополнительное внешнее условие объединения, добавленное неявно к предложению WHERE.

Например, учитывая родительскую таблицу Customer и дочернюю (порожденную) таблицу Invoice, следующий запрос всех счетов всех заказчиков (customer) по имени Smith:

SELECT Customer.Invoice->Number

FROM Customer

WHERE Customer.Name = "Smith"

будет эквивалентен такому:

SELECT Invoice.Number

FROM Customer,Invoice

WHERE Customer.Name = "Smith"

AND Customer.ID = Invoice.Customer

Зарезервированные имена переменных

Все локальные переменные, используемые Cache SQL, начинаются со знака процента (%) и имеют все имена нижнего регистра. Intersystems настоятельно советует не использовать определяемых пользователем переменных, которые начинаются со знака %.

Примечание: Ключевые слова Cache расширяют зарезервированные слова стандарта SQL 1992, также начинающиеся со знака процента (%). Как правило, они пишутся прописными буквами.

Когда Cache генерирует промежуточный код для метода, который содержит встроенный SQL, то автоматически генерируются имена переменных. Не-курсор имена переменных в инструкциях SQL начинаются с %mmmsql. Для курсор-основанных инструкций SQL (предполагается, что операции выполнены на курсоре по имени "PatCur") все сгенерированные имена переменных начинаются с %PatCur или %mmmsql.

Чтобы избежать конфликта со сгенерированными именами переменных, методы, содержащие встроенный код SQL, не должны иметь переменных с именами, начинающимися с %mmmsql. Имена переменных также не должны начинаться с любого имени курсора, которое появляется в программе.

Проверка статуса ошибки с помощью SQLCODE

Всякий раз, когда запускается инструкция SQL, в переменную SQLCODE Cache ObjectScript возвращается числовой код состояния. Этот код состояния может быть:

Успех

SQLCODE=0

Успешное завершение

SQLCODE=100

Успешно, но нет строк (или нет больше строк), удовлетворяющих запросу

Ошибка

SQLCODE < 0

 

Список ошибок приводится в Cache Error Message Reference.

===========================================

[Содержание_документа] [Конец_документа]

[Выше] [Начало_этой_части] [Конец_этой_части] [Далее]

===========================================

По вопросам поддержки любых продуктов InterSystems Corporation обращайтесь:

Россия 121019, Москва, Волхонка, 6, #14

Тел.: +7 095 203-4649

Факс: +7 095 956-8268

info@intsys.dol.ru

http://www.intersystems.ru

 

Copyright © 1999, InterSystems Corporation. Все права защищены.