Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Самоучитель PHP 4 - Котеров Д. В.

.pdf
Скачиваний:
99
Добавлен:
24.05.2014
Размер:
4 Мб
Скачать
☆

368

Часть IV. Стандартные функции PHP

Строки

Строки представляют собой массивы символов. Обычно при поиске по текстовым полям по запросу SELECT не берется в рассмотрение регистр символов, т. е. строки "Вася" и "ВАСЯ" считаются одинаковыми. Кроме того, если база данных настроена на автоматическую перекодировку текста при его помещении и извлечении (см. ни- же), эти поля будут храниться в указанной вами кодировке.

Для начала давайте ознакомимся с типом строки, которая может хранить не более length символов, где length принадлежит диапазону от 1 до 255.

VARCHAR(length) [BINARY]

При занесении некоторого значения в поле такого типа из него автоматически вырезаются концевые пробелы (как будто по вызову функции rtrim()). Если указан флаг BINARY, то при запросе SELECT строка будет сравниваться с учетом регистра. Тип VARCHAR неудобен тем, что может хранить не более 255 символов. Вместо него я рекомендую использовать другие текстовые типы, перечисленные в табл. 26.3.

 

Таблица 26.3. Строковые типы данных таблиц MySQL

 

 

Тип

Описание

 

 

TINYTEXT

Может хранить максимум 255 символов

TEXT

Может хранить не более 65 535 символов

MEDIUMTEXT

Может хранить максимум 16 777 215 символов

LONGTEXT

Может хранить 4 294 967 295 символов

Чаще всего применяется тип TEXT, но если вы не уверены, что данные не будут всегда короче 65 536 байтов, используйте LONGTEXT.

Слухи о том, что TEXT-типы занимают намного больше места, чем аналогич- ные VARCHAR-поля, сильно преувеличены.

Бинарные данные

Бинарные данные — это почти то же самое, что и данные в формате TEXT, но только при поиске в них учитывается регистр символов ("abc" и "ABC" — разные строки). Вего имеется 4 типа бинарных данных (табл. 26.4).

Таблица 26.4. Типы бинарных данных, используемые в MySQL

 

Глава 26. Работа с базой данных MySQL

369

 

 

 

 

 

 

 

Тип

Описание

 

 

 

 

 

 

 

 

TINYBLOB

Может хранить максимум 255 символов

 

 

 

BLOB

Может хранить не более 65 535 символов

 

 

 

MEDIUMBLOB

Может хранить максимум 16 777 215 символов

 

 

 

LONGBLOB

Может хранить 4 294 967 295 символов

 

 

BLOB-данные не перекодируются автоматически, если при работе с установленным соединением включена возможность перекодирования текста "на лету" (см. ниже).

Дата и время

MySQL поддерживает несколько типов полей, специально приспособленных для хранения дат и времени в различных форматах (табл. 26.5).

Таблица 26.5. Представление дат и времени в базах данных MySQL

Тип

Описание

 

 

DATE

Дата в формате ГГГГ-ММ-ДД

TIME

Время в формате ЧЧ:ММ:СС

DATETIME

Дата и время в формате ГГГГ-ММ-ДД ЧЧ:ММ:СС

TIMESTAMP

Время и дата в формате timestamp. Однако при получе-

 

нии значения поля оно отображается не в формате time-

 

stamp, а в виде ГГГГММДДЧЧММСС, что сильно умаляет

 

преимущества его использования в PHP

Надо заметить, что в PHP будет проще самостоятельно генерировать дату и время при вставке данных в таблицу, а не задействовать встроенные в MySQL типы. Например, привлекательный с виду тип TIMESTAMP на деле оказывается довольно неудобным, потому что отображается не в том виде, который мы ожидаем.

Перечисления и множества

MySQL поддерживает еще несколько специфических типов данных, использовать которые в PHP вряд ли целесообразно. Например, тип перечисления задает, что значение соответствующего поля может быть не любой строкой или числом, а только одним из нескольких указанных при создании таблицы значений: value1, value2 и т. д. Вот как выглядит имя типа перечисления:

ENUM(value1,value2,value3,...)

В отличие от всех остальных типов, множества означают, что в соответствующем поле может содержаться не одно, а сразу несколько значений (value1, value2 и т.

370

Часть IV. Стандартные функции PHP

д., т. е. — множество значений). Формат задания данных такого типа имеет следующий вид:

SET(value1,value2,value3,...)

Значений в множестве может быть не сколько угодно, а не более 64 штук. Ино- гда это сильно мешает при программировании.

Модификаторы и флаги типов

К типу можно также присоединять модификаторы, которые задают его "поведение" и те операции, которые можно (или, наоборот, запрещено) выполнять с соответствующими столбцами. Самые распространенные из них сведены в табл. 26.6.

 

