Пятница , 19 Апрель 2024
ДомойПубликацииновичкам: несколько простых приёмов для mysql

новичкам: несколько простых приёмов для mysql

новичкам: несколько простых приёмов для mysql

несколько раз приходилось видеть, как люди, только-только начавшие работать с базами данных, использовуют sql-синтаксис только для выборки/вставки/удаление/обновления, причём запросы формируются порой на основе одного единственного примера и не подлежат дальнейшему обсуждению. спешу таких людей обрадовать: sql — это язык программирования. в нём содержатся функции, над значениями разрешается производить арифметические операции. в общем, sql (и mysql в частности) содержит очень много полезных плюшек, не использоние которых приводит к ненужному разрастанию кода программы и дополнительным запросам к базе данных.

допустим, имеем таблицу новостей со следующими полями:

  • id — идентификатор новости;
  • subject — название новости;
  • date_add — дата добавления;
  • text — текст новости;
  • count — количество просмотров новости.

обновлять значения в mysql очень просто

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

$id = 1;
$q = 'SELECT `count` FROM `news` WHERE `id` = ' . $id;
$r = mysql_query($q);
$n = mysql_fetch_array($r);
$n['count'] = $n['count`] + 1;
$q = 'UPDATE `news` SET `count` = ' . $n['count'] . ' WHERE `id` = ' . $id;
$r = mysql_query($q);

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

$id = 1;
$q = 'UPDATE `news` SET `count` = `count` + 1 WHERE `id` = ' . $id;
$r = mysql_query($q);

в этом случае промежуточную работу возьмёт на себя сама база данных: запрос от второго потока не сможет изменить запись, пока это не сделает запрос от потока № 1.

mysql содержит развитые средства для работы с датой/временем

для получение текущего времени существует внутренняя фунция, которую лучше и вызывать (например, если требуется установить при вставке текущую дату), а не передавать из php значение даты.

SELECT NOW()

запрос вставки может выглядеть так:

INSERT INTO `news`
SET `date_add` = NOW(), `subject` = 'название', `text` = 'содержимое новости'

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

SELECT FROM_UNIXTIME(123456789)

может вернуть значение 2009-02-14 02:31:30.

для быстрого преобразования дат из одного формата в формат ГГГГ-ММ-ДД можно воспользоваться таким приёмом:

SELECT STR_TO_DATE('12.11.2010', '%d.%m.%Y')

функция вернёт значение 2010-11-12.

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

постоянно терзать базу, заставляя её возвращать огромные результаты выборки, плохая идея. да, субд оптимизируется под работу с данными. но при каждом запросе формировать таблицы на десятки (сотни) мегабайт явно излишне. поэтому в select-запросе обязательно перечисляются поля, реально требующиеся в скрипте (для вывода списка новостей, например, не требуется текст каждой новости) и используется ограничитель limit (и только так). запрос получение 10 последних новостей может выглядеть так:

SELECT `id`, `subject`, `date_add`
FROM `news`
ORDER BY `date_add` DESC
LIMIT 0, 10

при вставке лучше явно указать вставляемые значения

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

INSERT INTO `news` VALUES(NULL, 'название', NOW(), 'содержимое новости', 0)

но представьте, что в таблицу будет добавлено дополнительное поле. запрос выше вызовет ошибку. поэтому пишем так:

INSERT INTO `news` (`subject`, `date_add`, `text`)
VALUES('название', NOW(), 'содержимое новости')

при добавлении нового поля запрос всё-равно будет успешно выполнен и запись добавлена. новое поле получит значение по умолчанию.

mysql содержит множество полезных функций, например: MD5(), SHA1(), LEFT(), REPLACE(), DATE_FORMAT() и т. д. поэтому, когда возникнет непреодолимое желание что-то сделать через дополнительный подзапрос на стороне php, посмотрите в документации mysql, не предоставляет ли субд аналогичную функцию, и если это так без раздумий пользуйтесь ей.

Рейтинг: 0

Автор публикации

2 070
не в сети 12 месяцев

x64 (aka andi)

Комментарии: 2893Публикации: 405Регистрация: 02-04-2009
Так себеНеплохоХорошоЗамечательноСупер! (Оценок пока нет)
Загрузка...

Один комментарий

  1. Для большого объема SELECT COUNT можно оптимизировать: http://plutov.by/post/mongodb_counters

    Рейтинг: 0

Оставить комментарий

Политика конфиденциальности

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

Принять