尝试使用 MySQL 函数时返回以下错误。
#1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its
declaration and binary logging is enabled (you *might* want to use the less safe
log_bin_trust_function_creators variable)
几天前我开始使用复制..?不知道这是否可能有所懊恼?!但我知道一件事——它:)
如果我尝试覆盖(再次添加函数)会发生相同的错误。
函数
DELIMITER $$
DROP FUNCTION IF EXISTS `stock_in_stock_ids` $$
CREATE DEFINER=`dynaccount`@`localhost` FUNCTION `stock_in_stock_ids`(_running_total_limit INT, _product_id INT, _group_id INT) RETURNS TEXT
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE _running_count INT default 0;
DECLARE _id INT;
DECLARE _count INT;
DECLARE _ids TEXT DEFAULT NULL;
DECLARE _cur CURSOR FOR SELECT id, count FROM stock WHERE group_id=_group_id && type=2 && product_id=_product_id ORDER BY time DESC, id DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN _cur;
read_loop: LOOP
FETCH _cur INTO _id, _count;
IF done THEN
SET _ids = '0';
LEAVE read_loop;
END IF;
SET _running_count = _running_count + _count;
SET _ids = CONCAT_WS(',', _ids, _id);
IF _running_count >= _running_total_limit THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
CLOSE _cur;
RETURN _ids;
END $$
DELIMITER ;
这里有一篇帖子,可以保存我过去关于此错误的信息:http://forum.9kgames.com/default.aspx?g=posts&m=17
就我而言,我只需要在 create 函数中指定DETERMINISTIC
:
CREATE DEFINER=`dynaccount`@`localhost` FUNCTION `stock_in_stock_ids`(_running_total_limit INT, _product_id INT, _group_id INT)
RETURNS TEXT
DETERMINISTIC
READS SQL DATA
希望对您有所帮助
更新:链接不再有效,所以这是来自 archive.org 的副本:https://web.archive.org/web/20120310020353/http://forum.9kgames.com/default.aspx?g=posts&m=17
此警告在以下情况下上升
a). 你想创建一个存储函数和由于默认的MySQL服务器支持复制,即二进制日志记录被打开。要解决此问题,这里有一些提示:
1). 对于存储函数本身。创建存储函数时,必须声明它是确定性的,或者声明它不会修改数据。否则,数据恢复或复制可能不安全。默认情况下,要接受 CREATE FUNCTION
语句,必须至少显式指定 DETERMINISTIC
、 NO SQL
或 READS SQL DATA
中的一个。否则会发生错误:法典:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,
or READS SQL DATA in its declaration and binary logging is enabled
(you *might* want to use the less safe log_bin_trust_function_creators
variable).
此函数是确定性的(并且不会修改数据),因此它是安全的:法典:
CREATE FUNCTION f1(i INT)
RETURNS INT
DETERMINISTIC
READS SQL DATA
BEGIN
RETURN i;
END;
此函数使用非确定性的 UUID(),因此该函数也不是确定性的,也不安全:法典:
CREATE FUNCTION f2()
RETURNS CHAR(36) CHARACTER SET utf8
BEGIN
RETURN UUID();
END;
此函数会修改数据,因此可能不安全:法典:
CREATE FUNCTION f3(p_id INT)
RETURNS INT
BEGIN
UPDATE t SET modtime = NOW() WHERE id = p_id;
RETURN ROW_COUNT();
END;
MySQL不会检查声明为确定性的函数是否没有产生非确定性结果的语句。虽然可以在不指定DETERMINISTIC
的情况下创建确定性存储函数,但从MySQL 5.1.15开始,您不能使用基于语句的二进制日志记录来执行此函数。若要执行此类函数,必须使用基于行或混合二进制日志记录。或者,如果在函数定义中显式指定 DETERMINISTIC,则可以使用任何类型的日志记录,包括基于语句的日志记录。
2)虽然你已经完成了步骤1,但在大多数情况下,你可能仍然需要SUPER权限将全局变量log_bin_trust_function_creators
设置为true,然后运行以创建存储函数。要放宽函数创建时的上述条件(您必须具有 SUPER 权限,并且必须声明函数确定性或不修改数据),请将全局log_bin_trust_function_creators
系统变量设置为 1。默认情况下,此变量的值为 0,但您可以像这样更改它:
mysql> SET GLOBAL log_bin_trust_function_creators = 1;
还可以在启动服务器时使用 log_bin_trust_function_creators
选项设置此变量。如果未启用二进制日志记录,则log_bin_trust_function_creators
不适用。创建函数不需要 SUPER,除非如前所述,函数定义中的 DEFINER 值需要它。注意:如果应用程序在多租户托管服务器上运行,而托管公司不希望这样做,则可能需要修改存储过程,而不是使用存储函数。
您应该在"返回文本"和"开始"之间写以下行。它会工作..:)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
默认情况下,要接受 CREATE FUNCTION
语句,必须显式指定at least one of DETERMINISTIC, NO SQL, or READS SQL DATA
。否则会发生错误:
错误 1418 (HY000):此例程没有确定性、 SQL 和或在其声明中读取 SQL 数据并启用二进制日志记录(您可能希望使用不太安全的log_bin_trust_routine_creators变量)
如果set log_bin_trust_routine_creators to 1
,则会删除例程具有确定性或不修改数据的要求。