Таблица 26.6. Основные модификаторы MySQL

 

 

Модификатор

Описание

 

 

not null

Означает, что поле не может содержать неопределенное зна-

 

чение — в частности, поле обязательно должно быть инициа-

 

лизировано при вставке новой записи в таблицу (если не за-

 

дано значение по умолчанию)

primary key

Отражает, что поле является первичным ключом, т. е. иден-

 

тификатором записи, на которой можно ссылаться

auto_increment

При вставке новой записи поле получит уникальное значение,

 

так что в таблице никогда не будут существовать два поля с

 

одинаковыми номерами. (Мы поговорим об этом чуть позже.)

Default

Задает значение по умолчанию для поля, которое будет ис-

 

пользовано, если при вставке записи поле не было проини-

 

циализировано явно

 

 

Удаление таблицы

drop table ИмяТаблицы

Удаляет таблицу ИмяТаблицы. Таблица не обязательно должна быть пустой, так что будьте внимательны, чтобы случайно не "аннулировать" нужную таблицу с данными.

Вставка записи

insert into ИмяТаблицы(ИмяПоля1 ИмяПоля2 ...) values('зн1','зн2',...)

Добавляет в таблицу ИмяТаблицы запись, у которой поля, обозначенные как ИмяПоляN, установлены в значения, соответственно, знN. Те поля, которые в этой команде не перечислены, получают "неопределенные" значения (неопределенное зна-

Глава 26. Работа с базой данных MySQL

371

чение — это не пустая строка, а просто признак, который говорит MySQL, что у данного поля нет никакого значения). Впрочем, если для не указанного здесь поля при создании таблицы был задан not null, то данная команда закончится неуспешно. Значения полей можно заключать и в обычные кавычки, но, по-моему, апострофы тут использовать удобнее. При вставке в таблицу бинарных данных (или текстовых, содержащих апострофы и слэши) некоторые символы должны быть "защищены" обратными слэшами, а именно, символы \, ' и символ с нулевым кодом.

Удаление записей

delete from ИмяТаблицы where Выражение

Удаляет из таблицы ИмяТаблицы все записи, для которых выполнено Выражение. Параметр Выражение — это просто логическое выражение, составленное почти что по правилам PHP. Вот показательный пример:

(id<10) and (name regexp 'a*b') and (age=25)

В выражении, помимо имен полей, констант и операторов, могут также встречаться простейшие "вычисляемые" части, например: (id<10+11*234).

Вообще говоря, формат выражения един для всех команд запросов, которые мы встретим в дальнейшем. Например, он же используется и в операции select, и в операции update.

Поиск записей

select * from Таблица where Выражение [order by ИмяПоля [desc]]

Эта команда — основная и очень мощная. Предназначена она для того, чтобы искать все записи, удовлетворяющие выражению Выражение. Ее возможности гораздо более богаты, чем то сжатое изложение, которое я вам предлагаю, и о них можно прочитать в книгах, посвященных SQL. Если записей несколько, то при указанном предложении order by они будут отсортированы по тому полю, имя которого записывается правее этого ключевого слова (если задан описатель desc, то упорядочивание происходит в обратном порядке). В предложении order by могут также задаваться несколько полей.

Особое значение имеет символ *. Он предписывает, что из отобранных записей следует извлечь все поля, когда будет выполнена команда получения выборки. С другой стороны, вместо звездочки можно через запятую непосредственно перечислить имена полей, которые требуют извлечения. Но чаще всего все же используется именно *.

Обновление записей

update Таблица set(ИмяПоля1='зн1', ИмяПоля1='зн2', ...) where Выражение

372

Часть IV. Стандартные функции PHP

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

Получение числа записей, удовлетворяющих выражению

Стоит рассмотреть еще одну часто востребуемую возможность MySQL — получение числа записей, удовлетворяющих некоторому выражению. Вообще говоря, существует несколько способов сделать это. Вот один из них:

select count(if(Выражение,1,NULL)) from Таблица

Уже этот пример показывает, насколько богаче язык MySQL по сравнению с тем, что

было описано...

Получение уникальных значений столбцов

При использовании базы данных часто бывает крайне удобно узнать, какие уникаль- ные значения существуют в данном столбце таблицы. Например, если у каждой записи в некоей статистической таблице, содержащей сведения о людях, у нас есть поле Country (страна), в котором указана страна проживания конкретного человека, и мы хотим выяснить, в каких же странах проживают все люди, дожившие до 30 лет, занесенные в таблицу, можно выполнить запрос:

select distinct ИмяПоля from Таблица where Выражение

В нашем случае ИмяПоля=Country, а Выражение — что-то вроде age>=30. Этот запрос сгенерирует результат, состоящий из одного столбца, в котором и будут перечислены искомые страны.

