Kuzma's PHP Look

Home page: http://kuzma.russofile.ru
Оригинал на http://phplens.com/lens/adodb/docs-adodb.htm
Перевод Феськов Кузьма (kuzma@russofile.ru, http://kuzma.russofile.ru)

ADODB – русская документация (часть 3)

(c) 2002-2003 John Lim (jlim#natsoft.com)

(c) 2005 Feskov Kuzma (kuzma#russofile.ru)

Это программное обеспечение распространяется под двумя лицензиями: BSD-style и LGPL. Это означает, что вы можете использовать его в компилируемых и коммерческих продуктах.


Нужные ссылки: Скачать

Содержание

Рекомендации по созданию переносимого кода
      SELECT
            Способы выдачи результата
            Подсчет количества возвращаемых результатов
            Locking (блокирование, захват)
            Outer Joins (Внешнее присоединение)
      INSERT
      Binding (обвязка)
      Переносимый нативный SQL

Рекомендации по созданию переносимого кода

Если вы создаете приложение, которое может быть использовано в множестве операционных системах, то вам необходимо распланировать поддержку различных баз данных. Эта статья опирается на опыт работы со множеством баз данных в том числе и на компьютере Макинтош. В настоящее время я использую такие базы данных как: Oracle, FoxPro, Access, MS SQL Server и MySQL. Хотя большинство советов относится в пользователям SQL на Perl, Python и др. языках программирования, я сосредоточусь на использовании PHP и на том, какую помощь предлагает нам ADODB.

Большинство баз данных являются закрытыми. Самый лучший или быстрый способ сделать что-то – это использовать патентованные (платные) расширения SQL. Все это чрезвычайно затрудняет написание переносимого SQL, который бы хорошо работал при любых условиях. Когда ANSI комитет собрался в 1984 году, чтобы стандартизировать SQL, большинство производителей баз данных имели настолько различные способы обработки данных, что они смогли договориться только об основных функциональных возможностях SQL. Множество важных определений небыло стандартизировано. И даже после принятия ANSI-92 SQL, который стандартизировал гораздо больше, мы все еще должны осуществлять переносимость на уровне кода.

SELECT

Конструкция SELECT была стандартизована лучше других. Почти каждая база данных поддерживает следующее:

SELECT [cols] FROM [tables]
  [WHERE conditions]
  [GROUP BY cols]
  [HAVING conditions]
  [ORDER BY cols]

Но много полезных возможностей можно реализовать только через патентованные расширения. Для примера, используя SQL выведем только первые 10 записей:

База данных SQL синтаксис
DB2 select * from table fetch first 10 rows only
Informix select first 10 * from table
Microsoft SQL Server and Access select top 10 * from table
MySQL and PostgreSQL select * from table limit 10
Oracle 8i select * from (select * from table) where rownum <= 10

Эта возможности при получении данных настолько полезна, что в ADODB у нас есть функция SelectLimit(). Эта функция позволяет вам скрывать детали формирования запроса в пределах функции, которая напишет запрос за вас.

$connection->SelectLimit('select * from table', 10);

Способы выдачи результата

PHP позволяет вам получать данные SQL запросов в виде массива. Вы можете выбрать, каким образом массив будет проиндексирован: названием поля или числом. Однако разные драйверы баз данных противоречивы в способах индексации. ADODB позволяет вам четко определить способ индексации. Нужный вам формат вы можете определить в переменной $ADODB_FETCH_MODE указав ей в виде значения любую из констант: ADODB_FETCH_NUM (для числовой индексации), или ADODB_FETCH_ASSOC (для индексации по названию полей).

Значение поумолчанию определяется ADODB в зависимости от базы данных. Для точного определения – используйте описанные выше значения. ADODB_FETCH_NUM – для более быстрой работы, ADODB_FETCH_ASSOC – для удобства.


Подсчет количества возвращаемых результатов

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

В ADODB, функция RecordCount() возвращает число выбранных данных, или она будет эмулировать это число путем буферизации данных и их «ручному» пересчету, после того, как все запрошенные данные будут получены. Вы можете отключить эмуляцию по соображениям скорости при запросе большого количества результатов. Для этого вам необходимо задать значение глобальной переменной $ADODB_COUNTRECS = false. Эта переменная проверяется всегда, когда вы запускаете запрос, так что вы можете выбирать, когда вам нужно посчитать количество возвращаемых результатов, а когда нет.

Даже если вы установили $ADODB_COUNTRECS = false, у вас есть функция PO_RecordCount(). Эта функция вернет вам количество строк, а в случае, если эта информация будет не доступна, возвратит вам результат запроса SELECET COUNT(*):
$rs = $db->Execute("select * from table where state=$state");
$numrows = $rs->PO_RecordCount('table', "state=$state");

Locking (блокирование, захват)

При использовании SELECT обычно требуется заблокировать на время выборки данные. Ряд баз данных, например, Oracle, Interbase, PostgreSQL и MySQL с InnoDB не требуют блокирования, потому что используют versionning (версионность), чтобы показать данные на данный конкретный момент времени.

На данный момент я рекомендую инкапсулировать блокировку при помощи функции RowLock($table, $where).

$connection->BeginTrans( );
$connection->RowLock($table, $where); 

# какие-то действия

if ($ok) $connection->CommitTrans( );
else $connection->RollbackTrans( );

Outer Joins (Внешнее присоединение)

Не все базы данных поддерживают внешнее присоединение. К тому же, синтаксис у разных баз данных сильно отличается. Один из переносимых способов (возможно, медленных) делать внешние присоединения – это использование UNION.

Например, в ANSI-92 внешнее присоединение слева между двумя таблицами может выглядеть так:

SELECT t1.col1, t1.col2, t2.cola 
  FROM t1 LEFT JOIN t2 ON t1.col = t2.col

Это можно эмулировать следующим образом:

SELECT t1.col1, t1.col2, t2.cola FROM t1, t2 
           WHERE t1.col = t2.col 
   UNION ALL
SELECT col1, col2, null FROM t1 
           WHERE t1.col not in (select distinct col from t2)

С версии 2.13 в ADODB есть некоторые функции для помощи в составлении таких запросов. Эти функции все еще не полны и не совершенны и часто зависят от версии используемой базы данных. Но они могут быть полезны как общее руководство:

$conn->leftOuter: возвращает оператор для внешнего присоединения слева (например, *=), или FALSE, если составление оператора невозможно.

$conn->rightOuter: возвращает оператор для внешнего присоединения справа (например, =*), или FALSE, если составление оператора невозможно.

$conn->ansiOuter: булевая переменная. TRUE – если ваша база данных поддерживает ANSI-92, FALSE – если вы не уверены или не знаете об этом.

INSERT

Когда вы заносите в таблицу запись, то необходимо создать уникальный ID записи. Существует 2 общих способа: 1) auto-increment колонки, 2) последовательности.

Auto-increment колонки поддерживаются MySQL, Sybase и Microsoft Access и SQL Server. Однако большинство других баз не поддерживают такую возможность. Отсюда видно, что для создания переносимого кода у вас не такой большой выбор, а именно – использовать последовательности. Последовательности – это специальные функции, которые возвращают уникальное число каждый раз, когда вы к ним обращаетесь. Эти числа вполне подходят для использования в качестве уникальных ключей. В ADODB мы используем функцию GenId(). В качестве параметра она принимает название последовательности. Различные таблицы могут иметь разные последовательности.

$id = $connection->GenID('sequence_name');
$connection->Execute("insert into table (id, firstname, lastname) 
                           values ($id, $firstname, $lastname)");

Для баз данных, не поддерживающих последовательности, ADODB делает эмуляцию, создавая таблицы, для каждой последовательности.

Binding (обвязка)

Обвязка переменный в SQL запросе – это еще одна хитра особенность. Обвязка полезна, поскольку позволяет перекомпилировать SQL запрос. При многократной вставке однотипных данных в цикле, обвязка может сохранить до 50% (или больше) ресурсов и времени. Однако, многие базы данных, например Access и MySql не поддерживают нативно обвязку, а потому приходится делать некоторую надстройку для эмуляции обвязки. Кроме того, отдельные базы данных (особенно Oracle!), делают обвязку подругому. Я рекомендую делать обвязку только в том случае, если ваши запросы к базе данных очень медленные. Но удостоверьтесь, что ваша база данных поддерживает обвязку, например, Oracle.

ADODB поддерживает переносимые Portable/Execute:

$stmt = $db->Prepare('select * from customers where custid=? and state=?');
$rs = $db->Execute($stmt, array($id,'New York'));

Oracle использует именованные placeholders (не «?»). Для создания переносимого кода мы имеем функцию Param(), которая производит правильный placeholder (с версии ADODB 3.92):

$sql = 'insert into table (col1,col2) values ('.$DB->Param('a').','.$DB->Param('b').')';
# генерирует 'insert into table (col1,col2) values (?,?)'
# или        'insert into table (col1,col2) values (:a,:b)'
$stmt = $DB->Prepare($sql);
$stmt = $DB->Execute($stmt,array('one','two'));

Переносимый нативный SQL

ADODB обеспечивает следующие функции для генерации частей SQL запроса для встраивания затем их в основной запрос (некоторые доступны только с версии 3.92):

Функция Описание
DBDate($date) Берет UNIX timestamp или дату в формате ISO, и конвертирует ее в строку, пригодную для запросов INSERT/UPDATE
DBTimeStamp($date) Берет UNIX timestamp или дату в формате ISO, и конвертирует ее в строку, пригодную для запросов INSERT/UPDATE
SQLDate($date, $fmt) Переносимо форматирует дату по маске из $fmt для использвания ее в SELECT запросе
OffsetDate($date, $ndays) Переносимо генерирует дату ($date) с добавлением дней ($ndays).
Concat($s1, $s2, ...) Переносимо объединяет строки. Как альтернатива, для mssql, используйте mssqlpo драйвер, который принимеет || оператор.
IfNull($fld, $replaceNull) Возвращает строку иквивалентную MySQL IFNULL или Oracle NVL.
Param($name) Генерирует placeholders, используя ? или именованные соглашения.
$db->sysDateФормирует SQL запрос, который возвращает системную дату.
$db->sysTimeStampФормирует запрос, который возвращает тайм штамп (date+time).
$db->concat_operatorФормирует оператор объединения.
$db->lengthВозвращает название strlen SQL функции.
$db->upperCaseВозвращает название strtoupper SQL функции.
$db->randomВозвращает SQL, который генерирует случайное число между 0.00 и 1.00.
$db->substrВозвращает название substring SQL функции.
Яндекс цитирования