13.3. Описание API SQL

13.3.1. SQLList()

SQLList() --> aAvailableDrivers

13.3.2. ConnectNew()

ConnectNew(<cRDBMS>,[<RDBMS specific>,...],[<cCharset>],[<cIsolation>])
	--> TConnect object

13.3.2.1. Параметры

<cRDBMS>

идентификатор СУБД; см. информацию о специфике использования конкретной СУБД

<RDBMS specific>

несколько специфичных для используемой СУБД параметров; см. информацию о специфике использования конкретной СУБД

<cCharset>

(9-й параметр) кодировка, используемая сервером

<cIsolation>

(10-й параметр) уровень изоляции по умолчанию; см. информацию о специфике использования конкретной СУБД

13.3.2.3. Описание

ConnectNew() подключается к серверу, создает и возвращает объект класса TConnect. Этот объект может использоваться для старта/завершения транзакций, выполнения операторов SQL и для получения наборов записей - результата оператора SELECT.

Дополнительный параметр <cCharset> используется в случаях, когда кодировки сервера и клиента не совпадают. Все перекодировки строк, получаемых с сервера и передаваемых обратно производятся автоматически. Если этот параметр не передан используется SET("SQL_CHARSET"). Обратите внимание, что изменение SET("SQL_CHARSET") после подключения к серверу не имеет эффекта для этого подключения.

Если дополнительный параметр <cIsolation> не передан, используется соответствующая переменная SET, например SET("OR_ISOLATION_LEVEL") для Oracle. Если такой переменной SET нет, используется SET("SQL_ISOLATION_LEVEL").

Замечание

Вместо уровня изоляции по умолчанию может быть использоваться другой, определяемый соответствующим параметром функции TConnect:Start(). Изменение значения соответствующей переменной SET после того как подключение произведено не влияет на умалчиваемый уровень изоляции этого подключения.

Когда приложению больше не требуется SQL сервер, оно должно отключиться от сервера и освободить занимаемые подключением ресурсы при помощи вызова функции-деструктора TConnect:Destroy().

13.3.3. Класс TConnect

Ниже перечислены конструктор и методы класса TConnect:

13.3.3.1. TConnect:Command()

Command(<cSQL>,[<aParameters>]) --> nAffectedRows

13.3.3.1.1. Параметры

<cSQL>

строка содержащая оператор SQL для выполнения

<aParameters>

двухмерный массив с параметрами SQL, по одной строке на параметр. Каждая строка должна содержать как минимум два элемента. В первом - имя параметра, во втором - его значение. Третий элемент используется только с Oracle (обязателен), и содержит числовое значение - идентификатор типа данных Oracle. Дополнительный четвертый элемент служит для индикации бинарного значения; если .T. перекодировки не производятся

13.3.3.1.3. Описание

Command() используется для выполнения операторов SQL,кроме запросов SELECT (в т.ч. операторов, возвращающих результирующие строки). Для выполнения запроса, возвращающего строки, используйте TConnect:CreateRowset() даже если вы не заинтересованы в получении результатов.

Оператор SQL может получать параметры. Имени параметра в <cSQL> должен предшествовать символ ':'. Значения параметров передаются в двухмерном массиве <aParameters>.

Если нет активной транзакции, изменения, сделанные оператором <cSQL> коммитятся (вступают в силу) сразу. Если нужно другое поведение вызывайте TConnect:Start() явно.

Возвращаемое значение - количество затронутых записей, например количество удаленных записей в случае оператора DELETE.

13.3.3.4. TConnect:CreateRowset()

CreateRowset(;
	<cSelectSQL>,;
	[<aParameters>],;
	[<cInsertSQL>],;
	[<cDeleteSQL>],;
	[<cUpdateSQL>],;
	[<cRefreshSQL>],;
	[<cIdName>],;
	[<aOrders>],;
	[<cGenIdSQL>],;
	[<lNoFetch>],;
	[<bEval>],;
	[<nEvery>];
) --> TRowset object

13.3.3.4.1. Параметры

<cSelectSQL>

строка содержащая SQL запрос, который следует выполнить

<aParameters>

двухмерный массив с параметрами SQL, по одной строке на параметр. Каждая строка должна содержать как минимум два элемента. В первом - имя параметра, во втором - его значение. Третий элемент используется только с Oracle (обязателен), и содержит числовое значение - идентификатор типа данных Oracle. Дополнительный четвертый элемент служит для индикации бинарного значения; если .T. перекодировки не производятся. Переданные параметры могут использоваться в SQL операторах, описываемых ниже

<cInsertSQL>

