Рубрика «MySQL»

Хранение изображений в базе данных MySQL

Для хранения изображений в базе данных MySQL необходимо определить одно из полей таблицы как производное от типа BLOB. Сокращение BLOB означает большой двоичный объект. Тип хранения данных BLOB обладает несколькими вариантами:

  • TINYBLOB - может хранить до 255 байт
  • BLOB - может хранить до 64 килобайт информации
  • MEDIUMBLOB - до 16 мегабайт
  • LONGBLOB - до 4 гигабайт

Соответсвенно, для хранения изображений нам надо создать таблицу images с двумя полями:

  • id - уникальный ID изображения
  • content - поле для хранения изображения

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

<form enctype="multipart/form-data" method="post" action="putimage.php">
Изображение: <input type="file" name="image" />
<input type="submit" value="Загрузить" />
</form>

Обработчик формы - файл putimage.php:

<?php
// Проверяем пришел ли файл
if( !empty( $_FILES['image']['name'] ) ) {
  // Проверяем, что при загрузке не произошло ошибок
  if ( $_FILES['image']['error'] == 0 ) {
    // Если файл загружен успешно, то проверяем - графический ли он
    if( substr($_FILES['image']['type'], 0, 5)=='image' ) {
      // Читаем содержимое файла
      $image = file_get_contents( $_FILES['image']['tmp_name'] );
      // Экранируем специальные символы в содержимом файла
      $image = mysql_escape_string( $image );
      // Формируем запрос на добавление файла в базу данных
      $query="INSERT INTO `images` VALUES(NULL, '".$image."')";
      // После чего остается только выполнить данный запрос к базе данных
      mysql_query( $query );
    }
  }
}
?>

Извлечь сохраненный файл изображения можно следующим образом (файл image.php):

<?php
if ( isset( $_GET['id'] ) ) {
  // Здесь $id номер изображения
  $id = (int)$_GET['id'];
  if ( $id > 0 ) {
    $query = "SELECT `content` FROM `images` WHERE `id`=".$id;
    // Выполняем запрос и получаем файл
    $res = mysql_query($query);
    if ( mysql_num_rows( $res ) == 1 ) {
      $image = mysql_fetch_array($res);
      // Отсылаем браузеру заголовок, сообщающий о том, что сейчас будет передаваться файл изображения
      header("Content-type: image/*");
      // И  передаем сам файл
      echo $image['content'];
    }
  }
}
?>

Чтобы вывести изображение в HTML-документе, делаем так:

<img src="image.php?id=17" alt="" />

И последнее: графические файлы иногда имеют довольно большой размер, убедитесь, что настройки сервера позволяют работать с таким объемом данных. В файле php.ini это директивы post_max_size - определяет максимальный объем данных передаваемых методом POST, и upload_max_filesize - определяет максимальный размер загружаемого файла. Так же проверьте, позволяют ли настройки MySQL обрабатывать запросы с большим объемом данных (директива max_allowed_packet файла my.ini).

Как в MySQL при наличии некоторых данных изменить их, а при отсутствии - добавить?

Зачастую возникают ситуации, когда нужно при наличии определенной строки в таблице в MySQL изменить ее, а при ее отсутствии - добавить. Обычно решают такую задачу в два приема: сначала проверяют, есть ли данные (SELECT с нужными условиями), а затем в зависимости от полученного результата либо изменяют их (UPDATE), либо добавляют (INSERT).

Конструкция получается достаточно трудоемкая. В этом случае будет эффективнее использовать команду MySQL REPLACE. По синтаксису она эквивалентна INSERT:

REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
или REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
или REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression,...

Логика работы REPLACE такова: если в существующей строке есть поле, для которого построен индекс типа PRIMARY KEY или UNIQUE, с тем же значением, что и в новой строке, то старая строка удаляется, а новая - добавляется. Если строки с таким значением в указанном поле нет, то строка просто добавляется.

Есть еще вариант с использованием ON DUPLICATE KEY UPDATE:

INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]
или INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
или INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name=(expression | DEFAULT), ...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]

Если вы указываете ON DUPLICATE KEY UPDATE (новшество в MySQL 4.1.0), и производится вставка строки, которая вызывает ошибку дублирующегося первичного (PRIMARY) или уникального (UNIQUE) ключа, то вполняется UPDATE старой строки. Например:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;

Если a определяется как UNIQUE и уже содержит 1, то тогда вышеуказанная команда будет аналогична следующей:

UPDATE table SET c=c+1 WHERE a=1;

Ссылки по теме:

Сортировка результатов SQL-запроса

Сортировка результатов SQL-запроса производится при помощи конструкции ORDER BY, после которой указывается имя столбца, который подвергается сортировке. Если после имени столбца указано ключевое слово ASC, сортировка производится по возрастанию, если же указано ключевое слово DESC, то сортировка будет по убыванию. Таким образом, задача сводится к динамическому формированию SQL-запроса, в конструкцию ORDER BY которого подставлялись бы имена выбранных столбцов и порядок сортировки. Для этого будем использовать запрос вида

$query = "SELECT * FROM products WHERE 1 ORDER BY ".$orderby." ".$sort;

где переменная $orderby будет содержать имя столбца, а $sort принимать значение ASC или DESC, в зависимости от того, какой вид сортировки выбран.

<?php
$dblocation = "localhost";   // Имя сервера
$dbuser     = "root";        // Имя пользователя
$dbpswrd    = "";            // Пароль
$dbname     = "catalog";     // Имя базы данных

// Соединение с сервером базы данных
$dblink = mysql_connect( $dblocation, $dbuser, $dbpswrd );
mysql_query( 'SET NAMES cp1251' );
// Выбираем базу данных
mysql_select_db( $dbname, $dblink );

// По умолчанию сортировка по наименованию, по возрастанию
$orderby = 'title';
$sort = 'ASC';
if ( isset( $_GET['orderby'] ) and isset( $_GET['sort'] ) ) {
  if ( in_array( $_GET['orderby'], array( 'code', 'title', 'price' ) ) ) $orderby = $_GET['orderby'];
  if ( in_array( $_GET['sort'], array( 'ASC', 'DESC' ) ) ) $sort = $_GET['sort'];
}

$query = 'SELECT code, title, description, price
          FROM products
          ORDER BY '
.$orderby.' '.$sort;
$res = mysql_query( $query );
echo '<h1>Каталог продукции</h1>'."\n";
// Выводим "шапку" таблицы
echo '<table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; empty-cells: show">'."\n";
echo '<tr>';
if ( $sort == 'ASC' ) {
  $tmp = 'DESC';
  $image = 'down.gif';
} else {
  $tmp = 'ASC';
  $image = 'up.gif';
}
if ( $orderby == 'code' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=code&sort='.$tmp.'">Код</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=code&sort=ASC">Код</a></th>';
if ( $orderby == 'title' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=title&sort='.$tmp.'">Наименование</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=title&sort=ASC">Наименование</a></th>';
echo '<th>Описание</th>';
if ( $orderby == 'price' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=price&sort='.$tmp.'">Цена</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=price&sort=ASC">Цена</a></th>';
echo '</tr>'."\n";
while( $prd = mysql_fetch_array( $res ) ) {
  echo '<tr>';
  echo '<td>'.$prd['code'].'</td>'."\n";
  echo '<td>'.$prd['title'].'</td>'."\n";
  echo '<td>'.$prd['description'].'</td>'."\n";
  echo '<td>'.$prd['price'].'</td>'."\n";   
  echo '</tr>'."\n";
}
echo '</table>'."\n";
?>

Посмотреть рабочий пример можно здесь.