MySQL创建存储过程的语法及分隔符

40

我正在尝试创建一个使用分隔符的 MySQL 存储过程,像这样:

use am;

DELIMITER $$

CREATE PROCEDURE addfields()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE acc INT(16);
  DECLARE validId INT DEFAULT 0;

END $$

DELIMITER ;

它给我一个错误:

#1304 - PROCEDURE addfields already exists

如何使用分隔符编写存储过程,并在存在时删除它的正确语法是什么?


1
请注意,你的语法是正确的,这个错误只是意味着该过程已经被创建(你第二次运行脚本)。首先删除它:DROP PROCEDURE addfields; 在执行 USE 之后,在执行 DELIMITER 之前(因为我使用了 ;,如果你使用 DROP PROCEDURE addfields$$,那么它将在 DELIMITER 之后和 CREATE PROCEDURE 之前)。 - Xenos
5个回答

74

MySQL存储过程语法入门(使用终端):

1. 打开终端并登录mysql,如下所示:

el@apollo:~$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
mysql> 

2.查看是否有任何程序:

mysql> show procedure status;
+-----------+---------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db        | Name          | Type      | Definer | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+-----------+---------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
|   yourdb  | sp_user_login | PROCEDURE | root@%  | 2013-12-06 14:10:25 | 2013-12-06 14:10:25 | DEFINER       |         | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
+-----------+---------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set (0.01 sec)

我已经定义好了,你可能还没有开始。

3. 修改数据库之后,删除它。

mysql> use yourdb;
Database changed

mysql> drop procedure if exists sp_user_login;
Query OK, 0 rows affected (0.01 sec)
    
mysql> show procedure status;
Empty set (0.00 sec)
    

4. 好的,现在我没有定义任何存储过程。制作最简单的一个:

mysql> delimiter //
mysql> create procedure foobar()
    -> begin select 'hello'; end//
Query OK, 0 rows affected (0.00 sec)

//表示您已经输入完存储过程的命令,并将结果传输到终端。存储过程名为foobar,不接受任何参数,应返回“hello”。

5. 看一下它是否存在,记得设置回分隔符!:

 mysql> show procedure status;
 -> 
 -> 

懂了! 为什么这个不行? 你记得把分隔符设为//了吗? 把它改回;

6. 把分隔符改回来,再看看这个过程:

mysql> delimiter ;
mysql> show procedure status;
+-----------+--------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db        | Name   | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+-----------+--------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| yourdb    | foobar | PROCEDURE | root@localhost | 2013-12-06 14:27:23 | 2013-12-06 14:27:23 | DEFINER       |         | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
+-----------+--------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)

   

7. 运行它:

mysql> call foobar();
+-------+
| hello |
+-------+
| hello |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

你好世界完成了,我们可以用更好的东西来覆盖它。

8. 删除 foobar ,重新定义它以接受一个参数并重新运行:

mysql> drop procedure foobar;
Query OK, 0 rows affected (0.00 sec)

mysql> show procedure status;
Empty set (0.00 sec)

mysql> delimiter //
mysql> create procedure foobar (in var1 int)
    -> begin select var1 + 2 as result;
    -> end//
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call foobar(5);
+--------+
| result |
+--------+
|      7 |
+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

太好了!我们已经建立了一个接收输入、修改它并输出结果的过程。现在让我们来做一个输出变量。

9. 删除"foobar",创建一个输出变量,并运行它:

mysql> delimiter ;
mysql> drop procedure foobar;
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter //
mysql> create procedure foobar(out var1 varchar(100))
    -> begin set var1="kowalski, what's the status of the nuclear reactor?";
    -> end//
Query OK, 0 rows affected (0.00 sec)


mysql> delimiter ;
mysql> call foobar(@kowalski_status);
Query OK, 0 rows affected (0.00 sec)

mysql> select @kowalski_status;
+-----------------------------------------------------+
| @kowalski_status                                    |
+-----------------------------------------------------+
| kowalski, what's the status of the nuclear reactor? |
+-----------------------------------------------------+
1 row in set (0.00 sec)

10. MySQL中INOUT用法示例:

mysql> select 'ricksays' into @msg;
Query OK, 1 row affected (0.00 sec)