оператор SQL, который следует выполнить при добавлении новой строки к набору

<cDeleteSQL>

оператор SQL, который следует выполнить при удалении строки из набора

<cUpdateSQL>

оператор SQL, который следует выполнить при изменении строки набора

<cRefreshSQL>

запрос SQL, который следует выполнить для обновления текущей строки набора

<cIdName>

имя поля-идентификатора (только для Interbase, ODBC и DBTCP)

<aOrders>

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

<cGenIdSQL>

оператор SQL для получения нового уникального значения поля-идентификатора, используемое в дальнейшем с оператором <cInsertSQL> (только для Interbase)

<lNoFetch>

логическое значение определяющее режим загрузки записей. Если передано .F. все записи загружаются сразу, если .T. - записи загружаются позже (по требованию). По умолчанию - .F.

<bEval>

блок кода, выполняемый в процессе загрузки записей. Этот блок кода получает параметр - объект TRowset. Если блок кода возвращает .F. процесс загрузки прекращается досрочно. В режиме 'загрузка по требованию' (когда <lNoFetch> - .T.) этот параметр игнорируется

<nEvery>

определяет количество загруженных записей между между выполнениями <bEval> (если передан). По умолчанию - 1, то есть <bEval> выполняется после каждой загруженной записи

13.3.3.4.3. Описание

CreateRowset() выполняет запрос SELECT, строит локальный набор результирующих записей и возвращает объект TRowset. То есть эту функцию можно рассматривать как конструктор класса TRowset. 'Запрос SELECT' означает любой оператор SQL, возвращающий результирующие записи (или пустой набор записей). Использование оператора SQL любого другого вида приведет к ошибке.

<cInsertSQL>, <cDeleteSQL>, <cUpdateSQL> - дополнительные параметры, предназначенные для облегчения модификации таблиц базы данных. Если не переданы, соответствующие изменения набора записей не отражаются в базе данных. <cInsertSQL> выполняется автоматически методом TRowset:Append(). Таким же образом, <cDeleteSQL> выполняется методом TRowset:Delete(), а <cUpdateSQL> - методом TRowset:Write().

<cRefreshSQL> выполняется автоматически методом TRowset:RefreshCurrent(). <cRefreshSQL> должен запрашивать точно такой же список полей, что и <cSelectSQL>.

Редактируемый набор записей должен содержать поле - идентификатор записи с уникальными значениями, используемый для связывания записей таблицы базы данных и строк набора. Необходимо явно включать это поле в список запрашиваемых полей запроса SELECT. Для различных СУБД существуют различные подходы к реализации механизма связывания записей таблицы и строк набора.

  • Некоторые СУБД имеют 'скрытые' поля - идентификаторы записей для каждой хранимой таблицы (ROWID в Oracle, OID в PostgreSQL). Эти поля создаются неявно, даже если вы не включали его описания в список полей оператора CREATE TABLE. PostgreSQL понимает такой синтаксис:

    SELECT oid,* FROM mytable

    В отличие от PostgreSQL, Oracle не понимает такого синтаксиса. Необходимо перечислить все запрашиваемые поля:

    SELECT rowid,fname,lname FROM mytable
  • Некоторые СУБД предоставляют возможность использования автоинкрементных полей с уникальными значениями. Синтаксис оператора CREATE TABLE вMySQL позволяет использовать предложение AUTO_INCREMENT в определении поля. CLIP распознает такие поля и использует их в качестве идентификаторов записей. Никаких других действий кроме включения поля AUTO_INCREMENT в таблицу, которую предполагается редактировать при помощи методов класса TRowset, не требуется.

  • Некоторые СУБД (Interbase) предоставляют механизм триггеров и генераторы уникальных значений. Типичный подход в этом случае - создать триггер BEFORE INSERT, который получает уникальное значение от генератора и присваивает его полю - идентификатору записи. Но не существует способа определить значение поля - идентификатора записи вновь вставленной записи. То есть невозможно изменить или удалить (при помощи операторов UPDATE и DELETE) вновь вставленную запись (добавленную после того как был создан объект TRowset). Есть два выбора:

    1. оформлять приложение с учетом этого ограничения (никогда не изменять вновь вставленные записи);

    2. не использовать триггер BEFORE INSERT, а передавать конструктору TRowset параметр <cGenIdSQL> с запросом к генератору уникальных значений. Этот оператор должен возвращать новое уникальное значение, которое будет затем присвоено полю с именем <cIdName> во время выполнения оператора <cInsertSQL>.

    Замечание

    Атрибут таблиц Interbase под названием RDB$DB_KEY в действительности не является идентификатором записи, а скорее адресом записи, которое может меняться (как RECNO(), значение которого может измениться после PACK). Поэтому этот атрибут не используется в качестве идентификатора записей.

  • В случае использования СУБД не предоставляющих никаких из вышеперечисленных возможностей (ODBC,DBTCP), необходимо передавать параметр <cIdName> с именем поля - идентификатора записи и оформлять ваши приложения таким образом, чтобы никогда не изменялись вновь вставленные записи.

