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 select top 10 * from table MySQL,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 функции.
|