如何在 MySQL 函数中引发错误

Posted

技术标签:

【中文标题】如何在 MySQL 函数中引发错误【英文标题】:How to raise an error within a MySQL function 【发布时间】:2010-10-02 17:13:36 【问题描述】:

我创建了一个 mysql 函数,如果为参数传递的值无效,我想提出一个错误。在 MySQL 函数中引发错误的选项有哪些?

【问题讨论】:

【参考方案1】:

您必须定义异常处理程序。看看http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html

【讨论】:

异常处理程序用于捕获异常。问题是关于引发异常。【参考方案2】:

在 MySQL 5 中,您可能会通过调用不存在的存储过程 (CALL raise_error) 或将无效值传递给查询(例如将 null 传递给 NOT NULL 约束字段)来引发错误。这是 Roland Bouman 关于从 MySQL 函数中引发错误的有趣帖子:

http://rpbouman.blogspot.com/2005/11/using-udf-to-raise-errors-from-inside.html

【讨论】:

【参考方案3】:

您还可以使用无效数量的参数调用现有函数。

【讨论】:

【参考方案4】:

它实际上是所有三个答案的组合。您调用一个不存在的过程来引发错误,然后声明一个退出处理程序来捕获您生成的错误。下面是一个例子,如果要删除的行设置了外键id,则使用SQLSTATE 42000(过程不存在)在删除前抛出错误:

DROP PROCEDURE IF EXISTS decount_test;

DELIMITER //

CREATE DEFINER = 'root'@'localhost' PROCEDURE decount_test ( p_id bigint )
DETERMINISTIC MODIFIES SQL DATA
BEGIN
  DECLARE EXIT HANDLER FOR SQLSTATE '42000'
    SELECT 'Invoiced barcodes may not have accounting removed.';
  IF (SELECT invoice_id 
       FROM accounted_barcodes
       WHERE id = p_id
    ) THEN
    CALL raise_error;
 END IF;
 DELETE FROM accounted_barcodes WHERE id = p_id;
END //

DELIMITER ;

输出:

call decount_test(123456);
+----------------------------------------------------+
| Invoiced barcodes may not have accounting removed. |
+----------------------------------------------------+
| Invoiced barcodes may not have accounting removed. | 
+----------------------------------------------------+

【讨论】:

需要注意的是,这只对存储过程有效,对函数无效。在函数中,处理程序中的SELECT 将导致无法从函数返回集合的神秘错误。 它只适用于一条错误消息。实际上,您将有多个验证并需要引发不同的错误,但单个退出处理程序可能不是要走的路。【参考方案5】:

MySQL 5.5 引入了信号,类似于其他语言中的异常:

http://dev.mysql.com/doc/refman/5.5/en/signal.html

例如在mysql命令行客户端中:

mysql> SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Custom error';
ERROR 1644 (45000): Custom error

【讨论】:

【参考方案6】:

为什么不将VARCHAR 存储在声明的INTEGER 变量中?

DELIMITER $$ DROP FUNCTION IF EXISTS `raise_error` $$
CREATE FUNCTION `raise_error`(MESSAGE VARCHAR(255)) 
RETURNS INTEGER DETERMINISTIC BEGIN
  DECLARE ERROR INTEGER;
  set ERROR := MESSAGE;
  RETURN 0;
END $$ DELIMITER ;
-- set @foo := raise_error('something failed'); -- or within a query

错误信息是:

不正确的整数值:行中列“ERROR”的“失败” 1

它并不完美,但它提供了一个非常具有描述性的消息,并且您不必编写任何扩展 DLL。

【讨论】:

这很聪明。迄今为止最简单明了的方法。 @SystemParadox 在您必须报告足够多的错误之后......找到更好的方法变得有点痴迷。 (首先是call raise_error_life_sucks();,然后它逐渐演变为我需要它的地方我不能只调用一个proc) @Isblsb,您需要将 sql_mode 设置为 strict_trans_tables 才能引发错误。 strict_trans_tables 需要在创建函数时生效。

以上是关于如何在 MySQL 函数中引发错误的主要内容,如果未能解决你的问题,请参考以下文章

每当 MySQL 抛出警告时,我如何通知 sqlalchemy 引发错误?

如何让 MySQL 在 SQL 中引发条件运行时异常

如何创建一个函数以在 openerp 中引发错误

如何重写此 MySQL 查询,使其不会引发此错误:您无法在 FROM 子句中指定目标表 'crawlLog' 进行更新?

如何在 Firebase 可调用云函数上引发错误?

如何在 Django 中引发 410 错误