Операторы SQL <cInsertSQL>, <cDeleteSQL>, <cUpdateSQL> и <cRefreshSQL> получают значения полей через параметры SQL с именами совпадающими с именами полей набора. Например:

<cSelectSQL>  - SELECT DriverID AS id,fname,lname FROM mytable
<cInsertSQL>  - INSERT INTO mytable (fname,lname) VALUES (:fname,:lname)
<cUpdateSQL>  - UPDATE mytable SET fname=:fname,lname=:lname WHERE DriverId=:id
<cDeleteSQL>  - DELETE FROM mytable WHERE DriverId=:id
<cRefreshSQL> - SELECT DriverID,fname,lname FROM mytable WHERE DriverId=:id

Имеется три макроса: %FIELDS, %VALUES для использования в операторе INSERT; %LIST для использования в операторе UPDATE. %FIELDS преобразуется в список имен полей; %VALUES - в список параметров; %LIST - в список полей и параметров. Например:

INSERT INTO mytable (%FIELDS) VALUES (%VALUES)
UPDATE mytable SET %LIST

Имеется два режима загрузки записей, управляемые параметром <lNoFetch>: полная загрузка и загрузка по требованию.

  • В первом режиме (<lNoFetch>==.F.) все результирующие записи загружаются до завершения CreateRowset(). В этом режиме можно сразу использовать TRowset:Lastrec() для определения количества результирующих записей. Можно использовать <bEval> для наблюдения и прерывания процесса загрузки.

  • Во втором режиме (<lNoFetch>==.T.) записи загружаются по требованию (в процессе навигации по набору). Этот режим гораздо быстрее, но Lastrec() возвращает рельное количество результирующих записей только после того как загрузятся все записи. В этом режиме параметр <bEval> игнорируется.

Когда приложению больше не требуется набор строк, оно должно освободить занимаемые ресурсы при помощи вызова метода-деструктора TRowset:Destroy().

13.3.3.4.4. Примеры

13.3.4. Класс TRowset

Ниже перечислены конструктор и методы класса TRowset:

TConnect:CreateRowset()Конструктор TRowset
  
TRowset:Append()добавление новой строки в набор
TRowset:Bof()определение достижения начала набора
TRowset:Browse()просмотр набора строк в окне
TRowset:CreateOrder()создание нового локального индекса
TRowset:Delete()удаление строки из набора
TRowset:Destroy()уничтожение объекта TRowset
TRowset:Eof()определение достижения конца набора
TRowset:FetchAll()дозагрузка оставшихся записей
TRowset:Fetched()определение количества загруженных строк
TRowset:FieldBinary()определение, является ли поле бинарным
TRowset:FieldBlock()создание блока кода для доступа к заданному полю набора
TRowset:FieldDec()определение количества знаков после запятой для заданного поля
TRowset:FieldLen()определение длины заданного поля
TRowset:FieldName()определение имени поля по заданной позиции
TRowset:FieldNo()определение позиции поля с заданным именем
TRowset:FieldNullable()определение, может ли поле принимать значения NULL
TRowset:FieldType()определение типа данных поля
TRowset:FieldTypeSQL()определение типа данных поля (в терминах используемой СУБД)
TRowset:FieldUnsigned()определение, является ли поле беззнаковым
TRowset:GetValue()получение значения поля в текущей строке
TRowset:GoBottom()перемещение к последней логической строке
TRowset:Goto()перемещение к заданной строке
TRowset:GoTop()перемещение к первой логической строке
TRowset:KeyNo()определение логического номера текущей строки
TRowset:Lastrec()определение количества строк в наборе
TRowset:NFields()определение количества полей в наборе
TRowset:Read()чтение текущей строки
TRowset:Recno()определение номера текущей строки
TRowset:RefreshAll()обновление набора путем повторного выполнения запроса SELECT
TRowset:RefreshCurrent()обновление текущей строки путем выполнения <cRefreshSQL>
TRowset:Seek()поиск строки с заданным значением ключа
TRowset:SetOrder()установка логического порядка записей
TRowset:SetValue()присвоение значения полю текущей строки
TRowset:Skip()перемещение относительно текущей записи
TRowset:Write()запись текущей строки

