SUBSTR&;REGEXP匹配MySQL中其他表的多个值

SUBSTR&;REGEXP匹配MySQL中其他表的多个值,mysql,regex,Mysql,Regex,目标:我的触发器需要一个SQL逻辑来阻止插入传递字符串中任何位置的脏字(从表中) 说明:几天前,我正在开发一个SQL来实现这一点。我能够完成它,但在测试中发现,只有准确的单词被匹配。请参考下面的例子 PROFANITY TABLE: | word | somebadword somedirtyword somegarbageword someslangword 使用创建的触发器,如果new.email是somebadword或somedirtyword,则只有它阻止插入并抛出信号45000

目标:我的触发器需要一个SQL逻辑来阻止插入传递字符串中任何位置的脏字(从表中)

说明:几天前,我正在开发一个SQL来实现这一点。我能够完成它,但在测试中发现,只有准确的单词被匹配。请参考下面的例子

PROFANITY TABLE:

| word |

somebadword
somedirtyword
somegarbageword
someslangword
使用创建的触发器,如果new.email是
somebadword
somedirtyword
,则只有它阻止插入并抛出信号45000错误。我想要的是如果new.email是
testingsomebadword@somedomain.com
然后它也会抛出信号45000错误。需要集成一些substr/regexp搜索逻辑

TRIGGER:
DELIMITER $$
CREATE TRIGGER trg_contact_insert_profanity_check BEFORE INSERT ON contacts
FOR EACH ROW BEGIN
IF ((new.email IN (SELECT word FROM profanity)) OR (new.message
IN (SELECT word FROM profanity)) OR (new.message REGEXP '/(http|https|ftp|ftps)?(://)?[a-zA-Z0-9.-]+.[a-zA-Z]{2,3}(/S*)?/' ))
THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Database Error: BAD REQUEST";
END IF;
END;$$
期望和参考: 通过各种参考来实现这一点,但没有成功。预期我的解决方案可能是REF1+Ref2的组合。寻找(按性能)优化的最佳解决方案:

参考文献1:(最接近我的需求

参考文献2:

参考文献3:

DB版本:5.7.23以下作品:

TRIGGER:
DELIMITER $$
CREATE TRIGGER trg_contact_insert_profanity_check BEFORE INSERT ON contacts
FOR EACH ROW BEGIN
IF ((new.email REGEXP (SELECT GROUP_CONCAT(word SEPARATOR '|') FROM profanity)) OR (new.message
REGEXP (SELECT GROUP_CONCAT(word SEPARATOR '|') FROM profanity)) OR (new.message REGEXP '/(http|https|ftp|ftps)?(://)?[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}(/S*)?/' ))
THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Database Error: BAD REQUEST";
END IF;
END;$$

为了优化,我建议创建一个变量,并将
SELECT GROUP_CONCAT(单词分隔符“|”)的输出从亵渎中分配给循环,并在循环中使用该变量。

使用
count
CONCAT
可能会达到您想要的效果。我无法测试实际触发器,但请告诉我它是否有效:

TRIGGER:
DELIMITER $$
CREATE TRIGGER trg_contact_insert_profanity_check BEFORE INSERT ON contacts
FOR EACH ROW BEGIN
IF (
   (
       select count(*) 
       from profanity p
       where new.email like concat('%',p.word,'%')
          or new.message like concat('%',p.word,'%')
   ) > 0
THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Database Error: BAD REQUEST";
END IF;
END;$$

此触发器应该执行您想要的操作。它使用
EXISTS
检查电子邮件或消息是否与亵渎表中的单词相似:

DELIMITER $$
CREATE TRIGGER trg_contact_insert_profanity_check BEFORE INSERT ON contacts
FOR EACH ROW BEGIN
    IF EXISTS (SELECT * FROM profanity WHERE new.email LIKE CONCAT('%', word, '%')) OR 
       EXISTS (SELECT * FROM profanity WHERE new.message LIKE CONCAT('%', word, '%')) OR
       new.message REGEXP '(http|https|ftp|ftps)(://)[a-zA-Z0-9.-]+.(/S*)?'
THEN 
SET @msg = CONCAT("Database Error: BAD REQUEST: email = '", new.email, "', message = '", new.message, "'");
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = @msg;
END IF;
END;$$
请注意,您的正则表达式是错误的,MySQL正则表达式不需要分隔符,所以我已经删除了它们。另外,URL正则表达式中有太多可选部分,因此它与普通字符串匹配。我已经去掉了一些。此外,我还增强了错误消息以包含错误值


您正在转义URL模式,并使用了不能使用的分隔符。使用
REGEXP'(https?| ftps?(:/)?[a-zA-Z0-9.-]+\[a-zA-Z]{2,3}'
感谢您的评论。修复已就位,从错误的数据库复制,将编辑问题。我们将
[a-zA-Z0-9-.]+
改为
[-a-zA-Z0-9.]+
,效果很好。别忘了“d1rtyword”和“badw0rd”@Rick,对了。但首先,它应该做基本的事情,然后它将进一步发展。我们无法在这里迈出第一步,也无法对针的regexp(无论位置如何)进行基本匹配。有人能帮我吗?它没有按预期工作。在提出这个问题之前,我已经尝试过这个解决方案。我们有
俚语作为亵渎表中的一个条目,但它仍然允许
slangword@hotmail.com
要插入的电子邮件。请帮助。其他不应插入的示例是
bcslang@test.com
helloWorld@slang.com
myslangemail@gmial.com
,等等@AakashSahai我在我的机器上试过这个,它正在工作。请检查您是否正在插入该行&而不是更新该行。如果要更新行,请在更新之前使用
创建另一个触发器good@good.yes,message='good'
@PaulSpiegel感谢您指出,URL的OPs正则表达式有太多可选位。我已经更新了。