MySql delimiter的作用是什么

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

其中DELIMITER 定好结束符为"$$", 然后最后又定义为";", MYSQL的默认结束符为";".


详细解释:

其实就是告诉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 的客户端工具在有些地方是各自为政,各有各的一套。

(0)

相关推荐

  • mysql limit分页优化方法分享

    同样是取10条数据 select * from yanxue8_visit limit 10000,10 和 select * from yanxue8_visit limit 0,10 就不是一个数量级别的. 网上也很多关于limit的五条优化准则,都是翻译自MySQL手册,虽然正确但不实用.今天发现一篇文章写了些关于limit优化的,很不错. 文中不是直接使用limit,而是首先获取到offset的id然后直接使用limit size来获取数据.根据他的数据,明显要好于直接使用limit.这

  • 详解MySQL的limit用法和分页查询语句的性能分析

    limit用法 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接受一个或两个数字参数.参数必须是一个整数常量.如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目.初始记

  • php下MYSQL limit的优化

    同样是取10条数据 select * from yanxue8_visit limit 10000,10 和select * from yanxue8_visit limit 0,10 就不是一个数量级别的. 网上也很多关于limit的五条优化准则,都是翻译自mysql手册,虽然正确但不实用.今天发现一篇文章写了些关于limit优化的,很不错.原文地址:http://www.zhenhua.org/article.asp?id=200 文中不是直接使用limit,而是首先获取到offset的id

  • Mysql中limit的用法方法详解与注意事项

    在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心, mysql已经为我们提供了这样一个功能. SELECT * FROM table  LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接受一个或两个数字参数.参数必须 是一个整数常量.如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回 记录行的最大数目.初始记录行的偏

  • mysql查询语句通过limit来限制查询的行数

    mysql查询语句,通过limit来限制查询的行数. 例如: select name from usertb where age > 20 limit 0, 1; //限制从第一条开始,显示1条 select name from usertb where age > 20 limit 1; //同上面的一个效果 select name from usertb where age > 20 limit 4, 1; //显示从第五条开始,显示1条

  • mysql优化limit查询语句的5个方法

    mysql的分页比较简单,只需要limit offset,length就可以获取数据了,但是当offset和length比较大的时候,mysql明显性能下降 1.子查询优化法 先找出第一条数据,然后大于等于这条数据的id就是要获取的数据 缺点:数据必须是连续的,可以说不能有where条件,where条件会筛选数据,导致数据失去连续性,具体方法请看下面的查询实例: 复制代码 代码如下: mysql> set profiling=1; Query OK, 0 rows affected (0.00

  • MySql中取前几行数据使用limit来完成

    在mysql中是没有top关键字的,在mysql中可以用limit来完成功能. order by id desc limit 10 按照id的倒序排序 取出前10条 order by id desc limit 0,10 按照id的倒序排序 取出前10条 order by id limit 5,10 按照id的正序排序 从第5条开始取10条 复制代码 代码如下: SELECT cat_id FROM shop_goods_type order by cat_id desc limit 1

  • mysql delete limit 使用方法详解

    mysql delete limit优点: 用于DELETE的MySQL唯一的LIMIT row_count选项用于告知服务器在控制命令被返回到客户端前被删除的行的最大值.本选项用于确保一个DELETE语句不会占用过多的时间.您可以只重复DELETE语句,直到相关行的数目少于LIMIT值为止. 如果DELETE语句包括一个ORDER BY子句,则各行按照子句中指定的顺序进行删除.此子句只在与LIMIT联用是才起作用.例如,以下子句用于查找与WHERE子句对应的行,使用timestamp_colu

  • 深入分析Mysql中limit的用法

    Mysql中limit的用法:在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM table   LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接受一个或两个数字参数.参数必须是一个整数常量.如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行

  • MySql delimiter的作用是什么

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

  • Mysql中explain作用详解

    一.MYSQL的索引 索引(Index):帮助Mysql高效获取数据的一种数据结构.用于提高查找效率,可以比作字典.可以简单理解为排好序的快速查找的数据结构. 索引的作用:便于查询和排序(所以添加索引会影响where 语句与 order by 排序语句). 在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据.这样就可以在这些数据结构上实现高级查找算法.这些数据结构就是索引. 索引本身也很大,不可能全部存储在内存中,所以索引往往以索引文件的形式存储在磁盘上. 我们

  • MySQL 游标的作用与使用相关

    定义 我们经常会遇到这样的一种情况,需要对我们查询的结果进行遍历操作,并对遍历到的每一条数据进行处理,这时候就会使用到游标. 所以:游标(Cursor)是处理数据的一种存储在MySQL服务器上的数据库查询方法,为了查看或者处理结果集中的数据,提供了在结果集中一次一行遍历数据的能力. 游标主要用在循环处理.存储过程.函数.触发器 中. 游标的作用 比如我们上面那个students学生,需要对每个用户进行遍历,然后根据他们的其他评价进行加分或者减分.这时候我们就需要查询到所有的学生信息(包含成绩).

  • 解析MySQL索引的作用

    目录 1.索引用于减少需要扫描的记录数量 2.索引用于排序 1.分析下面的查询语句: 2.使用联合索引进行排序时的注意事项 3.不可以使用索引进行排序的情况: 3.索引用于分组 总结 面试题:索引的作用? 首先建立一张数据库表: create table single_table( id int not auto_increment, key1 varchar(100), key2 int, key3 varchar(100), key_part1 varchar(100), key_part2

  • mysql socket文件作用详解

    网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,一般在配置部署mysql环境时都会在mysql的my.cnf文件中[mysqld]栈下添加上socket文件的路径,而这样做的好处是如果启用了多实例mysql时,可以通过socket文件来快速的登录mysql对应不同端口下的实例,如在一台有部署2个实例的mysql服务一个是用3306,一个是用3307端口,那么就可以通过2个不同的socket文件快速的登录 mysql -uroot -p --socket=

  • mysql sql_mode="" 的作用说明

    sql_mode="",即强制不设定MySql模式(如不作输入检测.错误提示.语法模式检查等)应该能提高性能,但有如下问题: 如果插入了不合适数据(错误类型或超常),mysql会将数据设为"最好的可能数据"而不报错,如: /数字 设为:0/可能最小值/可能最大值 /字符串 设为:空串/能够存储的最大容量字符串 /表达式 设为:返回一个可用值(1/0-null) 所以,解决办法是:所有列都要采用默认值,这对性能也好. mysql_mode的详细描述: 在mysql 5

  • 详解 Mysql中的delimiter定义及作用

    初学mysql时,可能不太明白delimiter的真正用途,delimiter在mysql很多地方出现,比如存储过程.触发器.函数等. 学过oracle的人,再来学mysql就会感到很奇怪,百思不得其解. 其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了. 默认情况下,delimiter是分号(;) . 在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令.如输入下面的语句 mysql> select * from test_table;

  • 详细聊聊MySQL中auto_increment有什么作用

    目录 问题来源 解释 注意事项 总结 问题来源 很多时候,MySQL语句中会出现[auto_increment]这个词汇,大多数时候,表都是自动生成的,刚开始学习MySQL数据库时会学习到,后来,渐渐地可能会忘记,那么这个语句的作用到底是什么意思?下面,来汇总一下: 解释 auto_increment是用于主键自动增长的,从1开始增长,当你把第一条记录删除时,再插入第二条数据时,主键值是2,不是1. 例如: create table test ( id int(10) not null auto

  • mysql存储过程详解

    1.存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它. 一个存储过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的.数据库中的存储过程可以看做是对编程中面

  • MySQL中触发器的基础学习教程

    0.触发器的基本概念 触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力. 数据库触发器有以下的作用: (1).安全性.可以基于数据库的值使用户具有操作数据库的某种权利. # 可以基于时间限制用户的操作,例如不允许下班后和节假日修改数据库数据. # 可以基于数据库中的数据限制用户的操作,例如不允许股票的价格的升幅一次超过10%. (2).审计.可以跟踪用户对数据库的操作. # 审计用户操作数据库的语句. # 把用户对数

随机推荐