Безопасность систем баз данных. Учебное пособие
.pdf10. ОСОБЕННОСТИ СУБД MYSQL
(ПК-33)
10.1. Сопоставления и наборы символов MySQL
Поскольку не все разработчики хранят строки данных на английском языке, важно чтобы сервер баз данных мог управлять неанглийскими символами и применять различные методы сортировки символов. При сопоставлении или сортировке строк оценка результата MySQL зависит от используемого набора символов и сопоставления. Наборы символов определяют символы для хранения. Например, вам может потребоваться хранить неанглийские символы «ü». Упорядоченность строк определяется их сопоставлением. Для различных языков существуют разные сопоставления. Например, позиция символа «ü» в алфавите различна в двух немецких классификациях и отличается от позиции в шведском или финском алфавите.
По умолчанию СУБДMySQL использует наборы latinl и сопоставление по умолчаниюlatin1_swedish_ci. Сервер MySQL можно конфигурировать для использования различных наборов символов и порядков сопоставления на уровне подключения, базы данных, таблицы и столбца.
Доступные на сервере наборы символов можно перечислить с помощью инструкции SHOW CHARACTER SET.
Так, набор символов latin1 представляет собой кодовую страницу Windows 1252, которая поддерживает восточноевропейские языки. Сопоставлением по умолчанию для этого набора символов является latinl_swedish_ci, которое следует шведским правилам сортировки символов по возрастанию(английский язык соответствует этим правилам). Это сопоставление нечувствительно к регистру, на что указывают буквы«ci». И наконец каждый символ занимает один байт. При использовании набора символов ucs2 каждый символ требует 2 байта для хранения.
Подобным образом вы можете перечислить порядки сопоставления и наборы символов, к которым они применяются:
Создавая базу данных, возможно задать для нее и ее таблиц набор символов и порядок сортировки по умолчанию. Например,
121
если использовать набор символовlatin1 и порядок сопоставления latin1_swedish_cs (чувствительный к регистру), то следует ввести следующую инструкцию:
mysql> CREATE DATABASE rose DEFAULT
CHARACTER SET latinl COLLATE latin1_swedish_cs;
Query OK. 1 row affected (0.00 sec)
Также можно управлять набором символов и сопоставлением для отдельных таблиц и столбцов, однако не будем вдаваться в детали этого процесса.
Рис. 10.1. Краткое описание каждого набора символов
На рис. 10.1 дано описание каждого набора символов, его сопоставление по умолчанию, а также максимальный объем в байтах, используемый для каждого символа в наборе:
mysql> SHOW CHARACTER SET;
122
10.2. Типы данных и их атрибуты
Распространенные типы.
Далее представлены шесть наиболее широко используемых типов данных в таблицах MySQL.
INT[(ширина)] [UNSIGNED] [ZEROFILL].Чаще всего используемый числовой тип. Позволяет хранить целочисленные значения из диапазона от -2 147 483 648 до 2 147 483 647. Если добавить опциональное ключевое слово UNSIGNED, то диапазон будет от 0 до 4 294 967 295. Ключевое слово INT является короткой формой от INTEGER и оба они могут использоваться поочередно. Значение типа INT требует для хранения четыре байта.
Можно включить опциональные аргументыширина и ZEROFILL, чтобы значения дополнялись нулями до указанной длины. Максимальным значением аргументаширина является 255. Параметр ширина не играет роли для хранения. Если хранить значение, которое больше заданной ширины, то значение ширина будет игнорироваться. Рассмотрим пример:
mysql> CREATE TABLE numbers (my_number
INT(4) ZEROFILL );
Query OK, 0 rows affected (0.01 sec) mysql> INS ERT INTO numbers
VALUES(3),(33),(333),(3333),(33333),(333333);
Query OK, 6 rows affected (0.00 sec) Records; 6 Duplicates: 0 Warnings: 0
Как видно, числа, которые имеют меньше, чем четыре цифры, дополняются нулями, а числа, состоящие из более, чем четырех цифр, отображаются с неизмененными шириной и парамет-
рами ZEROFILL.
Если использовать параметр ZEROFILL, MySQL автоматически добавит в декларацию ключевое словоUNSIGNED (поскольку дополнение нулями имеет смысл только в контексте положительных чисел).
DECIMAL [(ширина[,дробь])] [UNSIGNED] [ZEROFILL]. Широко используемый числовой тип данных. Хранит число с фиксированной точкой(например, для записи заработной платы или расстояния) с указанной шириной, деся-
123
тичной точкой идробью, следующей после десятичной точки. Так, столбец, задекларированный как price DECIMAL (4,2), должен использоваться для хранения значений в диапазоне от-99.99 до 99.99. Если попытаемся сохранить значение не из этого диапазона, то оно будет сохранено как самое близкое значение в дозволенном диапазоне. Например, число 100 будет сохранено как 99.99, а число -100 — как -99.99. Отметим, что версии MySQL до 5.03 позволяли использовать дополнительную цифру для положительных значений (можно было хранить числа от-99.99 до 999.99). Параметр ширина является опциональным. Если этот параметр пропущен, то используется значение10. Максимальное значение параметра ширина составляет 255.
Количество цифр после десятичной точки(дробь) является опциональным. Если пропустить этот параметр, то по умолчанию будет задано значение0. Максимальное значение параметра дробь должно быть в два раза меньше, чем значение ширины. При хранении только положительных чисел используйте ключевое слово UNSIGNED, как в случае с типом INT. Если требуется дополнение нулями, используйте ключевое слово ZEROFILL точно таким же образом, как и в случае с типом INT. Параллельно с ключевым словом DECIMAL используют три взаимозаменяемых варианта: DEC, NUMERIC и FIXED.
До выхода версии MySQL 5.0.3 столбец DECIMAL хранился в виде строки и требовал для этого количество байтов, равное длине значения (плюс два байта для знака минус и десятичной точки). Начиная с версии 5.0.3, стал применяться двоичный формат, который использует четыре байта для каждых девяти цифр. В обоих подходах извлекаемое значение идентично хранящемуся значению. Тем не менее, это правило не всегда выполняется при использовании других типов, содержащих десятичные точки, на-
пример FLOAT и DOUBLE.
DATE . Позволяет хранить и отображать дату в формате
YYYY-MM-DD для диапазона от 1000-01-01 до 9999-12-31. Даты всегда следует вводить так: год, месяц, день. Однако формат ввода может варьироваться, как показано в следующих примерах.
YYYY-MM-DD или YY-MM-DD можно по своему усмотрению задать годы из двух или четырех цифр (с любыми знаками
124
пунктуации). Рекомендуется использовать версию из четырех цифр, чтобы избежать путаницы с веком. При использовании версии из двух цифр числа от70 до 99 интерпретируются как годы с 1970 по 1999, а числа с 00 до 69 — как годы с 2000 по 2069.
YYYY/MM/DD, YYYY:MM:DD, YY/MM/DD MySQL позволяет использовать любые знаки пунктуации для разделения компонентов даты. Рекомендуется использовать тире и избегать ввода года в виде двух цифр.
YYYY-M-D, YYYY-MM-D или YYYY-M-DD При использова-
нии знаков пунктуации(разрешены все знаки) дни и месяцы можно вводить в виде одной цифры. Например, 2 февраля 2006 года — указать как 2006-2-2. Можно использовать формат года в виде двух цифр, однако по уже известным причинам это не рекомендкется делать.
YYYYMMDD или YYMMDD Знаки пунктуации можно пропускать в обоих стилях дат, однако длина цифровых последовательностей должна составлять шесть или восемь цифр.
Можно ввести дату в форматах даты и времени для типов данных DATE-STAMP и TIMESTAMP, описанных далее, однако в столбце типа DATE хранится только компонент даты. Независимо
от типа ввода форматом хранения и отображения всегда будет YYYY-MM-DD. Нулевая дата 0000-00-00 разрешена во всех верси-
ях и может использоваться для представления неизвестного или фиктивного значения. Если введенная дата не входит в диапазон, то будет сохранена нулевая дата0000-00-00. По умолчанию, начиная с версии MySQL 5.0.2, нулевая дата сохраняется при вставке недействительной даты, как например 2007-02-31. До выхода этой версии недействительные даты сохранялись вместе с месяцем в диапазоне от 0 до 12 и днем в диапазоне о 0 до 31. Рассмотрим пример:
mysql> CREATE TABLE testdate (mydate
DATE);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO testdate VALUES
('2007/02/0');
Query OK, 1 row affected (0.00 sec)
125
mysql> INSERT INTO testdate VALUES
('2007/02/1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testdate VALUES
('2007/02/31');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testdate VALUES
('2007/02/100');
Query OK. 1 row affected, 1 warning (0.00
sec)
Используя более старую версиюMySQL (до 5.0.2), получили бы следующее:
|
mysql> SELECT * FROM testdate; |
|
|
+ ---------- ------ |
+ |
|
| mydate |
| |
+ |
------- --- + |
|
|
| 2007 - 02 - 00 | |
|
| 2007-02-01 | |
||
| 2007-02-31 | |
||
| 0000-00-00 | |
||
+ -- -- |
-- --- |
+ |
|
4 rows in set (0.00 sec) |
|
|
В версии , начиная с 5.0.2, получим такой результат: |
|
|
mysql> SELECT * FROM testdate; |
|
|
+ ----------- |
+ |
|
| mydate |
| |
+----------- |
|
+ |
|
| 2007 - 02 - 00 | |
|
| 2007-02-01 | |
||
| 0000-00-00 | |
||
| 0000-00-00 | |
||
+---------------- |
|
+ |
|
4 rows in set (0.01 sec) |
|
Отметим также, что дата отображается в форматеYYYY- MM-DD независимо от того, как она была введена.
126
TIME. Хранит время в форматеHHH:MM:SS, в диапазоне от -838:59:59 до 838:59:59. В этом формате можно хранить значения вне диапазона 24-часовых суток, чтобы разрешать вычислять и сохранять разницу между временными значениями(до 34 дн., 22 ч, 59 мин и 59 с). Время всегда следует вводить в порядке дни, часы, минуты и секунды с помощью следующих форматов:
–DD HH:MM:SS, HH:MM:.SS, DD НН:ММ, НН:ММ, DD
ННили SS Параметр DD представляет в виде одной или двух цифр значение дней в диапазоне от 0 до 34. Значение DD отделено от значения часов НН пробелом, а остальные компоненты разделены двоеточием. Если, к примеру, вставить в столбец типа TIME значение 2 13:25:59, то будет сохранено значение 61:25:59, поскольку сумма двух дней (48 ч) и 13 ч составляет 61 ч. Если попытаться вставить значение, не входящее в диапазон, то появится предупреждение, а значение будет ограничено возможным максимальным временным значением. Подобным образом, если попытаться вставить некорректное значение, то отобразится предупреждение, а сохранено будет нулевое значение. Для просмотра деталей предупреждения, сгенерированного предыдущей инструкцией SQL, можно использовать инструкциюSHOW WARNINGS.
–H:M:S Возможны также комбинации из одной, двух и трех цифр. Вставляя и обновляя даты, вы можете использовать различные комбинации цифр. MySQL преобразует их во внутренний временной формат и отображает соответствующим обра-
зом. Например, 1:1:3 является эквивалентом 01:12:03. Можно смешивать различные комбинации цифр. Так, 1:12:3 является эквивалентом 01:12:03. Рассмотрим примеры:
mysql> CREATE TABLE mytime (testtime
TIME);
Query OK, 0 rows affected (0.12 sec) mysql> INSERT INTO mytime VALUES
-> ('-1:1:1'), ('1:1:1'), -> ('1:23:45'), ('123:4:5'),
-> ('123:45:6'), ('-123:45:6');
Query OK, 4 rows affected (0.00 sec)
127
Records: 4 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM mytime;
+------------ |
+ |
Itesttime |
| |
+------------+ |
|
|-01:01:01 |
| |
|01:01:01 | |
|
|01:23:45 | |
|
|123:04:05 |
| |
|123:45:06 |
| |
|-123:45:06 |
| |
+---- +
5 rows in set (0.01 sec)
Обратите внимание, что часы отображаются в виде двухзначных чисел в диапазоне от -99 до +99.
– HHMMSS, MMSS и SS Знаки пунктуации можно пропустить, однако последовательности должны состоять из двух, четырех или шести цифр. Отметим, что самая правая пара цифр всегда интерпретируется как значение SS (секунды), самая правая пара перед ней (если она есть) интерпретируется как ММ (минуты), а третья пара цифр (в последовательности первая) — как НН (часы). В результате такое значение, как 1222, интерпретируется как 12 мин и 22 с, а не как 12 ч и 22 мин.
Можно вводить время вместе с датой в форматах, описанных для типов DATETIME и TIMESTAMP, однако компонент времени сохраняется в столбце типа TIME. Независимо от типа ввода типом хранения и отображения всегда будетНН:MM:.SS. Нулевое значение 00:00:00 можно использовать для представления неизвестного или фиктивного значения. Если введенное значение недействительно или не входит в диапазон, то сохраняется нулевое время 00:00:00. Тип TIME имеет дополнительный компонент дроби для хранения дробей(или мантисс) секунд, однако этот дробный компонент будет отсечен перед сохранением сервером
MySQL.
TIMESTAMP. Хранит и отображает пару дата-время в формате YYYY-MM-DD НН:MM:SS и в диапазоне от1970-01-01
128
00:00:00 до 2037 года. Поведение этого типа данных зависит от версии MySQL (что, судя по всему, будет продолжаться и далее). В данном разделе описывается версия, реализованная с MySQL 4.1. Ключевые возможности TIMESTAMP — двояки. Во-первых, если использовать в этом форматеNULL, то будут заданы текущие время и дата. Во-вторых, столбец TIMESTAMP в таблице, выбранный разработчиком, может автоматически обновляться текущими датой и временем при вставке или обновлении строки. Кроме того, всегда есть возможность явным образом присвоить
столбцу значение независимо от автоматического обновления этого столбца. Опция автоматического обновления описана далее в этом разделе. Необновляемым близким эквивалентом этого ти-
па является тип DATETIME, который мы обсудим чуть позже. Сохраняемое значение всегда соответствует шаблону YYYY-
MM-DD HH:MM:SS, однако значение можно вводить и в других форматах.
- YYYY-MM-DD HH:MM:SS или YY-MM-DD HH:MM:SS. Здесь для значений даты и времени действуют те же ограничения, что и для значений типовDATE и TIME, описанных ранее (однако в отношении MySQL 5.0.2 нулевые значения не разрешены). Существует возможность использовать любые знаки пунктуации, например 2005/02/15 12+22+23.
- YYYYMMDDHHMMSS или YYMMDDHHMMSS.
Знаки пунктуации можно пропустить, однако длина строк должна составлять 12 или 14 цифр. Рекомендуется использовать только недвусмысленную версию из12 цифр по причинам, указанным для типа DATE. Можно задавать значения с другой длиной без разделителей, однако не рекомендуется делать это.
Рассмотрим детально возможность автоматического обновления. При вставке или обновлении автоматическое присвоение текущих даты и времени может назначаться только для столбца типа TIMESTAMP. Управление этим столбцом осуществляется путем выполнения следующих операций при создании таблицы.
129
1.Выбрать столбец, который следует автоматически об-
новлять.
2.Если в таблице имеются другие столбцыTIMESTAMP, задать им в инструкции CREATE TABLE постоянное значение по умолчанию (DEFAULT 0).
3.Определить поведение для автоматического обновления
столбца.
Чтобы задавать временную метку только при вставке но-
вой |
строки |
в , |
дотабавьтелицу |
DEFAULT |
CURRENT_TIMESTAMP в конец декларации столбца. |
|
|||
|
Если не нужна временная метка по умолчанию, однако тре- |
|||
буется задавать текущее время каждый раз при обновлении дан- |
||||
ных |
в строке, добавьте ON UPDATE CURRENT_TIMESTAMP в |
|||
конец кода объявления столбца. |
|
|
||
|
При необходимости |
использовать оба |
вышеописанных |
|
подхода, то есть задавать текущее время при добавлении новой строки или обновлении уже существующей, добавьте DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP в
конец кода объявления столбца.
Если для столбца типа TIMESTAMP вы зададите DEFAULT NULL, то этот код будет интерпретироваться по-разному в зависимости от наличия других столбцовTIMESTAMP в таблице перед этим. Выражение DEFAULT NULL обрабатывается как
DEFAULT CURRENT_TIMESTAMP для первого столбца с вре-
менной меткой и как DEFAULT 0 для остальных столбцов. Рассмотрим пример:
mysql> CREATE TABLE mytime (id INT NOT
NULL,
-> changetime TIMESTAMP DEFAULT -> CURRENT_TIMESTAMP ON UPDATE -> CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytime VALUES (1,
''),
-> (2,'2006-07-16
-> 1:2:3'), (3, NULL);
130
