Введение в MySQL (используя Perl DBI)Перевод выполнил Дмитрий Николаев. Оригинал на ангийском лежит здесь: //www.danchan.com/feature/2000/10/16/mysql/mysql.htm ( http://webscript.ru///www.danchan.com/feature/2000/10/16/mysql/mysql.htm ) Я считаю, что если название статьи не звучит для Вас чуждо, то, возможно, Вы в нужном месте. MySQL - это реляционная база данных. MySQL основана на технологии client/server. Все примеры команд MySQL в этой статье могут быть введены прямо в командную строку MySQL. MySQL поддерживает многострочные команды и использует точку с запятой, как разделитель между командами. Почему же MySQL, а ни другая база данных SQL? Хотя бы потому, что она бесплатна, быстра и имеет хорошую поддержку. Данные организуются как ряды и колонки, образующие матрицу. С точки зрения SQL, матрица называется таблицей. Лучший способ для C программиста понять что же это такое: Каждый ряд - это структурная ссылка. Каждая колонка - это член этой структуры. Вот обычная структура (класс, объявленный с ключевым словом struct) в C: struct users { int id; char nickname[17]; char password[17]; int socks; int favorite_number; }; Это выглядит как информация, собранная Web-сайтом о пользователе. А вот MySQL версия этой структуры: create table users ( id int auto_increment not null, nickname varchar(16) not null, password varchar(16) not null, socks int, favorite_number int, primary key (user_id), unique (nickname) ); Несколько похоже, не так ли? Вот как будет выглядеть ряд в MySQL: +----+----------+----------+-------+-----------------+ | id | nickname | password | socks | favorite_number | +----+----------+----------+-------+-----------------+ Что же тогда матрица? Вот данные в таблице(матрице) о трёх гипотетических пользователях: +----+----------+----------+-------+-----------------+ | 1 | GdayMate | dingo | 57 | 42 | +----+----------+----------+-------+-----------------+ | 2 | Javier | cigar | 1 | 945 | +----+----------+----------+-------+-----------------+ | 3 | Rolo | pudding | 9 | 8 | +----+----------+----------+-------+-----------------+ Фактически эти таблицы - это то, что вы увидете, если введёте в MySQL следующую команду: select * from users; Звёздочка означает, что мы выбираем все колонки из таблицы. Таблица - это структурная основа многомиллиардной годовой индустрии баз данных, которая включает в себя такие компании, как Oracle и Informix. Простейшие команды MySQLДавайте быстро "пробежим" по простейшим командам MySQL. Вы уже занете команду create. create table users ( id int auto_increment not null, nickname varchar(16) not null, password varchar(16) not null, socks int, favorite_number int, primary key (user_id), unique (nickname) ); А что же делать, если хотим увидеть только прозвища и любимые числа пользователей? select nickname, favorite_number from users; Данная команда даст нам: +----------+-----------------+ | nickname | favorite_number | +----------+-----------------+ | GdayMate | 42 | +----------+-----------------+ | Javier | 945 | +----------+-----------------+ | Rolo | 8 | +----------+-----------------+ А если хотим вывести прозвища пользователей, но с условием, что носков у них меньше, чем 10 пар и их любимое число больше, чем 100? select nickname from users where socks < 10 and favorite_number > 100; +----------+ | nickname | +----------+ | Javier | +----------+ Как же ввести данные в таблицу? Это просто. insert into users (nickname, socks) values ('Cowlick', 0); Да , но мы забыли добавить поле пароля в таблицу! create table users ( ... password varchar(16) not null, ... ); Под NOT NULL понимается то, что поле должно нести в себе какие-либо данные. Поэтому в заданном выше примере MySQL выдаст ошибку. Поэтому следует сделать так: insert into users (nickname, password, socks) values ('Cowlick', 'udder', 0); Результат будет следующим: +----+----------+----------+-------+-----------------+ | id | nickname | password | socks | favorite_number | +----+----------+----------+-------+-----------------+ | 4 | Cowlick | udder | 0 | NULL | +----+----------+----------+-------+-----------------+ Но подождите! Мы не определили id! Оно также not null. create table users ( id int auto_increment not null, ... ); В этом случае колонку id мы определили как auto_increment и MySQL сама создаёт значения для нас, добавляя 1 к наибольшему значению, которое найдёт в таблице (Rolo имеет id == 3). Мы забыли ввести любимое число пользователя Cowlick. Которое, между прочим, -1. Для этого мы будем использовать команду update. update users set favorite_number = -1 where id = 4; Также можем выполнить это следующим образом: update users set favorite_number = -1 where nickname = 'Cowlick'; Но вдруг у нас появится больше чем один пользователь с прозвищем Cowlick? В нашем примере этого быть не может, т.к. в командеcreate table мы определили: create tables users ( ... unique (nickname) ); Если мы попробуем ввести ещё одного пользователя с прозвищем Cowlick, то мы получим ошибку от MySQL. Предположим Вы имеете проблемы с пользователем Javier. Длугие члены вашего общества также считают, что этому пользователю не место среди них, Вы можете сделать следующее delete from users where nickname = 'Javier'; Если же Вы хотите удалить всю таблицу, то необходимо будет сделать следующее. drop table users; Определение таблицы и все данные после вышеописанной команды будут удалены. Будьте осторожны с этой командой. Типы MySQL и primary keyМы не говорили о директиве primary key в команде create table. create table users ( ... primary key (user_id), ... ) Создаётся первичный ключ. Первичный ключ - это особый ключ, который может быть только один для данной таблицы для каждой аблицы. По сути, первичный ключ - это уникальный (UNIQUE) ключ с именем "PRIMARY". Несмотря на привелегированный статус, он функционирует как другой уникальный ключ. Но select * from users where user_id = 2; быстрее, чем select * from users where favorite_number = 945; MySQL ограничен маленькими типами данных? Если, конечно, Вы считаете, что 4 гигабайта - это мало, то да. Это размер, который может быть помещён в поля типов LongBlob и LongText. Предположим мы хотим создать форум. Простая таблица для хранения сообщений может выглядеть так: create table messages ( id int auto_increment not null, user_id int not null, posting_date datetime not null, comment_body text primary key (id) ) Этот пример предоставил нам два новых типа: datetime и text. Данные колонки datetime структуированы следующим образом: "YYYY-MM-DD hh:mm:ss". В данном примере поdatetime могут быть отсортированы сообщения. Для нас это всего лишь строка. Типtextможет содержать данные до 64Kb, что более чем достаточно для сообщения. Колонка user_id является реляционной частью Реляционной Системы Управления Базой Данных (РСУБД). Вот пример ряда (message_body может быть более длинным): +----+---------+---------------------+--------------+ | id | user_id | posting_date | message_body | +----+---------+---------------------+--------------+ | 1 | 3 | 2000-10-10 10:00:00 | Wassup! | +----+---------+---------------------+--------------+ Предположим мы имеем систему голосования, где пользователи могут оценить действительно ли сообщение было достойно чтения или нет. Создадим таблицу, подобную этой: create table message_votes ( message_id int not null, user_id int not null, vote enum('good', 'bad') not null, primary key (message_id, user_id) ); В этом примере колонка vote может содержать одно из двух: либо 'good', либо 'bad'. Для поиска голосования сообщения можно будет сделать следующее: select * from message_votes where message_id = 3; , что будет быстрее, чем: select * from message_votes where user_id = 2; Но самым быстрым поиском голосования по сообщению будет: select * from message_votes where message_id = 3 and user_id = 2; Теперь мы готовы к взаимодействию DBI и MySQL. Использование Perl DBI как интерфейс для MySQLПочему PERL? Почему не PHP? Как-никак, но считается, что PHP4 достаточно быстр за счёт нового интерпретатора? Я отвечу, потому, что Perl - это язык, который наиболее часто сейчас используется. А я люблю идти в ногу со стандартами индустрии. Perl имеет большую поддержку online и большинство книг написано о нём. Существует CPAN, the Comprehensive Perl Archive Network, где Вы можете найти модули для исполнения Ваших самых сокровенных желаний, относительно программирования, конечно :-). DBI даёт Вам интерфейс, который будет работать как с самой примитивной БД, так и с самой последней версией Oracle РСУБД. Давайте начнём с соединения с базой данных: use DBI; my $dsn = 'DBI:mysql:my_database:localhost'; my $db_user_name = 'admin'; my $db_password = 'secret'; my ($id, $password); my $dbh = DBI->connect($dsn, $db_user_name, $db_password); Давайте предположим, что мы получили из формы логин и пароль пользователя. Итак, $input_nickname = 'Cowlick' и $input_password = 'udder' Естественно наше желание проверить действительно ли введёный пароль соответствует введёному логину в нашей БД. my $sth = $dbh->prepare(qq{select id, password from users where nickname = $input_nickname}); $sth->execute(); Отмечу отсутствие точки с запятой. При одной команде она не обязательна. Как же мы получим результат? Т.к. мы ожидаем всего один ряд то, ($id, $password) = $sth->fetchrow_array(); $sth->finish(): # закончили запрос if ($input_password eq $password) # чувствительно к регистру { ... # вход удачен } Что же делать если результат - более одной строки? Продолжающиеся запросы к $sth->fetchrow_array() вернут нам оставшуюся часть данных. my $sth = $dbh->prepare(qq{ select nickname, favorite_number from users }); $sth->execute(); while (my ($nickname, $favorite_number) = sth->fetchrow_array()) # делать выборку данных # пока ничего не останется { print "$nickname, $favorite_number\n"; } $sth->finish(); Если же мы хотим сохранить все результаты для последующего использования my (@matrix) = (); while (my @ary = $sth->fetchrow_array()) { push(@matrix, [@ary]); # [@ary] это ссылка } $sth->finish(); Ссылка для программистов на C может быть расценена как указатель. Матрица теперь является массивом массивов ссылок или же двумерным массивов ссылок. Вы можете достать ряд $i при помощи: @{matrix[$i]} Или, достать нужный ряд и колонку ($i, $j) в таблице: $matrix[$i][$j] Для операций MySQL, которые не возвращают результатов можно использовать метод do вместо prepare для того, чтобы выполнить SQL-команду. $dbh->do("insert into message_votes (message_id, user_id, vote) values (1, 3, 'good')"); И, наконец, чтобы окончить работу с базой - рассоединение: $dbh->disconnect(); |