`
deepfuture
  • 浏览: 4334882 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
博客专栏
073ec2a9-85b7-3ebf-a3bb-c6361e6c6f64
SQLite源码剖析
浏览量:79435
1591c4b8-62f1-3d3e-9551-25c77465da96
WIN32汇编语言学习应用...
浏览量:68412
F5390db6-59dd-338f-ba18-4e93943ff06a
神奇的perl
浏览量:101532
Dac44363-8a80-3836-99aa-f7b7780fa6e2
lucene等搜索引擎解析...
浏览量:281270
Ec49a563-4109-3c69-9c83-8f6d068ba113
深入lucene3.5源码...
浏览量:14619
9b99bfc2-19c2-3346-9100-7f8879c731ce
VB.NET并行与分布式编...
浏览量:65612
B1db2af3-06b3-35bb-ac08-59ff2d1324b4
silverlight 5...
浏览量:31336
4a56b548-ab3d-35af-a984-e0781d142c23
算法下午茶系列
浏览量:45222
社区版块
存档分类
最新评论

MySql中delimiter的作用是什么?

阅读更多

MySql中delimiter的作用是什么?

这个命令与存储过程没什么关系吧。
其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了。
默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,
那么回车后,mysql将会执行该命令。如输入下面的语句
mysql> select * from test_table;
然后回车,那么MySQL将立即执行该语句。

但有时候,不希望MySQL这么做。在为可能输入较多的语句,且语句中包含有分号。
如试图在命令行客户端中输入如下语句
mysql> CREATE FUNCTION `SHORTEN`(S VARCHAR(255), N INT)
mysql>     RETURNS varchar(255)
mysql> BEGIN
mysql> IF ISNULL(S) THEN
mysql>    RETURN '';
mysql> ELSEIF N<15 THEN
mysql>     RETURN LEFT(S, N);
mysql> ELSE
mysql>     IF CHAR_LENGTH(S) <=N THEN
mysql>    RETURN S;
mysql>     ELSE
mysql>    RETURN CONCAT(LEFT(S, N-10), '...', RIGHT(S, 5));
mysql>     END IF;
mysql> END IF;
mysql> END;

默认情况下,不可能等到用户把这些语句全部输入完之后,再执行整段语句。
因为mysql一遇到分号,它就要自动执行。
即,在语句RETURN '';时,mysql解释器就要执行了。
这种情况下,就需要事先把delimiter换成其它符号,如//或$$。
mysql> delimiter //
mysql> CREATE FUNCTION `SHORTEN`(S VARCHAR(255), N INT)
mysql>     RETURNS varchar(255)
mysql> BEGIN
mysql> IF ISNULL(S) THEN
mysql>    RETURN '';
mysql> ELSEIF N<15 THEN
mysql>     RETURN LEFT(S, N);
mysql> ELSE
mysql>     IF CHAR_LENGTH(S) <=N THEN
mysql>    RETURN S;
mysql>     ELSE
mysql>    RETURN CONCAT(LEFT(S, N-10), '...', RIGHT(S, 5));
mysql>     END IF;
mysql> END IF;
mysql> END;//

这样只有当//出现之后,mysql解释器才会执行这段语句

 

例子:

mysql> delimiter //

mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END;
-> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)

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

 

 

 

 

本文代码在 MySQL 5.0.41-community-nt 下运行通过。

编写了个统计网站访问情况(user agent)的 MySQL 存储过程。就是下面的这段 SQL 代码。

drop procedure if exists pr_stat_agent;

-- call pr_stat_agent ('2008-07-17', '2008-07-18')

create procedure pr_stat_agent
(
   pi_date_from  date
  ,pi_date_to    date
)
begin
   -- check input
   if (pi_date_from is null) then
      set pi_date_from = current_date();
   end if;

   if (pi_date_to is null) then
      set pi_date_to = pi_date_from;
   end if;

   set pi_date_to = date_add(pi_date_from, interval 1 day);

   -- stat
   select agent, count(*) as cnt
     from apache_log
    where request_time >= pi_date_from
      and request_time <  pi_date_to
    group by agent
    order by cnt desc;
end;

我在 EMS SQL Manager 2005 for MySQL 这个 MySQL 图形客户端下可以顺利运行。但是在 SQLyog MySQL GUI v5.02 这个客户端就会出错。最后找到原因是没有设置好 delimiter 的问题。默认情况下,delimiter “;” 用于向 MySQL 提交查询语句。在存储过程中每个 SQL 语句的结尾都有个 “;”,如果这时候,每逢 “;” 就向 MySQL 提交的话,当然会出问题了。于是更改 MySQL 的 delimiter,上面 MySQL 存储过程就编程这样子了:

delimiter //;     -- 改变 MySQL delimiter 为:“//”

drop procedure if exists pr_stat_agent //

-- call pr_stat_agent ('2008-07-17', '2008-07-18')

create procedure pr_stat_agent
(
   pi_date_from  date
  ,pi_date_to    date
)
begin
   -- check input
   if (pi_date_from is null) then
      set pi_date_from = current_date();
   end if;

   if (pi_date_to is null) then
      set pi_date_to = pi_date_from;
   end if;

   set pi_date_to = date_add(pi_date_from, interval 1 day);

   -- stat
   select agent, count(*) as cnt
     from apache_log
    where request_time >= pi_date_from
      and request_time <  pi_date_to
    group by agent
    order by cnt desc;
end; //

delimiter ; //   -- 改回默认的 MySQL delimiter:“;”

当然,MySQL delimiter 符号是可以自由设定的,你可以用 “/” 或者“$$” 等。但是 MySQL 存储过程中比较常见的用法是 “//” 和 “$$”。上面的这段在 SQLyog 中的代码搬到 MySQL 命令客户端(MySQL Command Line Client)却不能执行。

mysql> delimiter //;     -- 改变 MySQL delimiter 为:“//”
mysql>
mysql> drop procedure if exists pr_stat_agent //
    ->
    -> -- call pr_stat_agent ('2008-07-17', '2008-07-18')
    ->
    -> create procedure pr_stat_agent
    -> (
    ->    pi_date_from  date
    ->   ,pi_date_to    date
    -> )
    -> begin
    ->    -- check input
    ->    if (pi_date_from is null) then
    ->       set pi_date_from = current_date();
    ->    end if;
    ->
    ->    if (pi_date_to is null) then
    ->       set pi_date_to = pi_date_from;
    ->    end if;
    ->
    ->    set pi_date_to = date_add(pi_date_from, interval 1 day);
    ->
    ->    -- stat
    ->    select agent, count(*) as cnt
    ->      from apache_log
    ->     where request_time >= pi_date_from
    ->       and request_time <  pi_date_to
    ->     group by agent
    ->     order by cnt desc;
    -> end; //
    ->
    -> delimiter ; //   -- 改回默认的 MySQL delimiter:“;”
    -> //
    -> //
    -> //
    -> ;
    -> ;
    ->

真是奇怪了!最后终于发现问题了,在 MySQL 命令行下运行 “delimiter //; ” 则 MySQL 的 delimiter 实际上是 “//;”,而不是我们所预想的 “//”。其实只要运行指令 “delimiter //” 就 OK 了。

mysql> delimiter //     -- 末尾不要符号 “;”
mysql>
mysql> drop procedure if exists pr_stat_agent //
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> -- call pr_stat_agent ('2008-07-17', '2008-07-18')
mysql>
mysql> create procedure pr_stat_agent
    -> (
    ->    pi_date_from  date
    ->   ,pi_date_to    date
    -> )
    -> begin
    ->    -- check input
    ->    if (pi_date_from is null) then
    ->       set pi_date_from = current_date();
    ->    end if;
    ->
    ->    if (pi_date_to is null) then
    ->       set pi_date_to = pi_date_from;
    ->    end if;
    ->
    ->    set pi_date_to = date_add(pi_date_from, interval 1 day);
    ->
    ->    -- stat
    ->    select agent, count(*) as cnt
    ->      from apache_log
    ->     where request_time >= pi_date_from
    ->       and request_time <  pi_date_to
    ->     group by agent
    ->     order by cnt desc;
    -> end; //
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> delimiter ;  -- 末尾不要符号 “//”
mysql>

顺带一提的是,我们可以在 MySQL 数据库中执行在文件中的 SQL 代码。例如,我把上面存储过程的代码放在文件 d:\pr_stat_agent.sql 中。可以运行下面的代码建立存储过程。

mysql> source d:\pr_stat_agent.sql
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

source 指令的缩写形式是:“\.”

mysql> \. d:\pr_stat_agent.sql
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

最后,可见 MySQL 的客户端工具在有些地方是各自为政,各有各的一套。

分享到:
评论

相关推荐

    详解 Mysql中的delimiter定义及作用

    初学mysql时,可能不太明白delimiter的真正用途,delimiter在mysql很多地方出现,比如存储过程、触发器、函数等。 学过oracle的人,再来学mysql就会感到很奇怪,百思不得其解。 其实就是告诉mysql解释器,该段命令...

    MySql中 delimiter 详解.docx

    其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了。默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。

    MySql delimiter的作用是什么

    MYSQL导出一个SQL后: DELIMITER $$ DROP TRIGGER IF EXISTS `updateegopriceondelete`$$ CREATE TRIGGER `updateegopriceondelete` AFTER DELETE ON `customerinfo` FOR EACH ROW BEGIN DELETE FROM egoprice ...

    MySQL存储过程的异常处理方法

    mysql&gt; delimiter $$ mysql&gt; mysql&gt; CREATE PROCEDURE myProc -&gt; (p_first_name VARCHAR(30), -&gt; p_last_name VARCHAR(30), -&gt; p_city VARCHAR(30), -&gt; p_description VARCHAR(30), -&gt; OUT p_sqlcode INT, -&gt; ...

    csharp mysql客户端类

    为解决在使用官方客户端类执行mysql脚本时,仅用Execute方法,不支持返回数据结果集的问题, 参照官方MySql.Data.dll中的源码写了一个扩展类,可以执行 MySQL Workbench中可执行的任何脚本,并返回select结果集到一...

    mysql中存储过程的实例教程

    “ delimiter // ” 的作用是将语句结束符更改为 “ // ” 。 “ in nc varchar(50) …… in address varchar(50) ” 表示要向存储过程中传入的参数。 实现过程 ( 1 )通过 PHP 预定义类 mysqli ,实现与 MySQL ...

    MySQL创建存储过程批量插入10万条数据

    MySQL创建存储过程批量插入10万条数据 存储过程 1、首先防止主键冲突,我们清空表。 TRUNCATE table A_student; 2、编写存储过程 delimiter ‘$’; CREATE PROCEDURE batchInsert(in args int) BEGIN declare i int ...

    SQL导出MySQL单个存储过程.txt

    SQL语句对单个的MySQL存储过程导出 首先确保参数secure-file-priv='' 表示不限制mysqld在任意目录的导入导出 打开my.cnf或my.ini,加入如下语句后重启mysql服务。 secure_file_priv='' sql语法只修改下面的...

    MySQL 数据库结构管理小工具,MySQL 表、视图、触发器、函数、过程结构同步管理MySQL DDL

    MySQL 数据库结构管理小工具,MySQL 表、视图、触发器、函数、过程结构同步管理,支持MySQL5.x ~ MySQL8,可保存创建对象的选择,导出SQL,当表、过程超过100着实令人头大,特意读取了表等的创建时间,可根据时间...

    socket身份校验(存储过程)mysql数据库

    用mysql的存储过程查询表中的数据 mysql数据库 tb_users表 use test; DROP TABLE IF EXISTS tb_users; CREATE TABLE IF NOT EXISTS tb_users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, password ...

    MySQL存储过程中使用WHILE循环语句的方法

    本文实例讲述了MySQL存储过程中使用WHILE循环语句的方法。分享给大家供大家参考。具体如下: mysql&gt; mysql&gt; delimiter $$ mysql&gt; mysql&gt; CREATE PROCEDURE myProc() -&gt; BEGIN -&gt; -&gt; DECLARE i int; -&gt; SET i=1;...

    PHP MYSQL 脚本运行器

    这个是一个单页面的MySQL脚本执行程序,PHP写的,当无法通过远程客户端连接MySQL,同时空间服务商提供的数据库管理器版本过低无法创建存储过程(因为要用到DELIMITER)的时候,可以用这个小东西,只有几K,比起穿上一...

    mysql技巧总结大全

    在mysql客户端定义存储过程的时候使用delimiter命令来把语句定界符从;变为 当使用delimiter命令时 你应该避免使用反斜杠 ‘&quot;’ 字符 因为那是MySQL的转义字符 "&gt;CREATE PROCEDURE存储过程名 参数列表 BEGIN ...

    MySQL数据库:流程控制语句while语句.pptx

    说明:语句首先判断search_condition是否为真,不为真则执行statement_list中的语句,然后再次进行判断,为真则继续循环,不为真则结束循环。begin_label和end_label是WHILE语句的标注。除非begin_label存在,否则...

    mysql中迅速插入百万条测试数据的方法

    对比一下,首先是用 mysql 的存储过程弄的: 代码如下: mysql&gt;delimiter $ mysql&gt;SET AUTOCOMMIT = 0$$ mysql&gt; create procedure test() begin declare i decimal (10) default 0 ; dd:loop INSERT INTO `million` (`...

    MySQL 自定义函数CREATE FUNCTION示例

    mysql&gt; delimiter $$ mysql&gt; mysql&gt; CREATE FUNCTION myFunction -&gt; (in_string VARCHAR(255), -&gt; in_find_str VARCHAR(20), -&gt; in_repl_str VARCHAR(20)) -&gt; -&gt; RETURNS VARCHAR(255) -&gt; BEGIN -&gt; DECLARE l_new_...

    MySql函数-取一个字符串分隔后指定位置的子字符串

    一、函数功能:对字符串进行分隔数组,取指定顺序位置的子字符串,支持左右双向获取,支持...二、函数格式:fn_get_split_val(in_str varchar,in_delimiter varchar,in_order int,in_default varchar) 三、测试用例

    mysql表数据定时随机生成.txt

    DELIMITER $$ ALTER DEFINER=`root`@`%` EVENT `NewEvent` ON SCHEDULE EVERY 30 SECOND STARTS '2018-10-08 14:00:00' ON COMPLETION NOT PRESERVE ENABLE DO CALL update_a()$$ DELIMITER ; 储存...

Global site tag (gtag.js) - Google Analytics