Чувствительность к регистру postgres: последствия использования lower ()

Использование SELECT и предикатов IN, OR, BETWEEN, LIKE

Предикаты — слова IN, OR, BETWEEN, LIKE в секции WHERE — также позволяют выбрать определённые диапазоны значений (IN, OR, BETWEEN) или
значения в строках (LIKE), которые требуется выбрать из таблицы. Запросы с предикатами IN, OR, BETWEEN имеют
следующий синтаксис:

SELECT ИМЯ_СТОЛБЦА FROM ИМЯ_ТАБЛИЦЫ
WHERE ЗНАЧЕНИЕ
ПРЕДИКАТ (IN, OR, BETWEEN) (ЗНАЧЕНИЯ, УКАЗЫВАЮЩИЕ ДИАПАЗОН)

Запросы с предикатом LIKE имеют следующий синтаксис:

SELECT ИМЯ_СТОЛБЦА FROM ИМЯ_ТАБЛИЦЫ
WHERE ИМЯ_СТОЛБЦА LIKE
ВЫРАЖЕНИЕ

Пример 7. Пусть требуется выбрать из таблицы Staff имена, должности
и число отработанных лет сотрудников, работающих в отделах с номерами 20 или 84.
Это можно сделать следующим запросом (на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT Name, Job, Years
FROM Staff
WHERE Dept IN (20, 84)

Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката IN.

Пример 8. Пусть теперь требуется выбрать из таблицы Staff те же данные,
что и в предыдущем примере. Запрос со словом OR аналогичен запросу со словом IN и перечислением интересующих
значений в скобках. Запрос будет следующим (на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT Name, Job, Years
FROM Staff
WHERE Dept=20 OR Dept=84

Пример 9. Выберем из той же таблицы имена, должности
и число отработанных лет сотрудников, зарплата которых между 15000 и 17000 включительно (на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT Name, Job, Years
FROM Staff
WHERE Salary BETWEEN 15000 AND 17000

Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката BETWEEN.

Предикат LIKE используется для выборки тех строк, в значениях которых встречаются символы, указанные
после предиката между апострофами (‘).

Пример 10. Выберем из той же таблицы имена, должности
и число отработанных лет сотрудников, имена которых начинаются с буквы S и состоят из 7 символов
(на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT Name, Job, Years
FROM Staff
WHERE Name LIKE ‘S_ _ _ _ _ _’

Символ подчёркивания (_) означает любой символ. Результат выполнения запроса:

Пример 11. Выберем из той же таблицы имена, должности
и число отработанных лет сотрудников, имена которых начинаются с буквы S и содержат любые другие буквы
в любом количестве (на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT Name, Job, Years
FROM Staff
WHERE Name LIKE ‘S%’

Символ процентов (%) означает любое количество символов. Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката LIKE.

Значения, указанные с использованием предикатов IN, OR, BETWEEN, LIKE можно инвертировать при помощи
слова NOT. Тогда запрашиваемые данные будут иметь противоположный смысл. Если мы используем NOT IN (20, 84),
то будут выведены данные сотрудников, которые работают во всех отделах, кроме имеющих номера 20 и 84.
С использованием NOT BETWEEN 15000 AND 17000 можно получить данные сотрудников, зарплата которых не
входит в интервал от 15000 до 17000. Запрос с NOT LIKE выведет данные сотрудников, чьи имена не начинаются
или не содержат символов, указанных с NOT LIKE.

Обсуждение¶

Конечно, этот рецепт тривиален. Но я включил его, чтобы воспользоваться случаем и обсудить недостатки решения для XPath 1.0. Преобразование регистров – тривиальная задача лишь до тех пор, пока текст записан в одной локали.

В английском тексте вам вряд ли придется столкнуться со специальными символами, которые содержат диакритические знаки, или такими преобразованиями, когда один символ превращается в два. Самый распространенный пример – немецкий язык, в котором строчная буква Я (β-цет) в верхнем регистре записывается как SS. Во многих современных языках программирования есть функции преобразования регистра, учитывающие локаль, но в XSLT прямой поддержки этой идеи нет. Это печально, поскольку другие средства поддержки интернационализации в XSLT все же включены.

Небольшого улучшения можно добиться, определив для каждого преобразования отдельные XML-компоненты, как в следующем примере:

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

В-третьих, наше намерение вызвать функцию становится очевидно всякому человеку, читающему код. Некоторые ревнители чистоты могут возразить против переноса третьего параметра в макрос, но я думаю, что так код читать проще. Если вы тоже сторонник пуризма, то можете писать так: .

Я не часто встречал употребление компонентов в книгах, посвященных XSLT, но полагаю, что этот прием обладает рядом достоинств. Вообще, одно из преимуществ записи XSLT-программы в синтаксической нотации XML заключается в том, что вы получаете возможность пользоваться всеми средствами XML, в том числе и определением компонентов. Если вы намереваетесь применять эту технику и планируете написать достаточно много таблиц стилей, то подумайте над тем, чтобы поместить общие определения компонентов во внешний файл и включать их, как показано в примере 2.6. Можно также хранить эти значения в глобальных переменных во внешней таблице стилей и импортировать при необходимости. Такую альтернативу предпочитают многие ветераны XSLT.

Пример 2.6. Файл standard.ent

Воспользоваться параметрическим компонентом, определенным в файле , можно, как показано в примере 2.7.

Пример 2.7. Таблица стилей, в которой используется файл

Реализация преобразования регистра, предложенная Стивом Болом (Steve Ball) и работающая практически во всех случаях, достигает этого за счет включения большинства общеупотребительных символов Unicode в строки, записанные в верхнем и нижнем регистре. При этом немецкая буква β обрабатывается специально.

XSLT 2.0

Добавленные в XPath 2.0 функции и решают большую часть проблем, связанных с преобразованием регистра в не-английских алфавитах.

Единственное исключение касается преобразований с учетом местных особенностей. Лучше не пользоваться этими функциями для сравнения строк без учета регистра. Вместо этого обратитесь к функции , указав таблицу сравнения (collation), в которой регистр игнорируется. Пользователь Saxon 8.x найдет информацию о таблицах сравнения на страницах http://www.saxonica.com/documentation/conformance/collation-uri.html и http://www.saxonica.com/documentation/extensions/instructions/collation.html.

REPLACE

Функция replace позволяет найти в значении поля подстроку и заменить ее на новое значение. У этой функции три параметра:

  1. Строка, в которой нужно искать подстроку;
  2. Подстрока, которую ищем;
  3. Значение, которое нужно подставить.

Посмотрим пример использования этой функции:

SELECT vcFamil, REPLACE(vcFamil, 'оро', 'аро') AS Ind
FROM tbPeoples
WHERE PATINDEX('%О_О%', vcFamil)>0

Мы выбираем из таблицы два поля: фамилию и результат функции REPLACE. Функция ищет в поле «vcFamil» строку «оро» и заменяет ее на строку «аро». Чтобы лучше было понятно, посмотрим на результат работы функции:

vcFamil                      Ind                                                                                                                                                                                                                                                              
----------------------------------------------
СИДОРОВ                      СИДароВ
КОНОНОВ                      КОНОНОВ
КОРОВА                       КароВА
МОЛОТКОВ                     МОЛОТКОВ
САДОВОДОВ                    САДОВОДОВ
СОДОРОЧКИН                   СОДароЧКИН

(6 row(s) affected)

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

WHERE

Оператор Where обычно — основная часть запроса, поскольку оно определяет условия, которые фильтруют выборку. Оператор Where может использовать любой оператор сравнения, логическую операцию, функции, атрибуты, объекты, и подвыборки. Операции сравнения включают =, <, >, <=, >=, <>, LIKE, BETWEEN, IS NULL,IN. NOT Может также использоваться с любым оператором сравнения (NOT LIKE, NOT BETWEEN, IS NOT NULL, NOT IN). Логические операции включают AND, OR, и NOT.

Операции сравнения

Операция Описание Пример
= равно
e.firstName = 'Bob'
< меньше чем
e.salary < 100000
> больше чем
e.salary > sal
<= меньше или равно
e.salary <= 100000
>= больше или равно
e.salary >= sal
LIKE оценивает, если два соответствия последовательности, ‘%’ и ‘_’ являются допустимыми подстановочными знаками, и Символ ESC дополнительный
e.firstName LIKE 'A%' OR e.firstName NOT LIKE '%._%' ESCAPE '.'
BETWEEN оценивает, если значение между двумя значениями
e.firstName BETWEEN 'A' AND 'C'
IS NULL сравнивает значение с нулем, базы данных могут не позволить или иметь неожиданные результаты при использовании = с нулем
e.endDate IS NULL
IN оценивает, если значение содержится в списке
e.firstName IN ('Bob', 'Fred', 'Joe')

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

e.firstName IN (:name1, name2, name3)
e.firstName IN (:name1)
e.firstName IN names
e.firstName IN (SELECT e2.firstName from Employee e2 WHERE e2.lastName = 'Smith')

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

e.firstName = (SELECT e2.firstName from Employee e2 WHERE e2.id = id)
e.salary < (SELECT e2.salary from Employee e2 WHERE e2.id = id)
e.firstName = ANY (SELECT e2.firstName from Employee e2 WHERE e.id <> e.id)
e.salary <= ALL (SELECT e2.salary from Employee e2)

Функция CONCAT

Начнем с функции CONCAT – она используется для объединения значений двух столбцов в один. Допустим у Вас в таблице, «Имя» и «Фамилия» находятся в разных колонках (что логично), а Вам, для какого-нибудь отчета, нужно чтобы они выводились в одной колонке. Вы можете легко использовать данную функцию.

  
  SELECT CONCAT (name, surname) AS FIO FROM table

С помощью данного запроса Вы объедините две колонки в одну, т.е. у Вас получится не вот так

Иван Иванов
Петр Петров

А вот так

Иван Иванов
Петр Петров

Аналогично этому запросу можно использовать следующую конструкцию (применимо в PostgreSQL).

  
  SELECT name || surname AS FIO FROM table

Или чтобы отделить пробелом введите

 
  SELECT name || ' ' || surname AS FIO FROM table

т.е. две вертикальные черты объединяют два столбца в один, а чтобы отделить их пробелом я поставил между ними пробел (можно использовать любой символ, например тире или двоеточие) в апострофах и объединил также двумя вертикальными чертами (в Transact-SQL вместо двух вертикальных черточек используется знак +).

STUFF

Функция STUFF позволяет вставить строку в определенную позицию другой строки. У этой функции четыре параметра:

  1. Строка, которую нужно изменить;
  2. Позиция, в которую должна произойти вставка;
  3. Количество удаляемых символов;
  4. Вставляемая строка.

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

Рассмотрим пример, в котором цена вставляется в поле названия товара, начиная с первой позиции, не удаляя ни одного из символов:

SELECT STUFF(, 1, 0, STR(Цена, 10, 2)+' ')
FROM Товары

Результат работы функции будет следующим:

--------------------------------------------
     13.60 КАРТОФЕЛЬ
     23.00 Сок
     25.00 Шоколад
      6.00 Хлеб
     18.40 Сок
     12.00 Молоко
      6.00 Хлеб
...

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

Попробуйте увеличить третий параметр до 1. В этом случае, первый символ в названии товара будет удален, а вместо него будет вставлена цена.

5 ответов

Лучший ответ

Возможно, вы не осведомлены об этом факте, но вы можете создавать уникальные индексы по функциям. И даже сделайте их частичными индексами.

Например:

Сделает имя пользователя уникальным независимо от регистра.

Вы также можете перейти на 1 шаг дальше и (например, это может быть не очень хорошей идеей в вашей среде) сделать так, чтобы уникальность применялась только для активных пользователей:

Также обратите внимание, что для поиска без учета регистра вы не должны использовать ILIKE. Проблема в том, что ILIKE не может (по какой-то непонятной мне причине) использовать индексы

Итак, хотя можно использовать функциональный индекс для ускорения запросов:

Или

(по крайней мере, для некоторых значений «…»)

Index не будет использоваться (насколько мне известно) в:

2

27 Мар 2009 в 18:30

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

ИЗМЕНИТЬ Что касается уникального ограничения :

3

Milen A. Radev
27 Мар 2009 в 18:29

Вы не разрешаете пользователям создавать объекты с одинаковыми именами при сравнении без учета регистра, если только у вас нет очень конкретной целевой аудитории, которая уже «понимает». Обычные пользователи компьютеров, Эмили Исполнительный, не поймут, почему у нее есть два файла для «Ежеквартального отчета» и «Ежеквартального отчета» — это только ухудшит удобство использования вашего продукта, если приложение или сценарии использования не требуют учета регистра.

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

Как я могу упростить нашим пользователям понимание того факта, что у них могут быть повторяющиеся имена, если дело обстоит иначе?

Если вы должны это сделать, установите шрифт, чтобы было очевидно, что имена разные. Задайте для пользователя поле выбора, которое включает и выключает предупреждения: «Этот файл имеет имя, аналогичное этому другому файлу, вы уверены, что хотите сохранить его под этим именем?» с автоматическим включением при запуске (отключение, а не включение общих предупреждений)

-Адам

Adam Davis
27 Мар 2009 в 17:36

Чувствительность к регистру заставляет пользователя решать проблемы в компьютерном мире.

Не выставляйте чувствительность к регистру!

Вы только что сказали мне, что и Windows, и Mac нечувствительны к регистру, они должны уменьшить путаницу для пользователя.

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

Pyrolistical
27 Мар 2009 в 18:45

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

bortzmeyer
29 Мар 2009 в 19:47

Оператор SELECT в подзапросах SQL

До сих пор мы разбирали конструкции SQL с оператором SELECT, в которых условия, по котором выбираются данные,
и сами выбираемые данные содержатся в одной и той же таблице базы данных. На практике часто бывает, что данные, которые надо
выбрать, содержатся в одной таблице, а условия — в другой. Здесь на помощь приходят подзапросы:
значения условия отбора возвращаются из другого запроса (вложенного запроса), начинающегося также с
SELECT. Запросы с подзапросами могут выдавать как одну, так и несколько строк.

Пример 18. Все те же таблицы Org и Staff. Пусть требуетcя узнать,
в каком подразделении работает сотрудник с идентификационным номером 16, и где это подразделение расположено. Но информация о подразделениях
хранится в таблице Org, а информация о сотрудниках — в таблице Staff. Это можно сделать при помощи следующего запроса с подзапросом, в
котором внешний SELECT обращается к таблице Org, а внутренний SELECT — к таблице Staff:

SELECT Division, Location
FROM Org
WHERE Deptnumb =
(SELECT Dept FROM Staff
WHERE ID = 16)

Пример 19. Пусть теперь требуетcя узнать,
в каких подразделениях (без дублирования) работают сотрудники с заработной платой менее 13000. Для этого в секции WHERE
внешнего SELECT (запрос к таблице Org) задаётся условие, принимающее диапазон значений (IN), а внутренний
SELECT (к таблице Staff) как раз возвращает требуемый диапазон значений:

SELECT DISTINCT Deptname
FROM Org
WHERE Deptnumb IN
(SELECT Dept FROM Staff
WHERE Salary

Результат выполнения запроса:

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

Поделиться с друзьями

Назад Листать Вперёд>>>

Функции LTRIM и RTRIM

LTRIM (<строковое выражение>)

RTRIM (<строковое выражение>)

отсекают соответственно лидирующие и конечные пробелы строкового выражения, которое неявно приводится к типу VARCHAR.

Пусть требуется построить такую строку: имя пассажира_идентификатор пассажира для каждой записи из таблицы Passenger. Если мы напишем

SELECT name + ‘_’ + CAST(id_psg AS VARCHAR) FROM Passenger,

то в результате получим что-то типа:

A                               _1

Это связано с тем, что столбец name имеет тип CHAR(30). Для этого типа короткая строка дополняется пробелами до заданного размера (у нас 30 символов). Здесь нам как раз и поможет функция RTRIM:

SELECT RTRIM(name) + ‘_’ + CAST(id_psg AS VARCHAR) FROM Passenger

PATINDEX

С помощью функции PATINDEX можно искать часть подстроки по определенному шаблону. Допустим, что нам надо найти все фамилии, в которых есть две буквы «о», между которыми может находиться любой символ. Эту задачу можно решить с помощью следующего запроса:

SELECT vcFamil, PATINDEX('%О_О%', vcFamil)
FROM tbPeoples

Если посмотреть на функцию, то пока не понятно, чем она отличается от LIKE с шаблоном? Все очень просто – LIKE используется для создания ограничений в секции WHERE, а PATINDEX возвращает индекс символа, начиная с которого идет указанный шаблон в строке. Если бы мы использовали LIKE, то сервер вернул бы нам только те строки, где найден шаблон:

SELECT vcFamil
FROM tbPeoples
WHERE vcFamil LIKE '%О_О%'

Если использовать функцию PATINDEX, то в результат попадут все строки (мы не ограничиваем вывод в секции WHERE), но там где в фамилии нет шаблона, в соответствующей строке будет стоять ноль, а там где есть, будет стоять 1. Посмотрим на пример результата выполнения запроса с использованием функции PATINDEX:

vcFamil                             Ind         
----------------------------------------------- 
ПОЧЕЧКИН                            0
ПЕТРОВ                              0
СИДОРОВ                             4
КОНОНОВ                             2
СЕРГЕЕВ                             0

В данном примере шаблон ‘%О_О%’ присутствует в фамилии Сидоров. Начиная с четвертого символа идут буквы «оро».

Запросы на удаление

Вы можете выполнить объемное удаление объектов с оператором DELETE . Запросы на удаление обеспечивают эквивалент оператору SQL DELETE , но с условными выражениями JPQL.

Запросы на удаление не позволяют соединения, но действительно поддерживают, подвыбирает. OneToOne и отношения ManyToOne могут быть пересечены в операторе Where. Отношения набора могут все еще быть запрошены посредством использования EXISTS в операторе Where с подвыбором. Сложные запросы на удаление зависят от базы данных, удаляют поддержку и может использовать временные таблицы на некоторых базах данных.

Запросы на удаление должны только использоваться для объема, удаляет, регулярный удаляет к объектам, должен быть выполнен посредством вызова EntityManager , удаляют () API.

Запросы на удаление возвращают число удаленных строк на базе данных (количество строки).

Этот пример демонстрирует, как использовать запрос на удаление, чтобы удалить всех сотрудников, которые не присвоены отделу. WHERE пункт содержит условное выражение.

Пример запроса на удаление

Query query = em.createQuery("DELETE FROM Employee e WHERE e.department IS NULL");
int rowCount = query.executeUpdate();

Запросы на удаление полиморфные: будут удалены любые экземпляры подкласса объекта, которые соответствуют критериям запроса на удаление. Однако запросы на удаление не соблюдают каскадные правила: никакие объекты кроме типа, на который ссылаются в запросе и его подклассах, не будут удалены, даже если у объекта будут отношения к другим объектам с каскадом, удаляет, включал. Запросы на удаление удалят строки из таблиц набора и соединения.

Контекст персистентности не может быть обновлен, чтобы отразить, что результаты удаляют операции. Если Вы используете ограниченный по объему транзакцией контекст персистентности, Вы должны или выполнить объемную работу в транзакции совершенно отдельно или являетесь первой работой в транзакции. Это вызвано тем, что любой объект, которым активно управляет контекст персистентности, останется не знать, что фактические изменения происходят на уровне базы данных.

Предложение GROUP BY

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

Обычно предложение применяют, если формулировка задачи содержит фразу «для каждого…», «каждому..» и т.п.

Пример 18.Определить суммарный объем деталей, поставляемых каждым поставщиком.

pnum sum
1 600
2 400
3 1000

Выполнение запроса можно описать следующим образом: СУБД разбивает таблицу PD на три группы, в каждую из групп помещаются строки с одинаковым значением номера поставщика. Затем к каждой из полученных групп применяется агрегатная функция SUM, что дает единственное итоговое значение для каждой группы.

Рассмотрим два похожих примера.

В примере 1 определяется минимальный объем поставки каждого поставщика. В примере 2 определяется объем минимальной поставки среди всех поставщиков.

Пример 1:

Пример 2:

Результаты запросов представлены в следующей таблице:

pnum min max
1 100 100
2 150
3 1000

Следует обратить внимание, что в первом примере мы можем вывести номера поставщиков, соответствующие объемам поставок, а во втором примере – не можем. Все имена столбцов, перечисленные после ключевого слова SELECT должны присутствовать и в предложении GROUP BY, за исключением случая, когда имя столбца является аргументом агрегатной функции

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

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

Если предложение расположено после предложения , то группы создаются из строк, выбранных после применения .

Пример 19.Для каждой из деталей с номерами 1 и 2 определить количество поставщиков, которые их поставляют, а также суммарный объем поставок деталей.

Результат запроса:

dnum COUNT SUM
1 3 1250
2 2 450

LEFT

Задачу обрезание лишних символов из начала строки можно было бы решить и с использованием функции LEFT, которая возвращает указанное количество символов, начиная с 1-го. Функции нужно передать следующие два параметра:

  1. Поле, подстроку которого нужно получить;
  2. Количество символов.

Следующий пример формирует ФИО, в котором имя и отчество сокращены:

SELECT vcFamil+' '+left(vcName, 1)+'. '+left(vcSurName, 1)+'.'
FROM tbPeoples

Поле «vcFamil» выводится полностью, а вот от имени и отчества выводится только один левый (первый) символ.

Теперь посмотрим, как можно было использовать LEFT для обрезания префикса ‘mr.’:

UPDATE tbPeoples
SET vcFamil=(case LEFT(vcFamil, 3)
      WHEN 'mr.' THEN SUBSTRING(vcFamil, 4, 255)
      ELSE vcFamil
     END)

Регистр символов и индексы

При работе со строками часто возникает необходимость в поиске и сравнении без учета регистра символов. Но если вы реализуете описанный здесь прием, вдруг выясняется, что ваше приложение перестает использовать индексы и начинает работать слишком медленно. Будьте внимательны, чтобы ваши действия не повредили использованию индексов в SQL. Для наглядности рассмотрим пример с демонстрационной таблицей . Таблица использует индекс для столбцов , . Мой код включает следующую команду SQL: 

SELECT * FROM employees WHERE last_name = lname

Изначально код использует индекс , но когда я задаю параметры и , чтобы включить поиск без учета регистра, индекс перестает использоваться, и операции выполняются с полным просмотром таблицы — со всеми вытекающими последствиями! Одно из возможных решений заключается в использовании индекса на базе функции, игнорирующего регистр символов:

CREATE INDEX last_name_ci ON EMPLOYEES (NLSSORT(last_name, 'NLS_SORT=BINARY_CI'))

Теперь при выполнении запросов без учета регистра символов используется индекс без учета регистра, а быстродействие программы остается на высоком уровне.

Поиск подстроки

Для того, чтобы найти вхождение одной строки в другую, используется
функция . Она возвращает позицию
вхождения одной строки в другую. Если вхождения
не обнаружено, то в качестве результата будет возвращён 0.

Следующий запрос возвращает позицию, начиная
с которой в заголовках записей пользователей
встречается символ восклицательного знака:

select a.title,
       instr(a.title, '!') pos
from articles a

Как видно, для тех заголовков, которые не содержат восклицательный знак, функция вернула 0.

В функции можно задавать позицию,
начиная с которой следует производить поиск вхождения:

select a.title,
       instr(a.title, 'о', 3) pos
from articles a

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

Так, в строке «Новый фотоаппарат» мы получили результат
8, хотя буква о есть и раньше — на второй позиции.

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

select a.title,
       instr(a.title, 'а', -4) pos
from articles a

Также можно указать, какое по счету совпадение нужно искать(4-ый параметр в функции ):

select a.title,
       instr(a.title, 'о', 1, 2) pos
from articles a
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: