【问题标题】:Find records with odd characters in names查找名称中包含奇数字符的记录
【发布时间】:2016-06-17 07:36:52
【问题描述】:

我有一个大的记录列表,这些记录是前段时间从一个不再存在的 Excel 文档中导入的。我们已经开始发现文档中的某些名称包含必须在导入过程中转换的字符。一些例子: ± © Ð € Ù _ l Ì » ñ

我不确定可能有多少奇数字符,并且有很多记录。有什么办法可以在记录中搜索其他类似这样的字符吗?导入是以 JSON 样式格式完成的,因此记录是一个长字符串,如本例(间隔以便于查看)

{
      "email_address":"fakemail@mail.com",
      "values":{
           "FNAME":"©Johñ",
           "LNAME":"SmÌth»"
      }
}

我正在使用 MSSQL Server 2008 R2,或者如果解决方案更简单,我可以使用 C#。任何帮助表示赞赏。

【问题讨论】:

  • “奇数”是什么意思? ñÙÌ 是完全有效的名称字符,现在在域名中也有效。
  • 在我的情况下,当此 JSON 稍后被其他代码使用时,它们不被接受为有效字符,使它们对我来说“奇怪”。
  • 即使它们自然是某人名字的一部分?或域名,在这种情况下,更改它以删除重音在技术上将不是相同的域名,因此不会是他们的电子邮件地址?
  • 我并不是说它们不是真实有效的字符。我是说在我的情况下,他们正在引起问题。我不会去这里做法官和陪审团,改变人名,我只需要找到相关记录。
  • 好吧 ;-)。稍后我会以正确的方式和您需要的方式发布答案;-)

标签: c# sql sql-server regex sql-like


【解决方案1】:

需要注意的是,这会发现在姓名和电子邮件地址中都有效的字符在您的系统中似乎无效,您应该使用以下LIKE 语句:

WHERE tab.col LIKE '%[^-a-zA-Z0-9.,@:{}" _]%' COLLATE Latin1_General_100_BIN2;

这里重要的是COLLATE Latin1_General_100_BIN2(除非该字段已经使用二进制排序规则)。但是如果该字段没有使用二进制排序规则,那么在此处不为LIKE 谓词指定一个将丢失诸如ñ 和其他重音字符,因为它们通常等同于非重音字符(例如n = @ 987654328@).

例子:

SELECT col
FROM (VALUES ('©Johñ'),
             ('{ "email_address":"fakemail@mail.com", "values":{ "LNAME":"SmÌth»"  } }'),
             ('{ "email_address":"fakemail2@mail.com", "values":{ "LNAME":"Jones"  } }'),
             ('{  }'),
             ('f_f'),
             ('g-g'),
             ('Johñ f')
     ) tab(col)
WHERE tab.col LIKE '%[^-a-zA-Z0-9.,@:{}" _]%' COLLATE Latin1_General_100_BIN2;

使用COLLATE 子句标识'Johñ f' 行,但没有COLLATE,该行似乎是“有效的”。


或者,如果你有两个:

  • Unicode 数据(即NVARCHAR / NCHAR 字段)
  • 一个接受真实世界数据的系统(并且不会错误地拒绝包含非美国英语字符的姓名和电子邮件地址,或将它们转换为美国英语等效字符)

然后,T-SQL LIKE 运算符无法工作,因为许多语言中的字母种类繁多。在这种情况下,您将需要一个正则表达式,因为它们可以处理字符类,它们是字符的逻辑分组。当然,RegEx 并不在 T-SQL 中原生提供,但您仍然可以通过 SQLCLR 获得此功能。您可以找到很多关于如何编写代码的示例,或者您可以下载SQL# 库的免费版本(我创建的,但大多数 RegEx 函数 - 以及许多其他函数 - 都是免费的),其中包括RegEx_IsMatch函数可以使用如下:

SELECT tab.col,
       CASE WHEN tab.col LIKE N'%[^-a-zA-Z0-9.,@:{}" _]%' COLLATE Latin1_General_100_BIN2
               THEN 1 ELSE 0 END AS [LikeOperator],
       SQL#.RegEx_IsMatch(tab.col, N'[\W-[-\{\} @:",.]]+', 1, N'IgnoreCase')
               AS [RegEx_IsMatch]
FROM (VALUES (N'©Johñ'),
             (N'{ "email_address":"fakemail@mail.com", "values":{ "LNAME":"SmÌth»" } }'),
             (N'{ "email_address":"fakemail2@mail.com", "values":{ "LNAME":"Jones" } }'),
             (N'{  }'),
             (N'f_f'),
             (N'g-g'),
             (N'k,k'),
             (N'WIDE'),
             (N'simple-email@place01.co'),
             (N'Johñ f')
     ) tab(col);

返回:

col                                                                         LIKE    RegEx
-----------------------                                                     -----   ------
©Johñ                                                                           1       1
{ "email_address":"fakemail@mail.com", "values":{ "LNAME":"SmÌth»" } }          1       1
{ "email_address":"fakemail2@mail.com", "values":{ "LNAME":"Jones" } }          0       0
{  }                                                                            0       0
f_f                                                                             0       0
g-g                                                                             0       0
k,k                                                                             0       0
WIDE                                                                         1       0
simple-email@place01.co                                                         0       0
Johñ f                                                                          1       0

[\W-[-\{\} @:",.]]+ 模式的含义是:一个或多个字符 ([]+) 是“非单词”字符 (\W) 除了 (-[]) 以下列表可以:-{}@:",.

【讨论】:

  • 这非常有效。非常感谢 srutzky 的帮助!
  • @Blankdud 没问题。如果您或任何人需要允许真实世界的数据,我添加了一个通过 RegEx 处理它的部分 :-)。
【解决方案2】:

您可以使用带有“not”和字符类的like 来查找意外字符:

select email_address
from t
where email_address like '%[^a-zA-Z0-9@.]%';

【讨论】:

  • 我试过这个:'%[^a-zA-Z0-9@.{":,}_]%' 并收到了所有的记录。做 JSON 字符比如 { " : , }需要逃脱吗?或者我可以把它们扔在括号里吗?
  • 如果您想忽略它们,请将它们放在方括号之间。请记住,以插入符号 ('^') 开头的列表表示“与此字符不匹配”。
【解决方案3】:

此正则表达式将匹配所有包含“奇数”字符的行。您不想被视为奇怪的任何其他字符都可以添加到字符类中以从搜索中排除。

/^.*[^a-zA-Z\s\[\]\{\}'":@.,_].*$/gm

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    相关资源
    最近更新 更多