MySQL 8.4 Reference Manual  /  Stored Objects  /  Defining Stored Programs

27.1 定义存储程序

每个存储程序都包含一个体,体内是一个SQL语句。这句语句可能是一个由分号(;)字符分隔的复合语句。例如,以下存储程序的体内是一个BEGIN ... END块,该块包含一个SET语句和一个REPEAT循环,该循环自身包含另一个SET语句:

CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
  SET @x = 0;
  REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END;

如果使用mysql客户端程序定义一个存储程序包含分号字符,出现问题。默认情况下,mysql自身识别分号作为语句分隔符,因此您必须临时重新定义分隔符,以便使mysql将整个存储程序定义传递给服务器。

要重新定义mysql分隔符,请使用delimiter命令。以下示例显示了如何对mysql客户端程序中的dorepeat()过程进行重新定义。将分隔符更改为//以便将整个定义传递给服务器,然后恢复到;之前调用过程时。这样可以使;分隔符在过程体内被传递给服务器,而不是被mysql客户端程序自身解释。

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)
    -> BEGIN
    ->   SET @x = 0;
    ->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> CALL dorepeat(1000);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x;
+------+
| @x   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)

您可以将分隔符重新定义为其他字符串,而不是//,分隔符可以是单个字符或多个字符。您应该避免使用反斜杠(\)字符,因为 MySQL 使用该字符作为转义字符。

以下是一个函数,它接受参数,使用 SQL 函数执行操作,并返回结果。在这种情况下,不需要使用delimiter,因为函数定义中没有内部;语句分隔符:

mysql> CREATE FUNCTION hello (s CHAR(20))
mysql> RETURNS CHAR(50) DETERMINISTIC
    -> RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world!  |
+----------------+
1 row in set (0.00 sec)