Получение результата

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

Результат — это просто набор данных, и количество вошедших в него записей можно узнать через mysql_num_rows(). Например, если в предыдущем примере при выборке из таблицы оказалось, что в таблице имеются записи о 10 людях старше 30 лет, то мы в идентификаторе результата получим "ссылку" на 10 "строчек". Теперь мы можем считать в программу на PHP любую из них с помощью специальных функций, которые будут описаны ниже.

Глава 26. Работа с базой данных MySQL

373

Каждая запись — это список значений полей, а именно, тех полей и в том же порядке, которые были указаны в запросе select ... from Таблица на месте многоточия (если там была звездочка, то все поля). Таким образом, результат — это такой своеобразный двумерный массив: первый индекс — номер записи и второй — имя поля. Можете называть его прямоугольной таблицей или матрицей данных — как угодно.

Мне не нравится общепринятый в технической литературе термин "резуль- тирующий набор данных" — слишком уж он длинный и бесформенный. Вместо него я и дальше буду использовать слово "результат".

Параметры результата

int mysql_num_rows(int $result)

Функция mysql_num_rows() возвращает число записей в результате запроса. Таким образом, функция позволяет определить вертикальную размерность "двумерного массива результата".

int mysql_num_fields(int $result)

Эта функция возвращает число полей в одной строке результата, т. е., число колонок в результате $result. В силу сказанного, функция позволяет определить горизонтальную размерность "двумерного массива результата".

Получение поля результата

int mysql_result(int $result, int $row, mixed $field)

Функция возвращает значение поля $field в строке результата с номером $row. Параметр $field может задавать не только имя поля, но и его номер — позицию, на которой столбец "стоял" при создании таблицы. Тем не менее, рекомендуется везде, где это только возможно, использовать именно имена полей.

Если мы опять будем рассматривать результат как двумерный массив полей, то параметр $field надо поставить в соответствие его X-координате, а $row — Y-координате. В этом понимании X-координата чаще всего будет ас- социативной — т. е. в ней задается не число, а имя столбца.

Функция универсальна: с ее помощью можно "обойти" весь результат по одной ячейке. И хотя это не возбраняется, но делать, однако, не рекомендуется, т. к. mysql_result() работает довольно медленно. Лучше воспользоваться функциями, которые описываются дальше.

374

Часть IV. Стандартные функции PHP

Получение целой строки результата

Разработчики MySQL предусмотрели другой, более быстрый, способ получения результата. Он чем-то похож на работу с файлами: появляется понятие текущей записи результата, и следующая операция считывания передвигает этот указатель на одну позицию вперед. Также можно установить указатель на любую указанную запись.

array mysql_fetch_row(int $result)

Функция возвращает массив-список со значениями полей очередной строки результата $result. Если указатель текущей позиции результата был установлен за последней записью (то есть строки кончились), возвращает false. Текущая позиция сдвигается к следующей записи, так что очередной вызов mysql_fetch_row() вернет следующую строку результата.

Эту функцию чаще всего применяют в таком контексте:

$r=mysql_query("select * frim OurTable where age<30"); while($Row=mysql_fetch_row($r)) {

// обрабатываем строку $Row

}

Как видим, цикл оборвется, как только строки закончатся, т. е. когда mysql_fetch_row() вернет false.

Работать с числовыми индексами полей, как до сих пор предлагалось, согласитесь, не очень-то удобно. Гораздо предпочтительнее было бы использовать для адресации поля внутри результата его имя. Функция mysql_fetch_array() как раз и извлекает из результата очередную запись и помещает ее в ассоциативный массив.

array mysql_fetch_array(int $result)

Функция mysql_fetch_array() возвращает очередную строку результата в виде ассоциативного массива, где каждому полю сопоставлен элемент с ключом, совпадающим с именем поля. Дополнительно в массив записываются элементы с числовыми ключами и значениями, соответствующими величинам полей с этими индексами. В возвращаемом массиве они размещаются сразу за элементами с "обычными" ключами.

Может возникнуть вопрос: зачем вообще тут нужны числовые индексы. Ответ прост: дело в том, что в результате выборки в действительности могут присут- ствовать поля (фактически, колонки) с одинаковыми именами, но, соответст- венно, с различными индексами. Это происходит тогда, когда выборка в SELECT производится одновременно из нескольких таблиц (язык SQL это по- зволяет). Думаю, в простейших приложениях такое случается нечасто.

Глава 26. Работа с базой данных MySQL

375

Рекомендую всегда вместо mysql_fetch_row() использовать функцию mysql_fetch_array(), потому что она более универсальна и к тому же, как написано в документации, не намного медленнее.