mysql> delimiter //
mysql> create procedure foobar (inout msg varchar(100))
-> begin
-> set msg = concat(@msg, " never gonna let you down");
-> end//


mysql> delimiter ;


mysql> call foobar(@msg);
Query OK, 0 rows affected (0.00 sec)


mysql> select @msg;
+-----------------------------------+
| @msg                              |
+-----------------------------------+
| ricksays never gonna let you down |
+-----------------------------------+
1 row in set (0.00 sec)

好的,它起作用了,它将字符串连接在一起。所以你定义了一个变量msg,把这个变量传递给存储过程foobar,而@msg被foobar写入。

现在你知道如何使用分隔符制作存储过程了。继续学习本教程,在存储过程中开始使用变量: http://net.tutsplus.com/tutorials/an-introduction-to-stored-procedures/


4
太棒了,谢谢你。这应该被加入维基百科。 - pspahn
1
非常棒的解释。非常感谢 :-) - Ravi Hirani

62

以下是带有分隔符的MYSQL存储过程示例以及如何调用它的方法。

DELIMITER $$

DROP PROCEDURE IF EXISTS `sp_user_login` $$
CREATE DEFINER=`root`@`%` PROCEDURE `sp_user_login`(
  IN loc_username VARCHAR(255),
  IN loc_password VARCHAR(255)
)
BEGIN

  SELECT user_id,
         user_name,
         user_emailid,
         user_profileimage,
         last_update
    FROM tbl_user
   WHERE user_name = loc_username
     AND password = loc_password
     AND status = 1;

END $$

DELIMITER ;

并通过mysql_connection规范进行调用

$loginCheck="call sp_user_login('".$username."','".$password."');";

它会返回该过程的结果。


它返回什么?它可以返回任何值或者返回真/假。 - Phoenix
我有一个问题:为什么有些语句以 ; 结尾,而其他语句以分隔符 $$ 结尾。如果分隔符表示语句的结尾,为什么不全部使用 $$,甚至为什么需要分隔符?难道不能只用 ; 结束语句吗?感到很困惑。 - Kellen Stuart
更改分隔符允许您在过程声明内使用标准分隔符,否则MySQL将在那里终止。一旦声明,您可以将其改回。 - inarilo
1
在 mariadb 上运行时,最后一个 DELIMITER 语句后面的空格是必需的,不确定 mysql 是否需要。 - Lanklaas
你也可以使用"create or replace procedure sp_user_login"来替换它,而不是先删除它。 - David Welborn
显示剩余3条评论

2

下面是我在MySQL中创建存储过程的代码:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `procedureName`(IN comId int)
BEGIN
select * from tableName 
         (add joins OR sub query as per your requirement)
         Where (where condition here)
END $$
DELIMITER ;

要调用此过程,请使用以下查询:

call procedureName(); // without parameter
call procedureName(id,pid); // with parameter

详情:

1)定义者:root是mysql的用户名,根据你自己的用户名进行更改。localhost是主机名,如果你在托管服务器上执行此查询,则可以将其更改为服务器的IP地址。

点击这里了解更多详情。


0

我已经创建了一个简单的MySQL存储过程,如下所示:

DELIMITER //
CREATE PROCEDURE GetAllListings()
 BEGIN
 SELECT nid, type, title  FROM node where type = 'lms_listing' order by nid desc;
END //
DELIMITER;

请按照以下步骤操作。创建完程序后,您可以查看并执行它。

这个回答似乎没有为讨论增添任何新内容,因为早期的回答已经涵盖了相关内容。如果您要在稍后添加一个回答,请说明您的回答显示了什么,而现有的回答尚未显示的内容。 - ToolmakerSteve

0

MySQL 存储过程创建

DELIMiTER $$
create procedure GetUserRolesEnabled(in UserId int)
Begin

select * from users
where id=UserId ;
END $$
DELIMITER ;

这个回答似乎没有为讨论增添任何新内容,因为早期的回答已经涵盖了相关内容。如果您要在稍后添加一个回答,请说明您的回答显示了什么,而现有的回答尚未显示的内容。 - ToolmakerSteve

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