【问题标题】:Validate email addresses in Mysql在 Mysql 中验证电子邮件地址
【发布时间】:2012-09-27 09:32:27
【问题描述】:

此查询创建一个 mysql 视图,该视图在一个表中捕获错误的电子邮件地址格式。因此,如果插入具有rtrrg.com 作为电子邮件的行,它将被记录在视图中。我的问题是,如何使视图跟踪不止一张表。第二张桌子。

SQL

CREATE VIEW `invalid_emails` AS 
  select `table_with_email_column`.`email` AS `invalidemail` 
    from `table_with_email_column` 
   where ((locate(_latin1'', ltrim(rtrim(`table_with_email_column`.`email`))) <> 0) 
      or (left(ltrim(`table_with_email_column`.`email`), 1) = _latin1'@') 
      or (right(rtrim(`table_with_email_column`.`email`), 1) = _latin1'.') 
      or ((locate(_latin1'.', `table_with_email_column`.`email`,locate(_latin1'@', `table_with_email_column`.`email`)) -  locate(_latin1'@', `table_with_email_column`.`email`)) <= 1) 
      or ((length(ltrim(rtrim(`table_with_email_column`.`email`))) -  length(replace(ltrim(rtrim(`table_with_email_column`.`email`)), _latin1'@', _latin1''))) <> 1) 
      or (locate(_latin1'.', reverse(ltrim(rtrim(`table_with_email_column`.`email`)))) < 3) 
      or (locate(_latin1'.@', `table_with_email_column`.`email`) <> 0) 
      or (locate(_latin1'..', `table_with_email_column`.`email`) <> 0));

