Оригинал на http://phplens.com/lens/adodb/docs-adodb.htm
Перевод Феськов Кузьма
(c) 2002-2003 John Lim (jlim#natsoft.com)
(c) 2005 Feskov Kuzma (kuzma#russofile.ru)
Это программное обеспечение распространяется под двумя лицензиями: BSD-style и LGPL. Это означает, что вы можете использовать его в компилируемых и коммерческих продуктах.
Если вы создаете приложение, которое может быть использовано в множестве операционных системах, то вам необходимо распланировать поддержку различных баз данных. Эта статья опирается на опыт работы со множеством баз данных в том числе и на компьютере Макинтош. В настоящее время я использую такие базы данных как: Oracle, FoxPro, Access, MS SQL Server и MySQL. Хотя большинство советов относится в пользователям SQL на Perl, Python и др. языках программирования, я сосредоточусь на использовании PHP и на том, какую помощь предлагает нам ADODB.
Большинство баз данных являются закрытыми. Самый лучший или быстрый способ сделать что-то – это использовать патентованные (платные) расширения SQL. Все это чрезвычайно затрудняет написание переносимого SQL, который бы хорошо работал при любых условиях. Когда ANSI комитет собрался в 1984 году, чтобы стандартизировать SQL, большинство производителей баз данных имели настолько различные способы обработки данных, что они смогли договориться только об основных функциональных возможностях SQL. Множество важных определений небыло стандартизировано. И даже после принятия ANSI-92 SQL, который стандартизировал гораздо больше, мы все еще должны осуществлять переносимость на уровне кода.
Конструкция 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");
При использовании SELECT обычно требуется заблокировать на время выборки данные. Ряд баз данных, например, Oracle, Interbase, PostgreSQL и MySQL с InnoDB не требуют блокирования, потому что используют versionning (версионность), чтобы показать данные на данный конкретный момент времени.
На данный момент я рекомендую инкапсулировать блокировку при помощи функции RowLock($table, $where).
$connection->BeginTrans( );
$connection->RowLock($table, $where);
# какие-то действия
if ($ok) $connection->CommitTrans( );
else $connection->RollbackTrans( );
Не все базы данных поддерживают внешнее присоединение. К тому же, синтаксис у разных баз данных сильно отличается. Один из переносимых способов (возможно, медленных) делать внешние присоединения – это использование 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 – если вы не уверены или не знаете об этом.
Когда вы заносите в таблицу запись, то необходимо создать уникальный 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 делает эмуляцию, создавая таблицы, для каждой последовательности.
Обвязка переменный в 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'));
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 функции. |