MySQL字符串比较函数学习(二) -- 比较函数 (MySQL学习)
发布于 2008-10-09 12:15 阅读:47,185 评论:0 标签: MySQL 字符串比较

      字符串比较函数函数在手册:这里。比较函数主要有三类:一个是用like子句;二是使用正则表达式的like子句;三是STRCMP函数了。前两者感觉更侧重搜索,第三个有大小的比较在里面。

      字符串比较中有以下四个规则

      1:MySQL 会自动将数字转化为字符串,反之亦然。 
      2:若想要将数字明确地转化为字符串,可使用 CAST()或 CONCAT()函数。
      3:若已经对一个字符串函数给定一个二进制字符串作为参数, 则所得到的结果字符串也是一个二进制字符串。
      4:一般而言, 若字符串比较中任意一个表达式是区分大小写的,则执行比较时也区分大小写。

      下面根据以上说的三类进行学习:

      一:使用like子句

  • expr LIKE pat [ESCAPE 'escape-char']

      模式匹配,使用SQL简单正规表达式比较。返回1 (TRUE) 0 (FALSE)。 若 expr pat 中任何一个为 NULL,则结果为 NULL

      模式不需要为文字字符串。例如,可以被指定为一个字符串表达式或表列。

      在模式中可以同LIKE一起使用以下两种通配符:

字符

说明

%

匹配任何数目的字符,甚至包括零字符 

_

只能匹配一种字符

以下是代码片段:

mysql> SELECT 'David!' LIKE 'David_';
       
-> 1

mysql> SELECT 'David!' LIKE '%D%v%';
       
-> 1

      若要对通配符的文字实例进行检验, 可将转义字符放在该字符前面。如果没有指定 ESCAPE字符, 则假设为‘\’。这个和一般的编程语言是一样的。

字符串

说明

\%

匹配一个  %’字符

\_

匹配一个 ‘_’ 字符

以下是代码片段:

mysql> SELECT 'David!' LIKE 'David\_';
       
-> 0

mysql> SELECT 'David_' LIKE 'David\_';
       
-> 1

      也可以指定一个不同的转义字符,需使用ESCAPE语句:

以下是代码片段:

mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
        -> 1

      以下两个语句举例说明了字符串比较不区分大小写,除非其中一个操作数为二进制字符串

以下是代码片段:

mysql> SELECT 'abc' LIKE 'ABC';
        -> 1

mysql> SELECT 'abc' LIKE BINARY 'ABC';
        -> 0

      在MySQL, LIKE 允许出现在数字表达式中 (这是标准SQL LIKE 的延伸)

以下是代码片段:

mysql> SELECT 10 LIKE '1%';
        -> 1

      注释由于 MySQL在字符串中使用 C转义语法(例如, 用‘\n’代表一个换行字符),在LIKE字符串中,必须将用到的‘\’双写。例如, 若要查找 ‘\n, 必须将其写成 ‘\\n’。而若要查找 ‘\, 则必须将其写成 it as \\\\;原因是反斜线符号会被语法分析程序剥离一次,在进行模式匹配时,又会被剥离一次,最后会剩下一个反斜线符号接受匹配。

      二:使用正则表达式的like子句

  • expr REGEXP pat expr RLIKE pat

      执行字符串表达式 expr 和模式pat 的模式匹配。该模式可以被延伸为正则表达式。正则表达式的语法在附录G:MySQL正则表达式中有详细讨论。若expr 匹配 pat则返回 1; 否则返回0。若 expr pat 任意一个为 NULL, 则结果为 NULL RLIKE REGEXP的同义词, 作用是为mSQL 提供兼容性。

      模式不需要为文字字符串。例如,可以被指定为一个字符串表达式或表列。

      注释由于在字符串中, MySQL使用 C 转义语法 (例如, 用‘\n’来代表换行字符 ),REGEXP字符串中必须将用到的‘\’ 双写。

      REGEXP 不区分大小写, 除非将其同二进制字符串同时使用

以下是代码片段:

mysql> SELECT 'Monty!' REGEXP 'm%y%%';
        -> 0

mysql> SELECT 'Monty!' REGEXP '.*';
        -> 1

mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
        -> 1

mysql> SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';
        -> 1  0

mysql> SELECT 'a' REGEXP '^[a-d]';
        -> 1

      在确定字符类型时,REGEXP RLIKE 使用当前字符集 (默认为cp1252 Latin1 )警告:这些操作符不支持多字节字元。

       三:使用函数:STRCMP

  • STRCMP(expr1,expr2)

      若所有的字符串均相同,则返回0;若根据当前分类次序,第一个参数小于第二个,则返回  -1,其它情况返回 1

以下是代码片段:

mysql> SELECT STRCMP('text', 'text2');
        -> -1

mysql> SELECT STRCMP('text2', 'text');
        -> 1

mysql> SELECT STRCMP('text', 'text');
        -> 0

      在执行比较时,STRCMP() 使用当前字符集。这使得默认的比较区分大小写,当操作数中的一个或两个都是二进制字符串时除外。

      说明:对于前两个都有其反操作。见下

  • expr NOT LIKE pat [ESCAPE 'escape-char']

          这相当于 NOT (expr LIKE pat [ESCAPE 'escape-char'])

  • expr NOT REGEXP pat expr NOT RLIKE pat

          这相当于NOT (expr REGEXP pat)

