Самая большая трудность в достижении точного решения состоит в том, чтобы точно определить , какие символы должны быть включены (или исключены, в зависимости от того, какое направление имеет больше смысла для операции). Смысл:
- Мы говорим о
VARCHAR
/ ASCII данных или NVARCHAR
/ Unicode данных? Список знаков препинания для данных ASCII зависит от кодовой страницы, которая, в свою очередь, зависит от параметров сортировки. ( в этом вопросе мы имеем дело с данными ASCII ).
- Имеем ли мы дело с поиском с учетом регистра или без учета регистра?
- Какой Collation установлен для столбца? Сортировка покажет нам как кодовую страницу, так и регистр символов. ( в этом вопросе мы имеем дело с
Latin1_General_CI_AS
)
- это термин «знаки препинания» означает только стандартные символы пунктуации (например
.
, ,
, ;
, :
и т.д.) , или это значит не алфавитно-цифровые символы?
- Включены ли пробельные символы?
- Включены ли контрольные символы?
- Как насчет валютных символов , таких , как
¢
, £
, ¥
и т.д.?
- А как насчет символов, таких как
©
и ™
?
- Какие символы считаются "альфа"? Не являются английские символы , такие как
Â
, É
, Ñ
, ß
, Þ
включены?
- Поскольку этот Вопрос касается клавиатур Великобритании (см. Обсуждение этого вопроса), как насчет символа
Æ
/ æ
?
Чтобы обеспечить ясность в отношении ожидаемого поведения, следующий запрос покажет все 256 символов набора символов Latin1 (т. Е. Кодовую страницу 1252) и то, как работают два варианта предлагаемого решения @ Shaneis . Первое поле (помеченное как Latin1_General_CI_AS
) показывает LIKE
предложение, предложенное @Shaneis (на момент написания этой статьи), а второе поле (помеченное как Latin1_General_100_BIN2
) показывает модификацию, в которой я переопределяю Collation для указания двоичного (то есть, Collation, заканчивающийся на _BIN2
; _BIN
Параметры сортировки устарели, поэтому не используйте их, если у вас есть доступ к _BIN2
версиям), что означало, что мне также нужно было добавить A-Z
диапазон, чтобы отфильтровать буквы в верхнем регистре, так как текущий параметр сортировки не учитывает регистр
;WITH nums AS
(
SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) AS [Decimal]
FROM [master].[sys].[all_objects]
)
SELECT nm.[Decimal],
CHAR(nm.[Decimal]) AS [Character],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9]%'
THEN 'x' ELSE '' END AS [Latin1_General_CI_AS],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9A-Z]%' COLLATE Latin1_General_100_BIN2
THEN 'x' ELSE '' END AS [Latin1_General_100_BIN2]
FROM nums nm;
ОБНОВИТЬ
Следует отметить, что ЕСЛИ кто-то действительно стремится найти символы, которые классифицируются как «знаки пунктуации» (а не «символ валюты», «математический символ» и т. Д.), И если ЕСЛИ один не запрещает использовать SQLCLR / загрузку пользовательского Ассамблея (SQLCLR была введена с SQL Server 2005, и я еще не сталкивался с хорошей причиной, что не позволяю ему, тем более , что Azure SQL Database V12 поддерживает SAFE
сборку), то вы можете использовать регулярные выражения, но не по той причине , что большинство людей догадался бы.
Вместо использования регулярных выражений для создания более функционального диапазона символов или даже вместо использования чего-то вроде \w
(означающего любой «слово»), вы можете указать категорию Unicode символов, по которым вы хотите фильтровать, и есть несколько определенных категорий :
https://www.regular-expressions.info/unicode.html#category
Вы даже можете указать блок Unicode для фильтрации, например, «InBengali» или «InDingbats» или «InOptical_Character_Recognition» и т. Д .:
https://www.regular-expressions.info/unicode.html#block
Существует множество примеров создания функций RegEx для SQL Server (хотя большинство примеров не соответствуют рекомендациям SQLCLR), или вы можете скачать бесплатную версию библиотеки SQL # (которую я создал) и использовать скалярную функцию RegEx_IsMatch следующим образом :
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
В \p{P}
выражение означает \p
= Unicode Категория, а {P}
= все знаки препинания (в отличие от конкретного типа пунктуации, такие как «Connector Пунктуации»). И в категорию «Знаки пунктуации» входят все знаки препинания на всех языках! Вы можете увидеть полный список на сайте Unicode.org по следующей ссылке (в настоящее время в этой категории 717 кодов):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Обновленная версия тестового запроса было показано выше, в том числе и другое поле , которое использует SQL # .RegEx_IsMatch с \p{P}
, и результаты всех 3 -х тестов на всех 256 символов кодовой страницы 1252 (т.е. Latin1_General) была размещена на PasteBin.com по адресу:
T-SQL-запрос и результаты для фильтрации типов символов
ОБНОВЛЕНИЕ
Следующее было упомянуто в связанной дискуссии:
Вы хорошо отметили символы с акцентом, так как они являются именами отелей со всего мира, в именах будут символы с акцентом, для моей проблемы я бы хотел классифицировать их как допустимых буквенных символов.
В этом случае:
Есть 11 неанглийских символов, которые включены в набор символов Latin1 / Кодовую страницу, которые не соответствуют a-z
диапазону. Они являются: ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Их необходимо добавить к шаблону, и хотя в данный момент это не нужно, добавление не повредит, A-Z
так что шаблон работает так же хорошо с учетом регистра с учетом регистра. Конечный результат:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Учитывая, что в эти данные могут входить «названия отелей со всего мира», я настоятельно рекомендую изменить тип данных столбца, чтобы NVARCHAR
можно было хранить все символы из всех языков. Принимая это во внимание, VARCHAR
существует очень высокий риск возможной потери данных, поскольку вы можете представлять только языки на основе латинского алфавита, и даже не полностью для тех, которые имеют шесть дополнительных категорий Unicode, которые предоставляют дополнительные символы, относящиеся к латинскому алфавиту.