【问题讨论】:

    标签: mysql sql validation view


    【解决方案1】:

    您可以使用纯 SELECT 来验证电子邮件地址:

    SELECT * FROM `users` WHERE `email` NOT REGEXP '^[^@]+@[^@]+\.[^@]{2,}$';
    

    现在对于跟踪多个表的问题,您可以使用逗号分隔的表名吗?

    SELECT * FROM `users`, `customers`, `clients`
             WHERE `email` NOT REGEXP '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$';
    

    【讨论】:

    • '^[^@]+@[^@]+\.[^@]{2,}$' 不好,因为并非所有符号都允许在电子邮件帐户名中使用。 '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$' 也不正确,因为电子邮件帐户名称应以字母或数字(而不是点或 _ 或任何其他符号)开头和结尾。域名同样的问题。
    • @PraveenKumar 对于其他人来说很有用,即使是几年后,也能意识到这些限制。例如,我有一个以句点结尾的无效电子邮件地址,您的正则表达式无法捕捉到该地址。这并不是要否定您在回答方面的努力,这是值得赞赏的,并使我走上正轨。
    • @IvanMcA 谢谢伙计...您想自己更新答案吗?我会批准它,这就是 Stack Overflow 的用途,这就是它的工作原理。 :)
    • 此答案也不适用于任何包含撇号的电子邮件地址,撇号是有效的地址字符,对于爱尔兰血统的人来说并不少见。
    • @JonWyatt 5 年前可能不是这样。
    【解决方案2】:

    对于正确的电子邮件验证,您可以使用此正则表达式,如下所示:

    SELECT
        *
    FROM
        `school`
    WHERE
        `email` NOT REGEXP '^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9._-]@[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]\\.[a-zA-Z]{2,63}$';
    

    【讨论】:

    • 这个正则表达式稍微好一点'^[a-zA-Z0-9][a-zA-Z0-9._-]*@[a-zA-Z0-9][a-zA-Z0-9._-]*\\.[a-zA-Z]{2,4}$',因为它也允许x@x.com
    • 顶级域名的最大长度为 63 个字符。所以它应该结束 {2,63}
    • 在@符号之前也应该允许加号:'^[a-zA-Z0-9][a-zA-Z0-9._+-]*@[a-zA- Z0-9][a-zA-Z0-9._-]*\\.[a-zA-Z]{2,4}$'(例如 joe+facebook@example.com)
    • 以上不再有效。我们现在拥有 .global 或 .ninja 等顶级域。
    • 它确实不会处理更长的但有效的 TLD。它也不处理“.co.uk”和类似的域。至少应该是:'^[a-zA-Z0-9][a-zA-Z0-9._-]*@[a-zA-Z0-9][a-zA-Z0-9._-]*(\\.[a-zA-Z]{2,4})+$'。至于长度检查,我们对单个正则表达式毫无防备。
    【解决方案3】:

    简单的SELECT 语句就足够了,例如:

     SELECT * FROM user WHERE email NOT 
     REGEXP '^[a-zA-Z0-9][+a-zA-Z0-9._-]*@[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]*\\.[a-zA-Z]{2,4}$'
    

    此查询处理带有 + 符号的 Gmail 地址和主机为单个字母的地址。

    【讨论】:

    • 它不允许域具有有效的 TLD,如 .world、.group 或 .global。
    • 在查询中将{2,4}设置为{2,6}
    • 在双反斜杠之前的 [a-zA-Z0-9]* 对我来说毫无意义。该(0 个或多个)字符列表已与之前的(0 个或多个)字符匹配:[a-zA-Z0-9._-]*。您可能想在点之前排除._-。但随后* 必须更改为+[a-zA-Z0-9]+
    【解决方案4】:

    您可以在VIEW 中使用UNION,但是您必须重复所有WHERE 语句,这会为您提供冗余代码。因此,您将创建一个帮助器VIEW,使您成为UNION,然后应用WHERE 子句。

    在这里演示:SQL Fiddle Demo

    这将以某种方式适用于您的 SQL(未经测试);

    CREATE VIEW `invalid_emails_helper` AS
      select `table_with_email_column`.`email` AS `invalidemail` 
        from `table_with_email_column` 
    union
      select `table_with_email_column`.`email` 
        from `second_table_with_email_column` 
    
    CREATE VIEW `invalid_emails` AS 
      select `invalidemail` as `email`
        from `invalid_emails_helper` as `table_with_email_column` 
       where ((locate(_latin1'', ltrim(rtrim(`table_with_email_column`.`email`))) <> 0) 
          or (left(ltrim(`table_with_email_column`.`email`), 1) = _latin1'@') 
          or (right(rtrim(`table_with_email_column`.`email`), 1) = _latin1'.') 
          or ((locate(_latin1'.', `table_with_email_column`.`email`,locate(_latin1'@', `table_with_email_column`.`email`)) -  locate(_latin1'@', `table_with_email_column`.`email`)) <= 1) 
          or ((length(ltrim(rtrim(`table_with_email_column`.`email`))) -  length(replace(ltrim(rtrim(`table_with_email_column`.`email`)), _latin1'@', _latin1''))) <> 1) 
          or (locate(_latin1'.', reverse(ltrim(rtrim(`table_with_email_column`.`email`)))) < 3) 
          or (locate(_latin1'.@', `table_with_email_column`.`email`) <> 0) 
          or (locate(_latin1'..', `table_with_email_column`.`email`) <> 0));
    

    是的,使用regex 检查电子邮件地址的查询在互联网上随处可见,进一步简化了它。

    【讨论】:

      【解决方案5】:
      SELECT
          *
      FROM
          users
      WHERE
          email NOT REGEXP ‘ ^[ a - zA - Z0 - 9 ][ a - zA - Z0 - 9._ -]*[ a - zA - Z0 - 9 ]@[ a - zA - Z0 - 9 ][ a - zA - Z0 - 9._ -]*[ a - zA - Z0 - 9 ]\.[ a - zA - Z ]{ 2,
          63 } $’
      

      【讨论】:

      • 这比接受的答案略好,但仍然不是完美的。 a@example.com 无效,因为 @ 之前只有 1 个符号。与域名相同。
      猜你喜欢
      • 2014-06-12
      • 1970-01-01
      • 2020-03-02
      • 2018-03-13
      • 2011-09-02
      • 2013-02-20
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多