13.3.4.4. TRowset:CreateOrder()

CreateOrder(<cOrderName>,<cFieldName>|<bExpression>,[<nKeyLength>]) --> NIL

13.3.4.4.2. Описание

CreateOrder() используется для создания локального индекса, то есть индекса в памяти, управляющего логическим порядком строк в наборе. Созданный индекс может затем быть установлен управляющим при помощи метода TRowset:SetOrder(). Кроме того, управляющий индекс может использоваться для быстрого поиска строки, содержащей заданный ключ при помощи метода TRowset:Seek() function.

Если набор был создан в режиме 'загрузка по требованию' (<lNoFetch>==.T.), то предварительно дозагружаются все оставшиеся записи.

13.3.4.5. TRowset:Delete()

Delete() --> NIL

13.3.4.5.1. Описание

Delete() удаляет текущую строку из набора.

Если конструктору набора был передан параметр <cDeleteSQL>, последний выполняется на SQL сервере со значением поля - идентификатора текущей записи.

Если набор был создан в режиме 'загрузка по требованию' (<lNoFetch>==.T.), то предварительно дозагружаются все оставшиеся записи.

Delete() уменьшает количество строк в наборе, возвращаемое методом TRowset:Lastrec().

Если нет управляющего индекса позиция указателя текущей строки не изменяется, или перемещается к последней строке (когда удаляется последняя физическая строка (Recno()==Lastrec()).

Если есть управляющий индекс (установленный методом TRowset:SetOrder()) указатель текущей строки перемещается к следующей логической строке, или перемещается к последней логической строке (когда удаляется строка с наибольшим значением ключа).

Если удаляется последняя оставшаяся строка, состояния Bof() и Eof() устанавливаются в .T. и TRowset:Recno() возвращает 0.

13.3.4.7. TRowset:Eof()

Eof() --> lBoundary

13.3.4.7.2. Описание

Eof() используется для проверки условия достижения границ набора при перемещении указателя в прямом направлении при помощи метода TRowset:Skip().

После того, как функцией Eof() будет установлено значение .T., оно остается до тех пор, пока не будет сделана очередная попытка передвижения указателя записи.

TRowset:Skip() является единственной функцией, которая может установить значение Eof() == .T.

Замечание

В отличие от команды SKIP, использеумой в XBase, TRowset:Skip() никогда не перемещает указатель за последнюю логическую строку. Когда TRowset:Eof() возвращает .T. указатель находится на последней логической строке, а не на Lastrec()+1.

13.3.4.25. TRowset:Lastrec()

Lastrec() --> nLastrec

13.3.4.25.2. Описание

Lastrec() возвращает количество строк в наборе.

Если набор был создан в режиме 'загрузка по требованию' (параметр <lNoFetch> конструктора TConnect:CreateRowset() - .T.), Lastrec() может возвращать 0 (когда загружены не все записи). Количество загруженных строк можно определить с помощью метода TRowset:Fetched(). Для дозагрузки оставшихся записей можно использовать метод TRowset:FetchAll(). После этого Lastrec(), будет возвращать действительноеколичество строк в наборе.

13.3.4.31. TRowset:Seek()

Seek(<xKeyValue>,[<lSoft>]) --> lFound

13.3.4.31.3. Описание

Seek() ищет первую логическую строку с ключом, равным <xKeyValue>. Если такая строка найдена, она становится текущей и Seek() возвращает .T.; иначе возвращается .F. и указатель перемещается следующим образом: при нормальном (не относительным) поиске указатель перемещается к последней логической строке и TRowset:Eof() возвращает .T.; при относительном поиске указатель перемещается к первой строке, ключевое значение которой больше чем заданное. Если такой строки не существует, указатель перемещается к последней логической строке и TRowset:Eof() возвращает .T.

Если нет управляющего индекса (созданного при помощи метода TRowset:CreateOrder() и установленного управляющим при помощи метода TRowset:SetOrder()),Seek() ничего не делает.

13.3.4.33. TRowset:SetValue()

SetValue(<nFieldNo> | <cFieldName>, <xValue>) --> NIL

13.3.4.33.2. Описание

SetValue() присвает значение <xValue> заданному полю текущей строки.

Замечание

В отличие от метода TRowset:Write() SetValue() не инициирует немедленного отражения изменения на SQL сервере (выполнения оператора <cUpdateSQL>, переданного конструктору класса TRowset TConnect:CreateRowset()). Отражение производится при первом же вызове метода, перемещающего указатель.

13.3.4.34. TRowset:Skip()

Skip([<nRows>]) --> nRows