int mysql_data_seek(int $result, int $row_number)

Эта функция устанавливает указатель текущей строки в результате $result в пози-

цию $row_number, так что следующий вызов mysql_fetch_row() и mysql_fetch_array() вернет значения полей именно этой строки. Возвращает false в случае ошибки или если строки кончились.

Получение информации о результате

Будет полезно рассмотреть еще несколько функций, предназначенных для получения различной информации о результате запроса.

string mysql_field_name(int $result, int $field_index)

Функция mysql_field_name() возвращает имя поля, которое расположено в результате по смещению $field_index. В общем-то, применяется довольно редко, что связано с существованием функции mysql_fetch_array().

Итак, с помощью функции mysql_field_name() мы можем "переводить" чи- словые X-координаты в двумерном массиве результата в их ассоциативные эк- виваленты.

string mysql_field_type(int $result, int $field_offset)

Эта функция похожа на mysql_field_name(), только возвращает не имя, а тип соответствующей колонки в результате. Им может быть, например, int, double и т. д.

int mysql_field_len(int $result, int $field_offset)

Функция возвращает длину поля в результате $result. Поле, как обычно, задается указанием его смещения. Под длиной здесь подразумевается не размер данных поля в байтах, а тот размер, который был указан при его создании. Например, если поле имеет тип varchar и было создано (вместе с таблицей) с типом varchar(100), то для него будет возвращено 100.

Описание подробностей выходит за рамки этой книги. За детальными разъяс- нениями вынужден отослать вас к какой-нибудь книге о языке запросов SQL.

376

Часть IV. Стандартные функции PHP

string mysql_field_flags(int $result, int $field_offset)

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

$Flags=explode(" ",mysql_field_flags($r,$field_offset));

Флаги, которые поддерживаются MySQL в настоящий момент, перечислены в табл. 26.7.

 

Таблица 26.7. Флаги типов полей

 

 

Флаг

Описание

 

 

not_null

Поле обязательно должно быть проинициализировано при

 

вставке очередной строки в таблицу

Primary_key

Поле является первичным ключом — т. е. идентификатором

 

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

Unique_key

Поле должно быть уникальным

Multiple_key

По этому полю построен индекс

Blob

Поле может содержать бинарный блок данных, который никак

 

не интерпретируется

 

Таблица 26.7 (окончание)

 

 

Флаг

Описание

 

 

Unsigned

Поле содержит беззнаковые числа

zerofill

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

binary

Поле содержит бинарные данные

enum

Поле содержит элемент перечисления, т. е. только один эле-

 

мент из нескольких возможных

auto_increment

Это поле автоматически нумеруется. Проставляется

 

MySQLпри добавлении новой записи так, чтобы в таблице

 

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

 

значением этого поля

timestamp

В поле динамически проставляется текущее время при до-

 

бавлении или изменении записи

string mysql_field_table(int $result, int $field_offset)

Возвращает имя таблицы, из которой было извлечено поле со смещением $field_offset в результате $result. Как уже говорилось, результат запроса мо-

Глава 26. Работа с базой данных MySQL

377

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

Пример использования функций поддержки MySQL

Ниже приводится пример комплексного использования описанных функций.

<?

//Соединяемся с сервером на локальной машине mysql_connect("localhost");

//Выбираем текущую базу данных

mysql_select_db("my_database"); // Получаем все данные таблицы

$result = mysql_query("SELECT * FROM tbl");

// Запрашиваем идентификатор данных о полях таблицы $fields = mysql_num_fields($result);

//Узнаем число записей в таблице $rows = mysql_num_rows($result);

//Получаем имя таблицы (правда, мы его и так знаем, но все же...) $table = mysql_field_table($result,0);

echo "Таблица '$table' содержит $fields колонок и $rows строк<BR>"; echo "Таблица содержит следующие поля:<BR>";

//"Проходимся" по всем полям и выводим информацию о них

for($i=0; $i<$fields; $i++) {

$type = mysql_field_type($result, $i); $name = mysql_field_name($result, $i); $len = mysql_field_len($result, $i); $flags = mysql_field_flags($result, $i); echo "$type $name $len $flags<BR>\n";

}

?>

Уникальные идентификаторы в MySQL

Обычно в таблице содержится довольно много записей с разными значениями полей. Встает проблема выбора одной конкретной записи из этого массива. В рассмотренном нами примере таблицы с информацией о гражданах, пожалуй, запись можно однозначно идентифицировать по фамилии человека. Ну а если встретятся однофамильцы? Тогда по имени. А если же и имена совпадут? Ну, тогда…...

Вы видите, насколько это все неудобно. Поэтому во избежание недоразумений подобного рода в таблицу вводят еще одно вспомогательное поле (колонку), назвав ее, ска-