展开全文  
收起全文  
MySQL字符串比较函数学习(一) (MySQL学习)
发布于 2008-09-22 22:23 阅读:29,905 评论:0 标签: MySQL 字符串比较

       通览了一下手册,发现MySQL的字符串函数和PHP的函数在功能还是有很多地方相似的,很多都能在php中找到对应的函数。所以在这里,要向大家推荐一个文章:PHP 中执行排序与 MySQL 中排序。作者:明灵(dragon) , Fenng 。地址:http://www.dbanotes.net/arch/php_mysql_sort.html

      好,回到本文。先说两个特别的地方:

      1:函数中,假如结果的长度大于 max_allowed_packet 系统变量的最大值时,字符串值函数的返回值为NULL。请参见7.5.2节,“调节服务器参数”(http://dev.mysql.com/doc/refman/5.1/zh/optimization.html#server-parameters)。

      2:和PHP等编程语言不同,对于在字符串位置操作的函数,第一个位置的编号为 1。

      下面开始函数学习:

      1:字符串连接函数

      CONCAT(str1,str2,...)

      返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。或许有一个或多个参数。 如果所有参数均为非二进制字符串,则结果为非二进制字符串。 如果自变量中含有任一二进制字符串,则结果为一个二进制字符串。一个数字参数被转化为与之相等的二进制字符串格式;若要避免这种情况,可使用显式类型 cast, 例如: SELECT CONCAT(CAST(int_col AS CHAR), char_col)

以下是代码片段:

mysql> SELECT CONCAT('My', 'S', 'QL');
        -> 'MySQL'

mysql> SELECT CONCAT('My', NULL, 'QL');
        -> NULL

mysql> SELECT CONCAT(14.3);
        -> '14.3'

      下面这个concat_ws是concat的变体:

      CONCAT_WS(separator,str1,str2,...)

      CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。   第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。

以下是代码片段:

mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name');
        -> 'First name,Second name,Last Name'

mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name');
        -> 'First name,Last Name'


      CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

      这个函数和php的explode和implode、list、extract相似了。有兴趣的可以看看php的手册。

      2:字符串剪接函数

      INSERT(str,pos,len,newstr)

      这个函数,mysql中文手册翻译得太烂了,还是偶自己来吧:

      这个函数返回一个字符串:

      A:str字符串从位置pos(从1开始计算)开始(含第pos位),之后的pos位被字符串newstr取代;
      B:如果pos大于str的长度,则从str后面开始衔接;
      C:如果因len超出余后的长度,则位置pos之后(含第pos位)全被取代;
      D:如果pos为负数,返回str;
      E:如果len为负数,则情同len超出余后的长度,这和php的substr之类的函数不一样。

以下是代码片段:

mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
        -> 'QuWhattic'

mysql> SELECT INSERT('Quadratic', -1, 4, 'What');
        -> 'Quadratic'

mysql> SELECT INSERT('Quadratic', 3, 100, 'What');
        -> 'QuWhat'


      这个函数支持多字节字元。


      3:进制转换函数

      CONV(N,from_base,to_base)

      不同数基间转换数字。返回值为数字的N字符串表示,由from_base基转化为 to_base 基。如有任意一个参数为NULL,则返回值为 NULL。自变量 N 被理解为一个整数,但是可以被指定为一个整数或字符串。最小基数为 2 ,而最大基数则为 36。 If to_base 是一个负数,则 N 被看作一个带符号数。否则, N 被看作无符号数。 CONV() 的运行精确度为 64比特。

以下是代码片段:

mysql> SELECT CONV('a',16,2);
        -> '1010'
mysql> SELECT CONV('6E',18,8);
        -> '172'
mysql> SELECT CONV(-17,10,-18);
        -> '-H'
mysql> SELECT CONV(10+'10'+'10'+0xa,10,10);
        -> '40'

      请看PHP的:

      base_convert ― 在任意进制之间转换数字

      说明:
      string base_convert ( string $number , int $frombase , int $tobase )
      返回一字符串,包含 number 以 tobase 进制的表示。number 本身的进制由 frombase 指定。frombase 和 tobase 都只能在 2 和 36 之间(包括 2 和 36)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。

      MySQL的进制转换函数还有一个,是一个为16进制而定义的函数:

      HEX(N_or_S)

      如果N_OR_S 是一个数字,则返回一个 十六进制值 N 的字符串表示,在这里,   N 是一个longlong (BIGINT)数。这相当于 CONV(N,10,16)。

      如果N_OR_S 是一个字符串,则返回值为一个N_OR_S的十六进制字符串表示, 其中每个N_OR_S 里的每个字符被转化为两个十六进制数字。

以下是代码片段:

mysql> SELECT HEX(255);
        -> 'FF'
mysql> SELECT 0x616263;
        -> 'abc'
mysql> SELECT HEX('abc');
        -> 616263

      4:字符查找定位函数

      ELT(N,str1,str2,str3,...)

      若N = 1,则返回值为  str1 ,若N = 2,则返回值为 str2 ,以此类推。   若N 小于1或大于参数的数目,则返回值为 NULL 。 ELT() 是  FIELD()的补数。

以下是代码片段:

mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
        -> 'ej'
mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
        -> 'foo'

      看见上面这个函数,还以为主要起逻辑判断用的,如:

以下是代码片段:

mysql> SELECT ELT(if(1, 2, 3), 'ej', 'Heja', 'hej', 'foo');      
+----------------------------------------------+
| ELT(if(1, 2, 3), 'ej', 'Heja', 'hej', 'foo') |
+----------------------------------------------+
| Heja                                         |
+----------------------------------------------+
1 row in set (0.00 sec)

      但是一看下面的函数,才明白不仅仅如此:

      FIELD(str,str1,str2,str3,...)

      返回值为str1, str2, str3,……列表中的str 指数。在找不到str 的情况下,返回值为 0 。

      如果所有对于FIELD() 的参数均为字符串,则所有参数均按照字符串进行比较。如果所有的参数均为数字,则按照数字进行比较。否则,参数按照双倍进行比较。

      如果str 为NULL,则返回值为0 ,原因是NULL不能同任何值进行同等比较。FIELD() 是ELT()的补数。

以下是代码片段:

mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 2
mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 0

      这个函数与php中的array_search和array_key_exists、in_array、isset还是有相似作用的。

      再看一下下面这个,不禁拍案叫绝了,直接就是in子句了:

      FIND_IN_SET(str,strlist)

      假如字符串str 在由N 子链组成的字符串列表strlist 中, 则返回值的范围在 1 到 N 之间 。一个字符串列表就是一个由一些被‘,’符号分开的自链组成的字符串。如果第一个参数是一个常数字符串,而第二个是type SET列,则   FIND_IN_SET() 函数被优化,使用比特计算。如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。 这个函数在第一个参数包含一个逗号(‘,’)时将无法正常运行。 

以下是代码片段:

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2

      5:数字格式化函数

      FORMAT(X,D)

      将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。

以下是代码片段:

mysql> SELECT FORMAT(12332.123456, 4);
        -> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
        -> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
        -> '12,332'

      php中类似的函数是:number_format

展开全文  
收起全文  
MySQL的timestamp类型自动更新问题 (MySQL学习)
发布于 2008-09-12 20:23 1 阅读:78,122 评论:1 标签: MySQL timestamp

    注:本文讨论的范围为未启用MAXDB模式的表!

    今天建了一个表,里面有一个列是timestamp类型,我本意是在数据更新时,这个字段的时间能自动更新。岂知对这个类型的值还不甚了解,导致出错。发现这个字段只是在这行数据建立的时候有值,在更新的却无变化。

    查找资料,发现是我建表的语句有问题:

以下是代码片段:

CREATE TABLE `test` (
  `t1` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `ww` varchar(5) NOT NULL
) ENGINE=MyISAM ;

    而实际上,以下两个建表语句的效果是一样的:

以下是代码片段:

CREATE TABLE `test` (
`t1` TIMESTAMP NOT NULL ,
`ww` VARCHAR( 5 ) NOT NULL
) ENGINE = MYISAM

CREATE TABLE `test` (
  `t1` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `ww` varchar(5) NOT NULL
) ENGINE=MyISAM ;

    比较之下,我的语句少了“on update CURRENT_TIMESTAMP”或多了“default CURRENT_TIMESTAMP”。如此一来,这个timestamp字段只是在数据insert的时间建立时间,而update时就不会有变化了。当然,如果你就是想达到这个目的倒也无所谓。

    查找英文手册(http://dev.mysql.com/doc/refman/5.1/en/timestamp.html),得到更详细的解说,翻译如下:

-----------------------------------翻译开始--------------------------------

    在CREATE TABLE语句中,第1个TIMESTAMP列可以用下面的任何一种方式声明:

    1: 如果定义时DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句都有,列值为默认使用当前的时间戳,并且自动更新。

    2: 如果不使用DEFAULT或ON UPDATE子句,那么它等同于DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。

    3: 如果只有DEFAULT CURRENT_TIMESTAMP子句,而没有ON UPDATE子句,列值默认为当前时间戳但不自动更新。

    4: 如果没用DEFAULT子句,但有ON UPDATE CURRENT_TIMESTAMP子句,列默认为0并自动更新。

    5: 如果有一个常量值DEFAULT,该列会有一个默认值,而且不会自动初始化为当前时间戳。如果该列还有一个ON UPDATE CURRENT_TIMESTAMP子句,这个时间戳会自动更新,否则该列有一个默认的常量但不会自动更新。

    换句话说,你可以使用当前的时间戳去初始化值和自动更新,或者是其中之一,也可以都不是。(比如,你在定义的时候可以指定自动更新,但并不初始化。)下面的字段定义说明了这些情况:

以下是代码片段:

自动初始化和更新:
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

只自动初始化:
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP

只自动更新
ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP

只是给一个常量(注:0000-00-00 00:00:00)
ts TIMESTAMP DEFAULT 0

-----------------------------------翻译结束--------------------------------

    上面我用红色字体标出了"第1个TIMESTAMP列",这是因为,一个表有多个timestamp列的话,定义起来是不一样的。

    比如上面的第二条:“如果不使用DEFAULT或ON UPDATE子句,那么它等同于DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。”如果是第二个timestamp列就不一样了,请看:

以下是代码片段:

CREATE TABLE `test` (
`ww` VARCHAR( 9 ) NOT NULL ,
`t1` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`t2` TIMESTAMP NOT NULL
) ENGINE = MYISAM

    这个情况下,数据插入时,t1会记录当前时间,t2为默认值(0000-00-00 00:00:00),等同下面的语句:

以下是代码片段:

CREATE TABLE  `test` (
`ww` VARCHAR( 9 ) NOT NULL ,
`t1` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`t2` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE = MYISAM

    而根据上面的第二条,应该是:

以下是代码片段:

CREATE TABLE `test` (
`ww` VARCHAR( 9 ) NOT NULL ,
`t1` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`t2` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE = MYISAM

    但实际上,上面的语句是个语法错误,mysql会返回:

以下是引用片段:

#1293 - Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    我曾经想这样设计一个表,这个表有两个timestamp列,一个可以记录更新时间,一个可以记录初始时间,但是尝试多次以后,我发现mysql好像做不到这一点,不知道这个是mysql的缺陷还是自我优化,因为,这个功能可以使用datetime实现记录初始化的时间,只是需要insert的时候指定一下。

    顺便说一下,官网上的MySQL中文手册好难看懂,翻译得太粗糙了。等偶过几天有空,把这一节翻译一下。

展开全文  
收起全文  
条件查询索引是相当有必要的 (MySQL学习)
发布于 2008-08-26 17:41 阅读:20,660 评论:0 标签: mysql 索引

    记得一年半前去面试的时候,题目上有问如何优化题目上的数据库,大脑搜索不出任何东西。后来提示可以加索引,才恍然大悟。再过不久,立马为自己的无知而羞愧。

    前几天处理一个旧的程序,发现数据库给出的结果特别慢,查了一下表也不过30万左右数据量。一看数据结构,发现where子句中的字段没有索引,嘿嘿,立马解脱了......

以下是代码片段:

mysql> select count(*) from appeal ;
+----------+
| count(*) |
+----------+
|   317656 |
+----------+
1 row in set (0.00 sec)

mysql> alter table appeal add index (A_Flag);
Query OK, 317656 rows affected (7.95 sec)
Records: 317656  Duplicates: 0  Warnings: 0

    给现有的数据加索引的速度还是可以接受的,这个字段存储的值也就是个个位数的数字,类型是char(2),31万数据花了7.95秒。

展开全文  
收起全文  
MySQL控制流程函数学习 (MySQL学习)
发布于 2008-08-21 00:09 阅读:23,889 评论:0 标签: MySQL 流程

    文章内容大量引用手册《12.2. 控制流程函数》。

    坦率的说,我甚至怀疑我即使精通这一节又有什么用?!在sql语句里面使用这个东西的话,貌似这个需求也太复杂了!

    废话不说,学习一下我不知道,甚至闻所未闻的语句:

    1:类似PHP中的switch(){case : ...}语句

    CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END

    CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END

    在第一个方案的返回结果中, value=compare-value。而第二个方案的返回结果是第一种情况的真实结果。如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE 部分,则返回值为 NULL。

    基本上可以认为是编程语言switch结构一个变体,然后又衍生出又一个变体。前者根据判断给定的值来确定流程走向,后者没有给定的值,而是根据不同的条件来确定流程。

    可以看看手册给出的例子:

   

以下是代码片段:

mysql> SELECT CASE 1 WHEN 1 THEN 'one'
        -> WHEN 2 THEN 'two' ELSE 'more' END;
        -> 'one'

mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;
        -> 'true'

mysql> SELECT CASE BINARY 'B'
        -> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;
        -> NULL

    2:类似PHP的三元表达式

    IF(expr1,expr2,expr3)

    如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。

    我们熟悉的三元表达式到mysql中就成这个小样了,原谅它吧,毕竟数据库的根本还是存储数据的。让我们瞧瞧它的小样:

以下是代码片段:

mysql> SELECT IF(1>2,2,3);
        -> 3

mysql> SELECT IF(1<2,'yes ','no');
        -> 'yes'

mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
        -> 'no'

    关于这个类三元表达式的返回值是个有趣的话题:

    “如果expr2 或expr3中只有一个明确是 NULL,则IF() 函数的结果类型为非NULL表达式的结果类型。”这句话不太好懂。 来看看下面这句:

    “expr1 作为一个整数值进行计算,就是说,假如你正在验证浮点值或字符串值, 那么应该使用比较运算进行检验。 ”还是看看例子比较好理解:

以下是代码片段:

mysql> SELECT IF(0.1,1,0);
        -> 0

mysql> SELECT IF(0.1<>0,1,0);
        -> 1

    在所示的第一个例子中,IF(0.1)的返回值为0,原因是 0.1 被转化为整数值,从而引起一个对 IF(0)的检验。这或许不是你想要的情况。在第二个例子中,比较检验了原始浮点值,目的是为了了解是否其为非零值。比较结果使用整数。 又是一个数学上的应用,如果你的数据库是和电子商城相关的,可就要注意了!

    IF() (这一点在其被储存到临时表时很重要 ) 的默认返回值类型按照以下方式计算:

以下是引用片段:

表达式

返回值

expr2 expr3 返回值为一个字符串。

字符串

expr2 expr3 返回值为一个浮点值。

浮点

expr2 expr3 返回值为一个整数。 

整数

    另外:“假如expr2 和expr3 都是字符串,且其中任何一个字符串区分大小写,则返回结果是区分大小写。”

    三元表达式在mysql里面会继续演变:

    3:IFNULL(expr1,expr2)

    假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 否则其返回值为 expr2。IFNULL()的返回值是数字或是字符串,具体情况取决于其所使用的语境。

    如此看来又是三元表达式的变体了,只不过把三元剪成了二元的。可以理解为第一元同时又作为了第三元。

以下是代码片段:

mysql> SELECT IFNULL(1,0);
        -> 1

mysql> SELECT IFNULL(NULL,10);
        -> 10

mysql> SELECT IFNULL(1/0,10);
        -> 10

mysql> SELECT IFNULL(1/0,'yes');
        -> 'yes'

    同样 有返回值类型的问题:

    ULL(expr1,expr2)的默认结果值为两个表达式中更加“通用”的一个,顺序为STRING、 REAL或 INTEGER。假设一个基于表达式的表的情况,  或MySQL必须在内存储器中储存一个临时表中IFNULL()的返回值:

以下是代码片段:

CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;

    在这个例子中,测试列的类型为 CHAR(4)。

    4:NULLIF(expr1,expr2)

     看见了么,NULLIF和上面的IFNULL是孪生兄弟呢。

     如果expr1 = expr2  成立,那么返回值为NULL,否则返回值为 expr1。这和CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END相同。  

以下是代码片段:

mysql> SELECT NULLIF(1,1);
        -> NULL

mysql> SELECT NULLIF(1,2);
        -> 1

    “注意,如果参数不相等,则 MySQL 两次求得的值为  expr1 。”这句话看得不明白。

    感觉这就乱了,说不定是mysql的开发者为了某个特定的需求胡乱想了一个出来!

    如果用三元表达式来套,就是NULLIF 为 NULL IF :

   

以下是代码片段:

if(exp1 == exp2)

    NULL ;//IF前面的NULL

else

    exp1;

展开全文  
收起全文  
MySQL操作符学习笔记 (MySQL学习)
发布于 2008-08-15 00:06 1 阅读:44,480 评论:1 标签: MySQL 操作符

    发现许多mysql的基础知识掌握不是很牢固,手头一本《SQL必知必会》,就参照它,另外再自己做一些扩展学习吧。

    以下基本来源手册:第12章:函数和操作符。作为笔记而记录吧。

==========================================================

    除非在文档编制中对一个函数或操作符另有指定的情况外,一个包含NULL 的表达式通常产生一个NULL 值。

    在默认状态下, 在函数和紧随其后的括号之间不得存在空格。这能帮助  MySQL 分析程序区分一些同函数名相同的函数调用以及表或列。不过,函数自变量周围允许有空格出现。

    可以通过选择--sql-mode=IGNORE_SPACE来打开MySQL服务器的方法使服务器接受函数名后的空格。 个人客户端程序可通过选择mysql_real_connect()的CLIENT_IGNORE_SPACE 实现这一状态。在以上两种情况中, 所有的函数名都成为保留字。请参见5.3.2节,“SQL服务器模式”. 

    MySQL按照以下规则进行数值比较

以下是引用片段:
若有一个或两个参数为 NULL,除非NULL-safe <=> 等算符,则比较运算的结果为NULL。

若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较。

若两个参数均为整数,则按照整数进行比较。 

十六进制值在不需要作为数字进行比较时,则按照二进制字符串进行处理。

假如参数中的一个为 TIMESTAMP 或 DATETIME 列,而其它参数均为常数, 则在进行比较前将常数转为 timestamp。这样做的目的是为了使ODBC的进行更加顺利。 注意,这不适合IN()中的参数!为了更加可靠,在进行对比时通常使用完整的 datetime/date/time字符串。

在其它情况下,参数作为浮点数进行比较。  

在默认状态下,字符串比较不区分大小写,并使用现有字符集(默认为cp1252 Latin1,同时对英语也适合)。

为了进行比较,可使用CAST()函数将某个值转为另外一种类型。 使用CONVERT()将字符串值转为不同的字符集

    注意,在将一个字符串列同一个数字进行比较时, MySQL 不能使用列中的索引进行快速查找。假如str_col 是一个编入索引的字符串列,则在以下语句中,索引不能执行查找功能:

以下是代码片段:
SELECT * FROM tbl_name WHERE str_col=1;

    其原因是许多不同的字符串都可被转换为数值 1: '1'、 ' 1'、 '1a'、 ……

    以下记录一些我没见过或不熟悉的操作符:

    IS boolean_value IS NOT boolean_value

    根据一个布尔值来检验一个值,在这里,布尔值可以是TRUE、FALSE或UNKNOWN。

以下是代码片段:
mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;
        -> 1, 1, 1
mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;
        -> 1, 1, 0

    IS NULL IS NOT NULL

    检验一个值是否为 NULL。

以下是代码片段:
mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
        -> 0, 0, 1
mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
        -> 1, 1, 0

    为了能够顺利的使用ODBC 程序工作,在使用IS NULL时,MySQL支持一下额外特性:

    在一个值产生后,立即运行一个以下格式的语句,从而找到最新AUTO_INCREMENT 值的所在行:

以下是代码片段:
SELECT * FROM tbl_name WHERE auto_col IS NULL


    当设置SQL_AUTO_IS_NULL=0时,这项操作无法运行。请参见13.5.3节,“SET语法”。

   对于命名为NOT NULL 的DATE 和DATETIME列,可通过使用如下的 语句找到特定日期 '0000-00-00':

以下是代码片段:
SELECT * FROM tbl_name WHERE date_column IS NULL

    运行这一步需要使用一些 ODBC 应用软件,因为 ODBC本身不支持 一个 '0000-00-00'的时间值。 

    expr BETWEEN min AND max

    假如expr大于或等于 min 且expr 小于或等于max, 则BETWEEN 的返回值为1,或是0。若所有参数都是同一类型,则上述关系相当于表达式   (min <= expr AND expr <= max)。其它类型的转换根据本章开篇所述规律进行,且适用于3种参数中任意一种。 

以下是代码片段:
mysql> SELECT 1 BETWEEN 2 AND 3;
        -> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
        -> 0


    expr NOT BETWEEN min AND max

    这相当于NOT(expr BETWEEN min AND max)。

    COALESCE(value,...)

    返回值为列表当中的第一个非 NULL值,在没有非NULL 值得情况下返回值为 NULL 。

以下是代码片段:
mysql> SELECT COALESCE(NULL,1);
        -> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
        -> NULL

    GREATEST(value1,value2,...)

    当有2或多个参数时,返回值为最大(最大值的)参数。比较参数所依据的规律同LEAST()相同。

以下是代码片段:
mysql> SELECT GREATEST(2,0);
        -> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
        -> 767.0
mysql> SELECT GREATEST('B','A','C');
        -> 'C'


    在没有自变量为NULL的情况下,GREATEST()的返回值为NULL。

    ISNULL(expr)

    如expr 为NULL,那么ISNULL() 的返回值为 1,否则返回值为 0。

以下是代码片段:
mysql> SELECT ISNULL(1+1);
        -> 0
mysql> SELECT ISNULL(1/0);
        -> 1


    使用= 的NULL 值对比通常是错误的。

    ISNULL() 函数同 IS NULL比较操作符具有一些相同的特性。请参见有关IS NULL 的说明。

    INTERVAL(N,N1,N2,N3,...)

    假如N < N1,则返回值为0;假如N < N2 等等,则返回值为1;假如N 为NULL,则返回值为 -1 。所有的参数均按照整数处理。为了这个函数的正确运行,必须满足 N1 < N2 < N3 < ……< Nn 。其原因是使用了二分查找(极快速)。

以下是代码片段:
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
        -> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
        -> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
        -> 0

    LEAST(value1,value2,...)

    在有两个或多个参数的情况下, 返回值为最小 (最小值) 参数。用一下规则将自变量进行对比:
假如返回值被用在一个 INTEGER 语境中,或是所有参数均为整数值,则将其作为整数值进行比较。

    假如返回值被用在一个 REAL语境中,或所有参数均为实值,则 将其作为实值进行比较。
假如任意一个参数是一个区分大小写的字符串,则将参数按照区分大小写的字符串进行比较。
在其它情况下,将参数作为区分大小写的字符串进行比较。

    假如任意一个自变量为NULL,则 LEAST()的返回值为NULL 。

以下是代码片段:
mysql> SELECT LEAST(2,0);
        -> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
        -> 3.0
mysql> SELECT LEAST('B','A','C');
        -> 'A'

    注意,上面的转换规则在一些边界情形中会产生一些奇特的结果:  

以下是代码片段:
mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED);
        -> -9223372036854775808

    发生这种情况的原因是MySQL在整数语境中读取9223372036854775808.0。整数表示法不利于保存数值,因此它包括一个带符号整数。

展开全文  
收起全文  
PHP和MySQL的删除空白函数 (MySQL学习)
发布于 2008-08-05 10:41 阅读:25,102 评论:0 标签: MySQL PHP trim

    作为黄金搭档,PHP和MySQL都有自己的删除空白函数,而且函数名字也一样:trim(), ltrim(), rtrim()。当然,作为编程语言,PHP删除空白函数更为强大。

    对 ltrim()和rtrim(),从其英语解释来看:

以下是引用片段:
PHP为:Strip whitespace (or other characters)
MySQL为:space characters removed

    显然,PHP还可以有“other characters”,而且PHP的函数还可以用第二个参数自定义要删除的字符。

    对“other characters”,手册解释为:

以下是引用片段:
  • " " (ASCII 32 (0x20)), an ordinary space.
  • "\t" (ASCII 9 (0x09)), a tab.
  • "\n" (ASCII 10 (0x0A)), a new line (line feed).
  • "\r" (ASCII 13 (0x0D)), a carriage return.
  • "\0" (ASCII 0 (0x00)), the NUL-byte.
  • "\x0B" (ASCII 11 (0x0B)), a vertical tab.
  •     不过,MySQL的trim()函数也增加了对其他字符的删除。具体请见下面从手册上摘抄的解释。

    = = = = = = = = = = = = = 方便阅读的分隔线  = = = = = = = = = = = = = = = =

        以下为MySQL的函数解释

        LTRIM(str) 

        Returns the string str with leading space characters removed.

    以下是代码片段:
    mysql> SELECT LTRIM('  barbar');
            -> 'barbar'


        This function is multi-byte safe.

        RTRIM(str)

        Returns the string str with trailing space characters removed.

    以下是代码片段:
    mysql> SELECT RTRIM('barbar   ');
            -> 'barbar'

        This function is multi-byte safe.

        TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr FROM] str)

        Returns the string str with all remstr prefixes or suffixes removed. If none of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is assumed. remstr is optional and, if not specified, spaces are removed.

    以下是代码片段:
    mysql> SELECT TRIM('  bar   ');
            -> 'bar'
    mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
            -> 'barxxx'
    mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
            -> 'bar'
    mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
            -> 'barx'

        This function is multi-byte safe.

        参考:
        php手册
        mysql中英文手册:
        http://dev.mysql.com/doc/refman/5.1/zh/functions.html
        http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_trim

    展开全文  
    收起全文  
    MySQL主从同步关键句 (MySQL学习)
    发布于 2008-08-04 16:31 阅读:35,420 评论:0 标签: MySQL 主从同步

        MySQL中文手册把mysql主从同步称为“复制”,感觉翻译的很不好。中文手册主从同步地址是:http://dev.mysql.com/doc/refman/5.1/zh/replication.html

        看资料离不开手册,但每次看手册也很繁琐,现把我认为的一些关键的地方整理出来,方便你我他她。

        一:主从同步原理关键句

        主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。

        MySQL复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新、删除等等)。因此,要进行复制,必须在主服务器上启用二进制日志。

        每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以便从服务器可以对其数据拷贝执行相同的更新。

        从服务器设置为复制主服务器的数据后,它连接主服务器并等待更新过程。如果主服务器失败,或者从服务器失去与主服务器之间的连接,从服务器保持定期尝试连接,直到它能够继续帧听更新。由--master-connect-retry选项控制重试间隔。 默认为60秒。

        每个从服务器跟踪复制时间。主服务器不知道有多少个从服务器或在某一时刻有哪些被更新了。

        二:主从同步的过程

        MySQL使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线程将二进制日志中的内容发送到从服务器。该线程可以识别为主服务器上SHOW PROCESSLIST的输出中的Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,是从服务器创建用于读取中继日志并执行日志中包含的更新。

        在前面的描述中,每个从服务器有3个线程(应该是每对主从)。有多个从服务器的主服务器创建为每个当前连接的从服务器创建一个线程;每个从服务器有自己的I/O和SQL线程。

        三:主从同步过程的相关文件

        默认情况,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪索引文件中目前正使用的中继日志。 默认中继日志索引文件名为host_name-relay-bin.index。默认情况,在从服务器的数据目录中创建这些文件。可以用--relay-log和--relay-log-index服务器选项覆盖 默认文件名

        中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并且不再需要之后,立即自动删除它。没有直接的删除中继日志的机制,因为SQL线程可以负责完成。然而,FLUSH LOGS可以循环中继日志,当SQL线程删除日志时会有影响。

        从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。它们包含SHOW SLAVE STATUS语句的输出所显示的信息(关于该语句的描述参见13.6.2节,“用于控制从服务器的SQL语句”)。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。

        四:主从同步过程的相关文件和MySQL语句的关系

        由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:

    以下是引用片段:
    行 描述
    1 文件中的行号
    2 Master_Log_File
    3 Read_Master_Log_Pos
    4 Master_Host
    5 Master_User
    6 密码(不由SHOW SLAVE STATUS显示)
    7 Master_Port
    8 Connect_Retry
    9 Master_SSL_Allowed
    10 Master_SSL_CA_File
    11 Master_SSL_CA_Path
    12 Master_SSL_Cert
    13 Master_SSL_Cipher
    14 Master_SSL_Key

     
        由SQL线程更新relay-log.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
    以下是引用片段:
    行 描述
    1 Relay_Log_File
    2 Relay_Log_Pos
    3 Relay_Master_Log_File
    4 Exec_Master_Log_Pos

     
        当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继续进行复制。如果丢失了中继日志但仍然有relay-log.info文件,你可以通过检查该文件来确定SQL线程已经执行的主服务器中二进制日志的程度。然后可以用Master_Log_File和Master_LOG_POS选项执行CHANGE MASTER TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。

        如果从服务器正复制LOAD DATA INFILE语句,你应也备份该目录内从服务器用于该目的的任何SQL_LOAD-*文件。从服务器需要这些文件继续复制任何中断的LOAD DATA INFILE操作。用--slave-load-tmpdir选项来指定目录的位置。如果未指定, 默认值为tmpdir变量的值。

        五:主从同步起点的说明

        master.info的内容会覆盖命令行或in my.cnf中指定的部分选项。

        如果从服务器启动时master.info文件不存在,选项采用选项文件或命令行中指定的值。首次将服务器作为从服务器启动时,或者已经运行RESET SLAVE然后已经关闭并重启从服务器时会发生。

        如果从服务器启动时master.info文件存在,服务器忽略那些选项。使用master.info文件中发现的值。

        如果你使用与master.info文件中相对应的启动选项的不同的值重启从服务器,启动选项的不同的值不会生效,因为服务器继续使用master.info文件。要想使用启动选项的不同的值,必须删除master.info文件并重启从服务器,或(最好是)在从服务器运行时使用CHANGE MASTER TO语句重新设置值。

        六:如何确保所有从服务器已经处理了中继日志中的所有语句

        在每个从服务器上,发出STOP SLAVE IO_THREAD语句,然后检查SHOW PROCESSLIST语句的输出,直到你看到Has read all relay log。当所有从服务器都执行完这些,它们可以被重新配置为一个新的设置。在被提升为主服务器的从服务器S1上,发出STOP SLAVE和RESET MASTER语句。

        七:如果你确定可以跳过来自主服务器的下一个语句,可以执行下面的语句

    以下是代码片段:
    mysql> SET GLOBAL SQL_slave_SKIP_COUNTER = n;
    mysql> START SLAVE;

        如果来自主服务器的下一个语句不使用AUTO_INCREMENT或LAST_INSERT_ID(),n 值应为1。否则,值应为2。使用AUTO_INCREMENT或LAST_INSERT_ID()的语句使用值2的原因是它们从主服务器的二进制日志中取两个事件。

        七:两个重要的选项:

        1):・ --logs-slave-updates

        这个是在my.cnf文件配置的

        通常情况,从服务器从主服务器接收到的更新不记入它的二进制日志。该选项告诉从服务器将其SQL线程执行的更新记入到从服务器自己的二进制日志。为了使该选项生效,还必须用--logs-bin选项启动从服务器以启用二进制日志。如果想要应用链式复制服务器,应使用--logs-slave-updates。例如,可能你想要这样设置:

         A -> B -> C

        也就是说,A为从服务器B的主服务器,B为从服务器C的主服务器。为了能工作,B必须既为主服务器又为从服务器。你必须用--logs-bin启动A和B以启用二进制日志,并且用--logs-slave-updates选项启动B。

        2):・ --slave-skip-errors=[err_code1,err_code2,... | all]

        这个是在mysql启动时的选项

        通常情况,当出现错误时复制停止,这样给你一个机会手动解决数据中的不一致性问题。该选项告诉从服务器SQL线程当语句返回任何选项值中所列的错误时继续复制。

        如果你不能完全理解为什么发生错误,则不要使用该选项。如果复制设置和客户程序中没有bug,并且MySQL自身也没有bug,应不会发生停止复制的错误。滥用该选项会使从服务器与主服务器不能保存同步,并且你找不到原因。

        对于错误代码,你应使用从服务器错误日志中错误消息提供的编号和SHOW SLAVE STATUS的输出。服务器错误代码列于附录B:错误代码和消息。

        你也可以(但不应)使用不推荐的all值忽略所有错误消息,不考虑所发生的错误。无需而言,如果使用该值,我们不能保证数据的完整性。在这种情况下,如果从服务器的数据与主服务器上的不相近请不要抱怨(或编写bug报告)。已经警告你了。

        例如:

    以下是代码片段:
    --slave-skip-errors=1062,1053
    --slave-skip-errors=all

        八:二个有用的问与答:

        1)Q:如果主服务器正在运行并且不想停止主服务器,怎样配置一个从服务器?
             A:有多种方法。如果你在某时间点做过主服务器备份并且记录了相应快照的二进制日志名和偏移量(通过SHOW MASTER STATUS命令的输出),采用下面的步骤:

    以下是引用片段:
        1.    确保从服务器分配了一个唯一的服务器ID号。
        2.    在从服务器上执行下面的语句,为每个选项填入适当的值:
                mysql> CHANGE MASTER TO
                        ->     MASTER_HOST='master_host_name',
                        ->     MASTER_USER='master_user_name',
                        ->     MASTER_PASSWORD='master_pass',
                        ->     MASTER_LOG_FILE='recorded_log_file_name',
                        ->     MASTER_LOG_POS=recorded_log_position;
        3.    在从服务器上执行START SLAVE语句。

        如果你没有备份主服务器,这里是一个创建备份的快速程序。所有步骤都应该在主服务器主机上执行。

    以下是引用片段:
    1.    发出该语句:
         mysql> FLUSH TABLES WITH READ LOCK;
    2.    仍然加锁时,执行该命令(或它的变体):
         shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
    3.    发出该语句并且确保记录了以后用到的输出:
         mysql>SHOW MASTER STATUS;
    4.    释放锁:
         mysql> UNLOCK TABLES;

        一个可选择的方法是,转储主服务器的SQL来代替前面步骤中的二进制复制。要这样做,你可以在主服务器上使用mysqldump --master-data,以后装载SQL转储到到你的从服务器。然而,这比进行二进制复制速度慢。

        不管你使用这两种方法中的那一个,当你有一个快照和记录了日志名与偏移量时,后来根据说明操作。你可以使用相同的快照建立多个从服务器。一旦你拥有主服务器的一个快照,可以等待创建一个从服务器,只要主服务器的二进制日志完整。两个能够等待的时间实际的限制是指在主服务器上保存二进制日志的可用硬盘空间和从服务器同步所用的时间。

        你也可以使用LOAD DATA FROM MASTER。这是一个方便的语句,它传输一个快照到从服务器并且立即调整日志名和偏移量。将来,LOAD DATA FROM MASTER将成为创建从服务器的推荐方法。然而需要注意,它只工作在MyISAM 表上并且可能长时间持有读锁定。它并不象我们希望的那样高效率地执行。如果你有大表,执行FLUSH TABLES WITH READ LOCK语句后,这时首选方法仍然是在主服务器上制作二进制快照。

        2)Q:从服务器需要始终连接到主服务器吗?
             A:不,不需要。从服务器可以宕机或断开连接几个小时甚至几天,重新连接后获得更新信息。例如,你可以在通过拨号的链接上设置主服务器/从服务器关系,其中只是偶尔短时间内进行连接。这意味着,在任何给定时间,从服务器不能保证与主服务器同步除非你执行某些特殊的方法。将来,我们将使用选项来阻塞主服务器直到有一个从服务器同步。

    展开全文  
    收起全文  
    MySQL server has gone away问题及其解决 (MySQL学习)
    发布于 2008-06-16 20:06 1 阅读:27,734 评论:1 标签: away MySQL

        初看这个提示,你可能会发笑,这个mysql的提示真是人性化呢。很快你就会笑不出来了,因为,问题是需要用来解决的。

        看上去,应该是两次mysql操作之间的时间太长了,导致mysql连接自动关闭了。可是根据经验,对同一批数据,此前程序也这么写过,两次操作的时间也同样很长。更何况,同事也同时在操作这个库,间隔的时间比我的更长。

        看了mysql服务器端的wait_timeout和max_allowed_packet的值,绝对的长和大!如下:

    以下是代码片段:
    mysql> show variables like 'wait_timeout';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | wait_timeout  | 28800 |
    +---------------+-------+
    1 row in set (0.00 sec)

    mysql> show variables like 'max_allowed_packet';
    +--------------------+---------+
    | Variable_name      | Value   |
    +--------------------+---------+
    | max_allowed_packet | 1048576 |
    +--------------------+---------+
    1 row in set (0.00 sec)

       看着这些数据,感觉可以判断出服务器端应该是没有问题的,但是总得用实验说话,编写如下程序:

    以下是代码片段:
    $link = mysql_connect('...', '...', '...');
    mysql_select_db("...", $link);

    echo "Start !\n";

    sleep(30);

    echo "End !\n";

    mysql_close($link);
    ?>

        执行之后,到mysql服务器端show processlist;发现一超过20秒,就没有其连接了。然而再到另一台服务器上执行,却无此问题。top命令了一下,发现两台服务器的空闲内存的确差异很大。而上面又说明了,同事和我在同一服务器上对这个库进行操作却无此问题,真令人诧异。

        而后又发现,我程序有个bug,有一数字变量本意是存储sql语句的记录,然而并没有考虑这个数组在执行时间好几个小时之后的大小会成为天文数字。莫非这个地方有问题?

       既然暂时可以排除服务器的问题,只好从我的程序入手了。

       mysql_ping()是个好东西,但用得也不是很爽。手册中“If it has gone down, an automatic reconnection is attempted. ”。但是,发现它并没有automatic reconnection。

       于是只好,先判断mysql_ping()的返回值,如果false,则mysql_close()本次连接,然后mysql_connect()。

        如果是在类里面实现的话,建议加上mysql_connect()第四的参数为true。这样在实例化的时候避免资源符号只有一个。

        参考资料:

    以下是引用片段:
    MySQL: 诡异的MySQL server has gone away及其解决
    http://www.jimmydong.com/blog/post/1/123

    MySQL server has gone away
    http://hi.baidu.com/thinkinginlamp/blog/item/8512ad4b6f2e96f482025cf7.html

    B.1.2.9. MySQL server has gone away
    http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

    MySQL server has gone away 解决办法
    http://yytcpt.blueidea.com/archives/2007/4280.shtml

    mysql_ping
    http://cn2.php.net/mysql_ping

    展开全文  
    收起全文  
    查看mysql版本的四种方法 (MySQL学习)
    发布于 2008-01-22 15:54 4 阅读:189,738 评论:4 标签: mysql 版本 方法
        1:在终端下:mysql -V。

    以下是代码片段:

    [shengting@login ~]$ mysql -V
    mysql  Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

        2:在mysql中:mysql> status;

    以下是代码片段:

    mysql> status;
    --------------
    mysql  Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

    Connection id:          416
    SSL:                    Not in use
    Current pager:          stdout
    Using outfile:          ''
    Using delimiter:        ;
    Server version:         3.23.56-log
    Protocol version:       10
    Connection:             Localhost via UNIX socket
    Client characterset:    latin1
    Server characterset:    latin1
    UNIX socket:            /tmp/mysql_3311.sock
    Uptime:                 62 days 21 hours 21 min 57 sec

    Threads: 1  Questions: 584402560  Slow queries: 424  Opens: 59664208  Flush tables: 1  Open tables: 64 Queries per second avg: 107.551

        3:在help里面查找

    以下是代码片段:

    [shengting@login ~]$ mysql --help | grep Distrib
    mysql  Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

        4:使用mysql的函数

    以下是代码片段:

    mysql> select version();
    +-------------+
    | version()   |
    +-------------+
    | 3.23.56-log |
    +-------------+
    1 row in set (0.00 sec)

     

    展开全文  
    收起全文