Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РУБД - Теория по SQL .doc
Скачиваний:
4
Добавлен:
27.08.2019
Размер:
691.71 Кб
Скачать

Применение подзапросов в операторах изменения данных

К операторам языка DML, кроме оператора SELECT, относятся операторы, позволяющие изменять данные в таблицах. Это оператор INSERT, выполняющий добавление одной или нескольких строк в таблицу, оператор DELETE, удаляющий из таблицы одну или несколько строк, и оператор UPDATE, изменяющий значения столбцов таблицы.

Оператор INSERT может добавлять в таблицу как одну, так и несколько строк. Список полей (field .,…) указывает имена полей и порядок занесения в них значений из списка значений, определяемого фразой VALUES, или как результат выполнения подзапроса.

Следующий оператор INSERT демонстрирует копирование строк таблицы tbl2, выполняемое на основе подзапроса:

INSERT INTO tbl1(f1,f2,f3) (SELECT f1,f2,f3 FROM tbl2);

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

Оператор DELETE используется для удаления из таблицы строк, указанных условием во фразе WHERE (поисковое удаление, searched deletion

Никогда нельзя забывать, что если фраза WHERE будет отсутствовать или предикат во фразе WHERE будет всегда принимать значение TRUE, то оператор DELETE удалит из таблицы все строки.

Оператор UPDATE применяется для внесения изменений в данные таблиц.

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

Переменные пользователя

Для конкретного процесса пользователь может определить локальные переменные, которые в MySQL обозначаются как @variablename. Имя локальной переменной может состоять из буквенно-цифровых символов установленного в данное время алфавита и символов ‘_’, ‘$’, and ‘.’. Тип кодировки по умолчанию - ISO-8859-1 Latin1, он может быть изменен указанием иного типа в аргументе параметра --default-character-set mysqld

Локальные переменные не требуют инициализации. Они содержат значение NULL по умолчанию; в них могут храниться целые числа, вещественные числа или строковые величины. При запуске конкретного процесса все объявленные в нем локальные переменные автоматически активизируются.

Локальную переменную можно объявить, используя синтаксис команды SET:

SET @variable= { integer expression | real expression | string expression }

[,@variable= ...].

Можно также определить значение переменной иным способом, без команды SET. Однако в этом случае в качестве оператора присвоения более предпочтительно использовать оператор ':=', чем оператор ‘=’, так как последний зарезервирован для сравнения выражений, не связанных с установкой переменных:

mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;

+----------------------+------+------+------+

| @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 |

+----------------------+------+------+------+

| 5 | 5 | 1 | 4 |

+----------------------+------+------+------+

Введенные пользователем переменные могут применяться только в составе выражений и там, где выражения допустимы. Заметим, что в область их применения в данное время не включается контекст, в котором явно требуется число, например, условие LIMIT в команде SELECT или выражение IGNORE number LINES в команде LOAD DATA.

Примечание: в команде SELECT каждое выражение оценивается только при отправлении клиенту. Это означает, что в условиях HAVING, GROUP BY, or ORDER BY не следует ссылаться на выражение, содержащее переменные, которые введены в части SELECT этой команды. Например, следующая команда НЕ будет выполняться так, как ожидалось:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

Причина в том, что переменная @aa не будет содержать значения текущей строки, в то время как значение id в предыдущем выражении является строкой.

Действует правило никогда не создавать и не использовать одну и ту же переменную в одном и том же выражении SQL.

Полнотекстовый поиск в MySQL

Полнотекстовые индексы в MySQL обозначаются как индексы типа FULLTEXT. Эти индексы могут быть созданы в таблицах MyISAM в столбцах VARCHAR и TEXT во время создания таблицы командой CREATE TABLE или добавлены позже с помощью команд ALTER TABLE или CREATE INDEX. Загрузка больших массивов данных в таблицу будет происходить намного быстрее, если таблица не содержит индекс FULLTEXT, который затем создается командой ALTER TABLE (или CREATE INDEX). Загрузка данных в таблицу, уже имеющую индекс FULLTEXT, будет более медленной.

Полнотекстовый поиск выполняется с помощью функции MATCH().

mysql> CREATE TABLE articles (

id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,

title VARCHAR(200),

body TEXT,

FULLTEXT (title,body)

);

Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES

-> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),

-> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),

-> (NULL,'Optimising MySQL','In this tutorial we will show ...'),

-> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),

-> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),

-> (NULL,'MySQL Security', 'When configured properly, MySQL ...');

Query OK, 6 rows affected (0.00 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM articles

WHERE MATCH (title,body) AGAINST ('database');

+----+-------------------+------------------------------------------+

| id | title | body |

+----+-------------------+------------------------------------------+

| 5 | MySQL vs. YourSQL | In the following database comparison ... |

| 1 | MySQL Tutorial | DBMS stands for DataBase ... |

+----+-------------------+------------------------------------------+

2 rows in set (0.00 sec)

Функция MATCH() выполняет поиск в естественном языке, сравнивая строку с содержимым текста (совокупность одного или более столбцов, включенных в индекс FULLTEXT). Строка поиска задается как аргумент в выражении AGAINST(). Поиск выполняется без учета регистра символов. Для каждой строки столбца в заданной таблице команда MATCH() возвращает величину релевантности, т.е. степень сходства между строкой поиска и текстом, содержащимся в данной строке указанного в списке оператора MATCH() столбца.

Когда команда MATCH() используется в выражении WHERE (см. пример выше), возвращенные строки столбцов автоматически сортируются, начиная с наиболее релевантных. Величина релевантности представляет собой неотрицательное число с плавающей точкой. Релевантность вычисляется на основе количества слов в данной строке столбца, количества уникальных слов в этой строке, общего количества слов в тексте и числа документов (строк), содержащих отдельное слово.

Поиск возможен также в логическом режиме, это объясняется ниже в данном разделе.

Предыдущий пример представляет собой общую иллюстрацию использования функции MATCH(). Строки возвращаются в порядке уменьшения релевантности.

В следующем примере показано, как извлекать величины релевантности в явном виде. В случае отсутствия выражений WHERE и ORDER BY возвращаемые строки не упорядочиваются.

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;

+----+-----------------------------------------+

| id | MATCH (title,body) AGAINST ('Tutorial') |

+----+-----------------------------------------+

| 1 | 0.64840710366884 |

| 2 | 0 |

| 3 | 0.66266459031789 |

| 4 | 0 |

| 5 | 0 |

| 6 | 0 |

+----+-----------------------------------------+

6 rows in set (0.00 sec)

Следующий пример - более сложный. Запрос возвращает значение релевантности и, кроме того, сортирует строки в порядке убывания релевантности. Чтобы получить такой результат, необходимо указать MATCH() дважды. Это не приведет к дополнительным издержкам, так как оптимизатор MySQL учтет, что эти два вызова MATCH() идентичны, и запустит код полнотекстового поиска только однажды.

mysql> SELECT id, body, MATCH (title,body) AGAINST

-> ('Security implications of running MySQL as root') AS score

-> FROM articles WHERE MATCH (title,body) AGAINST

-> ('Security implications of running MySQL as root');

+----+-------------------------------------+-----------------+

| id | body | score |

+----+-------------------------------------+-----------------+

| 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |

| 6 | When configured properly, MySQL ... | 1.31140957288 |

+----+-------------------------------------+-----------------+

2 rows in set (0.00 sec)

Для разбивки текста на слова MySQL использует очень простой синтаксический анализатор. «Словом» является любая последовательность символов, состоящая из букв, чисел, знаков ‘'’ и ‘_’. Любое «слово», присутствующее в стоп-списке (stopword) или просто слишком короткое (3 символа или меньше), игнорируется.

Каждое правильное слово в наборе проверяемых текстов и в данном запросе оценивается в соответствии с его важностью в этом запросе или наборе текстов. Таким образом, слово, присутствующее во многих документах, будет иметь меньший вес (и даже, возможно, нулевой), как имеющее более низкое смысловое значение в данном конкретном наборе текстов. С другой стороны, редко встречающееся слово получит более высокий вес. Затем полученные значения весов слов объединяются для вычисления релевантности данной строки столбца.

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

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');

Empty set (0.00 sec)

Поиск по слову ``MySQL'' в предыдущем примере не приводит к каким-либо результатам, так как это слово присутствует более чем в половине строк. По существу, данное слово целесообразно трактовать как стоп-слово (т.е. слово с нулевой смысловой ценностью). Это наиболее приемлемое решение - запрос на естественном языке не должен возвращать каждую вторую строку из таблицы размером 1Гб.

Маловероятно, что слово, встречающееся в половине строк таблицы, определяет местонахождение релевантных документов. На самом деле, наиболее вероятно, что будет найдено много не относящихся к делу документов. Общеизвестно, что такое случается слишком часто при попытке найти что-либо в Интернет с помощью поисковых машин. Именно на этом основании подобным строкам должно быть назначено низкое смысловое значение в данном конкретном наборе данных.

В MySQL 4.0.1 возможен полнотекстовый поиск также и в логическом режиме с использованием модификатора IN BOOLEAN MODE.

mysql> SELECT * FROM articles WHERE MATCH (title,body)

-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

+----+------------------------------+-------------------------------------+

| id | title | body |

+----+------------------------------+-------------------------------------+

| 1 | MySQL Tutorial | DBMS stands for DataBase ... |

| 2 | How To Use MySQL Efficiently | After you went through a ... |

| 3 | Optimising MySQL | In this tutorial we will show ... |

| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |

| 6 | MySQL Security | When configured properly, MySQL ... |

+----+------------------------------+-------------------------------------+

Данный запрос вывел все строки, содержащие слово ``MySQL'' (заметьте, 50-процентная пороговая величина здесь не используется), но эти строки не содержат слова ``YourSQL''. Следует отметить, что логический режим поиска не сортирует автоматически строки в порядке уменьшения релевантности. Это видно по результату предыдущего запроса, где строка с наиболее высокой релевантностью (содержащая слово ``MySQL'' дважды) помещена последней, а не первой. Логический режим полнотекстового поиска может работать даже без индекса FULLTEXT, хотя и очень медленно.

В логическом режиме полнотекстового поиска поддерживаются следующие операторы:

  • + Предшествующий слову знак ``плюс'' показывает, что это слово должно присутствовать в каждой возвращенной строке.

  • - Предшествующий слову знак ``минус'' означает, что это слово не должно присутствовать в какой-либо возвращенной строке.

  • По умолчанию (если ни плюс, ни минус не указаны) данное слово является не обязательным, но содержащие его строки будут оцениваться более высоко. Это имитирует поведение команды MATCH() ... AGAINST() без модификатора IN BOOLEAN MODE.

  • < > Эти два оператора используются для того, чтобы изменить вклад слова в величину релевантности, которое приписывается строке. Оператор < уменьшает этот вклад, а оператор > - увеличивает его. См. пример ниже.

  • ( ) Круглые скобки группируют слова в подвыражения.

  • ~ Предшествующий слову знак ``тильда'' воздействует как оператор отрицания, обуславливая негативный вклад данного слова в релевантность строки. Им отмечают нежелательные слова. Строка, содержащая такое слово, будет оценена ниже других, но не будет исключена совершенно, как в случае оператора - ``минус''.

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

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

Ниже приведен ряд примеров:

  • apple banana находит строки, содержащие по меньшей мере одно из этих слов.

  • +apple +juice ... оба слова.

  • +apple macintosh ... слово ``apple'', но ранг строки выше, если она также содержит слово ``macintosh''.

  • +apple -macintosh ... слово ``apple'', но не ``macintosh''.

  • +apple +(>pie <strudel) ... ``apple'' и ``pie'', или ``apple'' и ``strudel'' (в любом порядке), но ранг ``apple pie'' выше, чем ``apple strudel''.

  • apple* ... ``apple'', ``apples'', ``applesauce'', и ``applet''.

  • "some words" ... ``some words of wisdom'', но не ``some noise words''.

Ограничения для полнотекстового поиска

  • Все параметры функции MATCH() должны быть столбцами одной и той же таблицы, т.е. частью одного и того же индекса FULLTEXT, за исключением работы MATCH() в режиме IN BOOLEAN MODE.

  • Список столбцов в команде MATCH() должен точно соответствовать списку столбцов в определении индекса FULLTEXT для этой таблицы, за исключением работы данной функции MATCH() в режиме IN BOOLEAN MODE.

  • Аргумент в выражении AGAINST() должен быть неизменяемой строкой.

select_expression может содержать следующие функции и операторы:

+ - * /

Арифметические действия.

%

Остаток от деления (как в C)

| &

Битовые функции (используется 48 бит).

- С

Смена знака числа.

<<

Осуществляет побитовый левый сдвиг целочисленного значения.

>>

Осуществляет побитовый правый сдвиг целочисленного значения.

BETWEEN(A,B,C)

(A >= B) AND (A <= C).

BIT_COUNT()

Количество бит.

ELT(N,a,b,c,d)

Возвращает a, если N == 1, b, если N == 2 и т. д. a, b, c, d строки.

ELT(3, “First”, “Second”, “Third”, “Fourth”) вернет “Third”.

FIELD(Z,a,b,c)

Возвращает a, если Z == a, b, если Z == b и т. д. a, b, c, d строки.

FIELD(“Second”, “First”, “Second”, “Third”, “Fourth”) вернет “Second”.

IF(A,B,C)

Если A истина (!= 0 and != NULL), то вернет B, иначе вернет C.

IFNULL(A,B)

Если A не null, вернет A, иначе вернет B.

ISNULL(A)

Вернет 1, если A == NULL, иначе вернет 0. Эквивалент ('A == NULL').

NOT !

NOT, вернет TRUE (1) или FALSE (0).

OR, AND

Вернет TRUE (1) или FALSE (0).

SIGN()

Вернет -1, 0 или 1 (знак аргумента).

expr LIKE expr

Вернет TRUE (1) или FALSE (0).

expr NOT LIKE expr

Вернет TRUE (1) или FALSE (0).

expr REGEXP expr

Проверяет строку на соответствие регулярному выражению expr.

expr NOT REGEXP expr

Проверяет строку на соответствие регулярному выражению expr.

select_expression может также содержать математические функции.

ABS()

Абсолютное значение (модуль числа).

EXP()

Экспонента.

FORMAT(nr,NUM)

Форматирует число в формат '#,###,###.##' с NUM десятичных цифр.

LOG()

Логарифм.

MOD()

Остаток от деления (аналог %).

POW()

Степень.

ROUND()

Округление до ближайшего целого числа.

RAND([integer_expr])

Случайное число типа float, 0 <= x <= 1.0, используется integer_expr как значение для запуска генератора.

SQRT()

Квадратный корень.

select_expression может также содержать одну или больше следующих строковых функций.

CONCAT()

Объединение строк.

INTERVAL(A,a,b,c,d)

Возвращает 1, если A == a, 2, если A == b... Если совпадений нет, вернет 0. A,a,b,c,d... строки.

INSERT(org,strt,len,new)

Заменяет подстроку org[strt...len(gth)] на new. Первая позиция строки=1.

LCASE(A)

Приводит A к нижнему регистру.

LEFT()

Возвращает строку символов, отсчитывая слева.

LENGTH()

Длина строки.

LOCATE(A,B)

Позиция подстроки B в строке A.

LOCATE(A,B,C)

Позиция подстроки B в строке A, начиная с позиции C.

LTRIM(str)

Удаляет все начальные пробелы из строки str.

REPLACE(A,B,C)

Заменяет все подстроки B в строке A на подстроку C.

RIGHT()

Get string counting from right.

RTRIM(str)

Удаляет хвостовые пробелы из строки str.

STRCMP()

Возвращает 0, если строки одинаковые.

SUBSTRING(A,B,C)

Возвращает подстроку из A, с позиции B до позиции C.

UCASE(A)

Переводит A в верхний регистр.

Несколько просто полезных функций, которые тоже можно применить в select_expression.

CURRDATE()

Текущая дата.

DATABASE()

Имя текущей базы данных, из которой выполняется выбор.

FROM_DAYS()

Меняет день на DATE.

NOW()

Текущее время в форматах YYYYMMDDHHMMSS или “YYYY-MM-DD HH:MM:SS”.

PASSWORD()

Шифрует строку.

PERIOD_ADD(P:N)

Добавить N месяцев к периоду P (в формате YYMM).

PERIOD_DIFF(A,B)

Возвращает месяцы между A и B. Обратите внимание, что PERIOD_DIFF работает только с датами в форме YYMM или YYYMM.

TO_DAYS()

Меняет DATE (YYMMDD) на номер дня.

USER()

Возвращает логин текущего пользователя.

WEEKDAY()

Возвращает день недели (0 = понедельник, 1 = вторник, ...).

Следующие функции могут быть использованы в предложении GROUP:

AVG()

Среднее для группы GROUP.

SUM()

Сумма элементов GROUP.

COUNT()

Число элементов в GROUP.

MIN()

Минимальный элемент в GROUP.

MAX()

Максимальный элемент в GROUP.

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

Пример: “SUM(value/10)” нормально, но вот “SUM(value)/10” уже нет!

Функции

Для функций, работающих с позициями в строке, нумерация позиций начинается с 1.

COUNT(expr) Возвращает количество величин со значением, не равным NULL, в строках, полученных при помощи команды SELECT:

SELECT student.student_name,COUNT(*) FROM student,course

WHERE student.student_id=course.student_id GROUP BY student_name;

COUNT(*) оптимизирована для очень быстрого возврата результата при условии, что команда SELECT извлекает данные из одной таблицы, никакие другие столбцы не обрабатываются и функция не содержит выражения WHERE. Например SELECT COUNT(*) FROM student;

COUNT(DISTINCT expr,[expr...]) Возвращает количество различающихся величин со значением, не равным NULL: SELECT COUNT(DISTINCT results) FROM student;

AVG(expr) Возвращает среднее значение аргумента expr:

SELECT student_name, AVG(test_score) FROM student GROUP BY student_name;

MIN(expr) , MAX(expr) Возвращает минимальную или максимальную величину аргумента expr. Функции MIN() и MAX() могут принимать строковый аргумент; в таких случаях они возвращают минимальную или максимальную строковую величину.

SELECT student_name, MIN(test_score), MAX(test_score) FROM student GROUP BY student_name;

SUM(expr) Возвращает сумму величин в аргументе expr. Обратите внимание: если возвращаемый набор данных не содержит ни одной строки, то функция возвращает NULL!

Например, SELECT order.custid,customer.name,MAX(payments) FROM order,customer WHERE order.custid = customer.custid GROUP BY order.custid;

value BETWEEN value1 AND value2 Выбирает записи, если value находится в диапазоне между valuel и value2 или равно одному из них.

value IN (valuel,value2,... ) Выбирает записи, если value находится среди указанных значений.

value NOT IN (value1, value2,.., ) Выбирает записи, если value не находится среди указанных значений.

valuel LIKE value2 Сравнивает value1 и value2 и выбирает записи, где они совпадают. Значение справа может содержать знак подстановки ' %', которому удовлетворяет любое число символов (включая 0) и знак '_', заменяющий ровно один символ. Чаще всего используется сравнение поля с некоторым символом и знаком подстановки ( SELECT name FROM people WHERE name LIKE 'B%' ).

valuel NOT LIKE value2 Сравнивает valuel и value2 и выбирает записи, где они не совпадают. Команда идентична NOT (valuel LIKE value2).

valuel REGEXP/RLIKE value2 Сравнивает valuel и value2, используя расширенный синтаксис регулярных выражений, и выбирает записи, если они совпадают. Значение справа может содержать полные подстановочные выражения ( SELECT name FROM people WHERE name RLIKE '^B. *').

valuel NOT REGEXP value2 Сравнивает valuel и value2, используя расширенный синтаксис регулярных выражений, и выбирает записи, если они не совпадают. Команда идентична NOT (valuel REXEXP value2). Предложение WHERE вернет все полученные в выражении значения, которые отличаются от 0 или NULL (т. е. все, что не является логически ложным). Поэтому SELECT age FROM people WHERE age>10 вернет только те записи, где возраст больше 10.

ПРИЛОЖЕНИЕ В

ПРИМЕРЫ ПОСТРОЕНИЯ ЗАПРОСОВ

mysql> SELECT VERSION(), CURRENT_DATE;

VERSION()

CURRENT_DATE

3.22.20a-log

1999-03-19