如何在MySQL触发器中中止INSERT操作?

31

我有一个表格包含一个URL和一个表示其参数的字符串。问题是,我希望URL和参数字符串成为该表格的唯一约束条件-也就是说,没有任何条目可以具有相同的URL和参数字符串。参数字符串的长度可以任意(比如长于800字节,这是MySql关键字的最大长度,因此我不能使用Unique(url,params),因为它会抛出错误...)。

我考虑使用触发器来解决这个问题,但如果触发器发现插入操作将要插入重复条目,我该如何抛出异常/引发错误呢?我想象中会像MySql那样抛出MySqlException,就像重复的主键等一样,这样我就可以在我的C#代码中捕获它。

我在触发器中有两个需要得到帮助的部分: ...中止并向C#抛出异常...如何抛出异常或者向C#抛出异常? ...允许插入...-如果没有重复项,如何仅允许插入?

以下是触发器代码:

CREATE TRIGGER urls_check_duplicates
BEFORE INSERT ON urls
FOR EACH ROW

BEGIN
DECLARE num_rows INTEGER;

SELECT COUNT(*)
INTO num_rows
FROM urls
WHERE url = NEW.url AND params = NEW.params;

IF num_rows > 0 THEN
   ... ABORT/throw exception to C# ...
ELSE
   ... Allow insert ...
END

从MySQL 5.5版本(可能更早),您可以使用信号(signals),请参阅我的回答 - RuiDC
3个回答

72

我遇到了这个问题,虽然解决方案有效,但后来我发现了一种更好的解决方案。我怀疑当时提出这个问题时还不存在这种解决方案。

CREATE TRIGGER `TestTable_SomeTrigger`
BEFORE UPDATE ON `test_table`
FOR EACH ROW
BEGIN
    DECLARE msg VARCHAR(255);
    IF (SomeTestToFail = "FAIL!") THEN
        set msg = "DIE: You broke the rules... I will now Smite you, hold still...";
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
    END IF;

    -- Do any other code here you may want to occur if it's all OK or leave blank it will be
    --  skipped if the above if is true
END$$

现在这个操作将会返回一个清晰的(或者可怕的)错误信息,你可以进行捕获。更多相关信息请参考:http://dev.mysql.com/doc/refman/5.5/en/signal.html

希望这能对其他人有所帮助!


2
这真是太棒了。对我很有用。 - rishad2m8
1
谢谢。我需要一个表格并强制执行不重叠的范围,这使我能够做到这一点。 - Kickstart

8

7

如果您的表定义是 NOT NULL 值,则可以将 NEW 设置为 NULL,这实际上不会执行插入操作。为了使其正常工作,您可能需要开启严格的 SQL 模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接