• 1. 外键总结:(上面例证的前提外键是默认的约束类型restrict(no action) ) 不能删除/更新主键关联列,插入操作随意; 不能更新子表外键关联字段,不可插入非外键关联字段,删除操作随意。更新父表非主键关联字段删除/更新父表主键关联字段删除子表任意字段插入子表非外键关联字段插入子表外键关联字段插入父表任意字段还要注意:当两个表主外键列间不满足数据 一致完整性时,建立外键连接会报错。添加外键:alter table infos add constraint fk_inf_stu foreign key(Name) references students(Name); 建表时添加外键:create table infos(Name char(10) references students(Name) , …)
  • 2. 在给表定义触发器时,一定要注意外键约束。 要想可删除父表关联列字段,可设置on delete set null,不过之后外键连接自动断开了。添加外键的格式: ALTER TABLE yourtablename ADD [CONSTRAINT 外键名] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}] [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]CASCADE:在父表上update/delete记录时,同步update/delete掉子表的匹配记录。 Set NULL:在父表上update/delete记录时,将子表上匹配记录的列设为null。 要注意子表的外键列不能为not null 。建立的主键会自动添加索引,建立外键后也给外键列添加了索引。删除/更新时的自动触发动作是单独设置的, 指的是当父表删除、更新时外键表的动作。现若设置为“SET NULL”,报错!create index语句用于在表中创建索引,索引 使数据库应用程序可以更快地查找数据。用户 无法看到索引,它们只能被用来加速搜索/查询。 语法:create index index_name on table_name(col_name); 由于在更新表时索引也被更新,故更新速度会慢些,理想的 做法是仅仅在常常被搜索的列(以及表)上面创建索引。create trigger newpruduct after insert on products for each row select ‘Product added’;若允许空值,则:
  • 3. CREATE TABLE `NewTable` ( `Number` int(11) NOT NULL AUTO_INCREMENT , `Name` varchar(10) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL , `activity` varchar(20) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL , `Score` int(11) NULL DEFAULT NULL , PRIMARY KEY (`Number`), FOREIGN KEY (`Name`) REFERENCES `students` (`Name`) ON DELETE RESTRICT ON UPDATE RESTRICT, INDEX `fk_inf_stu` (`Name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARACTER SET=gbk COLLATE=gbk_chinese_ci AUTO_INCREMENT=5 ROW_FORMAT=COMPACT ;
  • 4. 1.(1)CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END (2)CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END 在第一个方案的返回结果中, value=compare-value。而第二个方案的返回结果是第一种情况的真实结果。如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE 部分,则返回值为 NULL。 mysql> SELECT CASE ‘x’ WHEN ‘x’ THEN ‘x’ WHEN 2 THEN 'two' ELSE 'more' END; => ‘x' 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 一个CASE表达式的默认返回值类型是任何返回值的相容集合类型,但具体情况视其所在语境而定。如果用在字符串语境中,则返回结果为字符串。如果用在数字语境中,则返回结果为十进制值、实值或整数值。 控制流程函数
  • 5. 2.IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。 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 都是字符串,且其中任何一个字符串区分大小写,则返回结果是区分大小写。
  • 6. 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' IFNULL(expr1,expr2)的默认结果值为两个表达式中更加“通用”的一个,顺序为STRING、 REAL或 INTEGER。假设一个基于表达式的表的情况, 或MySQL必须在内存储器中储存一个临时表中IFNULL()的返回值: CREATE TABLE tmp SELECT IFNULL(1,'test') AS test; 在这个例子中,测试列的类型为 CHAR(4)。 4.NULLIF(expr1,expr2) 如果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 。
  • 7. 在MySQL存储过程的语句中有三个标准的循环方式:WHILE循环,LOOP循环以及REPEAT循环。还有一种非标准的循环方式:GOTO,不过这种循环方式最好别用,很容易引起程序的混乱,在这里就不错具体介绍了。 这几个循环语句的格式如下: WHILE……DO……END WHILE REPEAT……UNTIL END REPEAT LOOP……END LOOP GOTO。 下面首先使用第一种循环编写一个例子。 mysql> create procedure pro10() -> begin -> declare i int; -> set i=0; -> while i<5 do -> insert into t1(filed) values(i); -> set i=i+1; -> end while; -> end;// 再来看一下第二个循环控制指令 REPEAT……END REPEAT。使用REPEAT循环控制语句编写下面这个存储过程: mysql> create procedure pro11() -> begin -> declare i int default 0; -> repeat -> insert into t1(filed) values(i); -> set i=i+1; -> until i>=5 -> end repeat; -> end;//mysql存储过程中的循环语句
  • 8. 再来看一下第三个循环控制语句LOOP……END LOOP。编写一个存储过程程序如下: mysql> create procedure pro12() -> begin -> declare i int default 0; -> loop_label: loop -> insert into t1(filed) values(i); -> set i=i+1; -> if i>=5 then //条件语句if then end if -> leave loop_label; -> end if; -> end loop; -> end;// Labels 标号和 END Labels 结束标号 在使用loop的时候,使用到的labels标号,对于labels可以用到while,loop,repeat等循环控制语句中。而且有必要好好认识一下lables!! //类似于java中带标签的break、continue语句 mysql> create procedure pro13() -> label_1:begin -> label_2:while 0=1 do leave label_2;end while; -> label_3:repeat leave label_3;until 0=0 end repeat; -> label_4:loop leave label_4;end loop; -> end;// 上面这里例子显示了可以在BEGIN、WHILE、REPEAT或者LOOP语句前使用语句标号,语句标号只能在合法的语句前使用,所以LEAVE label_3意味着离开语句标号名为label_3的语句或符合语句。 其实,也可以使用END labels来表示标号结束符。 mysql> create procedure pro14() -> label_1:begin -> label_2:while 0=1 do leave label_2;end while label_2; -> label_3:repeat leave label_3;until 0=0 end repeat label_3; -> label_4:loop leave label_4;end loop label_4; -> end label_1;// 上面就是使用了标号结束符,其实这个结束标号并不是十分有用,而且他必须和开始定义的标号名字一样,否则就会报错。如果要养成一个良好的编程习惯方便他人阅读的话,可以使用这个标号结束符。while(true){(loop) … … leave …;(循环结束条件语句) }(end loop)
  • 9. ITERATE 迭代 如果是在ITERATE语句,即迭代语句中的话,就必须使用LEAVE语句。ITERATE只能出现在LOOP,REPEAT和WHILE语句中,它的意思是“再次循环”,例如: mysql> create procedure pro15() -> begin -> declare i int default 0; -> loop_label:loop -> if i=3 then -> set i=i+1; -> iterate loop_label; -> end if; -> insert into t1(filed) values(i); -> set i=i+1; -> if i>=5 then -> leave loop_label; -> end if; -> end loop; -> end;// iterate语句和leave语句一样,也是在循环内部使用,它有点类似于Java语言中的continue。 那么这个存储程序是怎么运行的的?首先i的值为0,条件判断语句if i=3 then判断为假,跳过if语段,向数据库中插入0,然后i+1,同样后面的if i>=5 then判断也为假,也跳过;继续循环,同样插入1和2;在i=3的时候条件判断语句if i=3 then判断为真,执行i=i+1,i值为4,然后执行迭代iterate loop_label;,即语句执行到iterate loop_label;后直接跳到if i=3 then判断语句,执行判断,这个时候由于i=4,if i=3 then判断为假,跳过IF语段,将4添加到表中,i变为5,条件判断if i>=5 then判断为真,执行leave loop_label;跳出loop循环,然后执行end;//,结束整个存储过程。等效于java代码: int[] t1; int i=0; loop_label: while(true){ if(i=3){(then) i=i+1; continue loop_label; }(end if) t1[i]=i; i=i+1; if(i>=5) break loop_label; }
  • 10. [begin_label:] BEGIN [statement_list]END [end_label] 存储子程序可以使用BEGIN ... END复合语句来包含多个语句。 statement_list 代表一个或多个语句的列表。statement_list之内每个语句都必须用分号(;)来结尾。 复合语句可以被标记。除非begin_label存在,否则end_label不能被给出,并且如果二者都存在,他们必须是同样的。 请注意,可选的[NOT] ATOMIC子句现在还不被支持。这意味着在指令块的开始没有交互的存储点被设置,并且在上下文中用到的BEGIN子句对当前交互动作没有影响。 使用多重语句需要客户端能发送包含语句定界符;的查询字符串。这个符号在命令行客户端被用delimiter命令来处理。改变查询结尾定界符;(比如改变为//)使得; 可被用在子程序体中。BEGIN ... END复合语句CALL sp_name([parameter[,...]]) CALL语句调用一个先前用CREATE PROCEDURE创建的程序。 CALL语句可以用声明为OUT或INOUT的参数给它的调用者传回值。它也“返回”受影响的行数,客户端程序可以在SQL级别通过调用ROW_COUNT()函数获得这个数,从C中是调用the mysql_affected_rows() C API函数来获得。CALL语句
  • 11. DECLARE语句: DECLARE语句被用来把不同项目局域到一个子程序: 局部变量、条件和处理程序及光标。(SIGNAL和RESIGNAL语句当前还不被支持) DECLARE仅被用在BEGIN ... END复合语句里,并且必须在复合语句的开头,在任何其它语句之前。 光标必须在声明处理程序之前被声明,并且变量和条件必须在声明光标或处理程序之前被声明。DECLARE局部变量DECLARE var_name[,...] type [DEFAULT value] 这个语句被用来声明局部变量。要给变量提供一个默认值,请包含一个DEFAULT子句。值可以被指定为一个表达式,不需要为一个常数。如果没有DEFAULT子句,初始值为NULL。 局部变量的作用范围在它被声明的BEGIN ... END块内。它可以被用在嵌套的块中,除了那些用相同名字声明变量的块。 DECLARE条件DECLARE condition_name CONDITION FOR condition_value 。 condition_value: SQLSTATE [VALUE] sqlstate_value|mysql_error_code 这个语句指定需要特殊处理的条件。它将一个名字和指定的错误条件关联起来。这个名字可以随后被用在DECLARE HANDLER语句中。除了SQLSTATE值,也支持MySQL错误代码。
  • 12. DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type: CONTINUE | EXIT | UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code 这个语句指定每个可以处理一个或多个条件的处理程序。如果产生一个或多个条件,指定的语句被执行。 对一个CONTINUE处理程序,当前子程序的执行在执行处理程序语句之后继续。对于EXIT处理程序,当前BEGIN...END复合语句的执行被终止。UNDO 处理程序类型语句还不被支持。 · SQLWARNING是对所有以01开头的SQLSTATE代码的速记。 · NOT FOUND是对所有以02开头的SQLSTATE代码的速记。 · SQLEXCEPTION是对所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的速记。 除了SQLSTATE值,MySQL错误代码也不被支持。DECLARE处理程序
  • 13. 例如: mysql> CREATE TABLE test.t (s1 int,primary key (s1)); Query OK, 0 rows affected (0.00 sec) mysql> delimiter // mysql> CREATE PROCEDURE handlerdemo () -> BEGIN -> DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000’ SET @x2 = 1; //’23000’:主键约束不唯一 -> SET @x = 1; -> INSERT INTO test.t VALUES (1); -> SET @x = 2; -> INSERT INTO test.t VALUES (1); //此句只是使@x2=1,此句并未执行成功,断续执行下面的语句【SQLSTATE消息大全.doc】 -> SET @x = 3; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> CALL handlerdemo()// Query OK, 0 rows affected (0.00 sec) mysql> SELECT @x// +------+ | @x | +------+ | 3 | +------+ 1 row in set (0.00 sec) 注意到,@x是3,这表明MySQL被执行到程序的末尾。如果DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; 这一行不在,第二个INSERT因PRIMARY KEY强制而失败之后,MySQL可能已经采取默认(EXIT)路径,并且SELECT @x可能已经返回2。
  • 14. SELECT col_name[,...] INTO var_name[,...] table_expr 这个SELECT语法把选定的列直接存储到变量。因此,只有单一的行可以被取回。 SELECT id,data INTO x,y FROM test.t1 LIMIT 1; 注意,用户变量名在MySQL 5.1中是对大小写不敏感的。 重要: SQL变量名不能和列名一样。如果SELECT ... INTO这样的SQL语句包含一个对列的参考,并包含一个与列相同名字的局部变量,MySQL当前把参考解释为一个变量的名字。例如,在下面的语句中,xname 被解释为到xname variable 的参考而不是到xname column的: SELECT ... INTO语句CREATE PROCEDURE sp1 (x VARCHAR(5)) BEGIN DECLARE xname VARCHAR(5) DEFAULT 'bob'; DECLARE newname VARCHAR(5); DECLARE xid INT; SELECT xname,id INTO newname,xid FROM table1 WHERE xname = xname; SELECT newname; END; 当这个程序被调用的时候,无论table.xname列的值是什么,变量newname将返回值‘bob’。SET var_name = expr [, var_name = expr] ... 在存储程序中的SET语句是一般SET语句的扩展版本。被参考变量可能是子程序内声明的变量,或者是全局服务器变量。 在存储程序中的SET语句作为预先存在的SET语法的一部分来实现。这允许SET a=x, b=y, ...这样的扩展语法。其中不同的变量类型(局域声明变量及全局和集体变量)可以被混合起来。这也允许把局部变量和一些只对系统变量有意义的选项合并起来。在那种情况下,此选项被识别,但是被忽略了。变量SET语句
  • 15. 模式匹配要想找出以“b”开头的名字: mysql> SELECT * FROM pet WHERE name LIKE 'b%'; 要想找出以“fy”结尾的名字: mysql> SELECT * FROM pet WHERE name LIKE '%fy'; 要想找出包含“w”的名字: mysql> SELECT * FROM pet WHERE name LIKE '%w%'; 要想找出正好包含5个字符的名字,使用“_”模式字符: mysql> SELECT * FROM pet WHERE name LIKE ‘_ _ _ _ _'; SQL模式匹配允许你使用“_”匹配任何单个字符,而“%”匹配任意数目字符(包括零字符)。注意使用SQL模式时,不能使用=或!=;而应使用LIKE或NOT LIKE比较操作符。
  • 16. 由MySQL提供的模式匹配的其它类型是使用扩展正则表达式。当你对这类模式进行匹配测试时,使用REGEXP和NOT REGEXP操作符。扩展正则表达式的一些字符是: · ‘.’ 匹配任何单个的字符。 · 字符类“[...]” 匹配在方括号内的任何字符。 例如,“[abc]”匹配“a”、“b”或“c”。为了命名字符的范围,使用一个“-”。“[a-z]”匹配任何字母,而“[0-9]”匹配任何数字。 · “ * ” 匹配零个或多个在它前面的字符。 例如,“x*”匹配任何数量的“x”字符,“[0-9]*”匹配任何数量的数字,而“.*”匹配任何数量的任何字符。 如果REGEXP模式与被测试值的任何地方匹配,模式就匹配(这不同于LIKE模式匹配,只有与整个值匹配,模式才匹配)。 为了定位一个模式以便它必须匹配被测试值的开始或结尾,在模式开始处使用“^”或在模式的结尾用“$”。 正则表达式为了找出以“b”开头的名字,使用“^”匹配名字的开始: mysql> SELECT * FROM pet WHERE name REGEXP '^b'; 如果你想强制使REGEXP比较区分大小写,使用BINARY关键字使其中一个字符串变为二进制字符串。该查询只匹配名称首字母的小写‘b’。 mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b'; 为了找出以“fy”结尾的名字,使用“$”匹配名字的结尾: mysql> SELECT * FROM pet WHERE name REGEXP 'fy$'; 为了找出包含一个“w”的名字,使用以下查询: mysql> SELECT * FROM pet WHERE name REGEXP 'w'; 为了找出包含正好5个字符的名字,使用“^”和“$”匹配名字的开始和结尾,和5个“.”实例在两者之间: mysql> SELECT * FROM pet WHERE name REGEXP '^.....$'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+ 你也可以使用“{n}”“重复n次”操作符重写前面的查询: mysql> SELECT * FROM pet WHERE name REGEXP ‘^.{5}$’; //查询结果和上面一样mysql> SELECT * FROM pet WHERE name REGEXP 'w'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+regexp ‘word?’ 可匹配任何带有 wor word子串的字段 。
  • 17. 正则表达式 描述了一组字符串。最简单的正则表达式是不含任何特殊字符的正则表达式。例如,正则表达式hello匹配hello。 非平凡的正则表达式采用了特殊的特定结构,从而使得它们能够与1个以上的字符串匹配。例如,正则表达式hello|word匹配字符串hello或字符串word。 作为一个更为复杂的示例,正则表达式B[an]*s匹配下述字符串中的任何一个:Bananas,Baaaaas,Bs,以及以B开始、以s结束、并在其中包含任意数目a或n字符的任何其他字符串。 对于REGEXP操作符,正则表达式可以使用任何下述特殊字符和结构: · ^ 匹配字符串的开始部分。 mysql> SELECT 'fo\nfo' REGEXP '^fo$'; -> 0 mysql> SELECT 'fofo' REGEXP '^fo'; -> 1 · $ 匹配字符串的结束部分。 mysql> SELECT 'fo\no' REGEXP '^fo\no$'; -> 1 mysql> SELECT 'fo\no' REGEXP '^fo$'; -> 0 · . 匹配任何字符(包括回车和新行)。 mysql> SELECT 'fofo' REGEXP '^f.*$'; -> 1 mysql> SELECT 'fo\r\nfo' REGEXP '^f.*$'; -> 1 · a* 匹配0或多个a字符的任何序列。 mysql> SELECT 'Ban' REGEXP '^Ba*n'; -> 1 mysql> SELECT 'Baaan' REGEXP '^Ba*n'; -> 1 mysql> SELECT 'Bn' REGEXP '^Ba*n'; -> 1 · a+ 匹配1个或多个a字符的任何序列。 mysql> SELECT 'Ban' REGEXP '^Ba+n'; -> 1 mysql> SELECT 'Bn' REGEXP '^Ba+n'; -> 0 · a? 匹配0个或1个a字符。 mysql> SELECT 'Bn' REGEXP '^Ba?n'; -> 1 mysql> SELECT 'Ban' REGEXP '^Ba?n'; -> 1 mysql> SELECT 'Baan' REGEXP '^Ba?n'; -> 0 · de|abc 匹配序列de或abc。 mysql> SELECT 'pi' REGEXP 'pi | apa'; -> 1 mysql> SELECT 'axe' REGEXP 'pi|apa'; -> 0 mysql> SELECT 'apa' REGEXP 'pi|apa'; -> 1 mysql> SELECT 'apa' REGEXP '^(pi|apa)$'; -> 1 mysql> SELECT 'pi' REGEXP '^(pi|apa)$'; -> 1 mysql> SELECT 'pix' REGEXP '^(pi|apa)$'; -> 0
  • 18. · (abc)* 匹配序列abc的0个或多个实例。 mysql> SELECT 'pi' REGEXP '^(pi)*$'; -> 1 mysql> SELECT 'pip' REGEXP '^(pi)*$'; -> 0 mysql> SELECT 'pipi' REGEXP '^(pi)*$'; -> 1 · {1}, {2,3} {n}或{m,n}符号提供了编写正则表达式的更通用方式,能够匹配模式的很多前述原子(或“部分”)。m和n均为整数。 o a* 可被写入为a{0,}。 o a+ 可被写入为a{1,}。 o a? 可被写入为a{0,1}。 更准确地讲,a{n}与a的n个实例准确匹配。a{n,}匹配a的n个或更多实例。a{m,n}匹配a的m~n个实例,包含m和n。 m和n必须位于0~RE_DUP_MAX(默认为255)的范围内,包含0和RE_DUP_MAX。如果同时给定了m和n,m必须小于或等于n。 mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e'; -> 0 mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e'; -> 1 mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e'; -> 1 · [a-dX], [^a-dX] 匹配任何是(或不是,如果使用^的话)a、b、c、d或X的字符。两个其他字符之间的“-”字符构成一个范围,与从第1个字符开始到第2个字符之间的所有字符匹配。 例如,[0-9]匹配任何十进制数字 。要想包含文字字符“]”,它必须紧跟在开括号“[”之后。要想包含文字字符“-”,它必须首先或最后写入。对于[]对内未定义任何特殊含义的任何字符,仅与其本身匹配。 mysql> SELECT 'aXbc' REGEXP '[a-dXYZ]'; -> 1 mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]$'; -> 0 mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]+$'; -> 1 mysql> SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$'; -> 0 mysql> SELECT 'gheis' REGEXP '^[^a-dXYZ]+$'; -> 1 mysql> SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$'; -> 0 · [.characters.] 在括号表达式中(使用[和]),匹配用于校对元素的字符序列。字符为单个字符或诸如新行等字符名。在文件regexp/cname.h中,可找到字符名称的完整列表。 mysql> SELECT '~' REGEXP '[[.~.]]'; -> 1 mysql> SELECT '~' REGEXP '[[.tilde.]]'; -> 1
  • 19. · [=character_class=] 在括号表达式中(使用[和]),[=character_class=]表示等同类。它与具有相同校对值的所有字符匹配,包括它本身,例如,如果o和(+)均是等同类的成员,那么[[=o=]]、[[=(+)=]]和[o(+)]是同义词。等同类不得用作范围的端点。 · [:character_class:] 在括号表达式中(使用[和]),[:character_class:]表示与术语类的所有字符匹配的字符类。标准的类名称是: 它们代表在ctype(3)手册页面中定义的字符类。特定地区可能会提供其他类名。字符类不得用作范围的端点。 mysql> SELECT 'justalnums' REGEXP '[[:alnum:]]+'; -> 1 mysql> SELECT '!!' REGEXP '[[:alnum:]]+'; -> 0 · [[:<:]], [[:>:]] 这些标记表示word边界。它们分别与word的开始和结束匹配。word是一系列字字符,其前面和后面均没有字字符。字字符是alnum类中的字母数字字符或下划线(_)。 mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1 mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0 要想在正则表达式中使用特殊字符的文字实例,应在其前面加上2个反斜杠“\”字符。MySQL解析程序负责解释其中一个,正则表达式库负责解释另一个。例如,要想与包含特殊字符“+”的字符串“1+2”匹配,在下面的正则表达式中,只有最后一个是正确的: mysql> SELECT '1+2' REGEXP '1+2'; -> 0 mysql> SELECT '1+2' REGEXP '1\+2'; -> 0 mysql> SELECT '1+2' REGEXP '1\\+2'; -> 1 alnum文字数字字符alpha文字字符blank空白字符cntrl控制字符digit数字字符graph图形字符lower小写文字字符print图形或空格字符punct标点字符space空格、制表符、新行、和回车upper大写文字字符xdigit十六进制数字字符
  • 20. MySQL实现行转列行转列SELECT YEAR, sum( CASE WHEN MONTH = '1' THEN VALUE END ) m1, sum( CASE WHEN MONTH = '2' THEN VALUE END ) m2, sum( CASE WHEN MONTH = '3' THEN VALUE END ) m3, sum( CASE WHEN MONTH = '4' THEN VALUE END ) m4 FROM test GROUP BY YEAR //可去掉sum函数group_concat():mysql> delete from a -> using demo as a, demo as b -> where (a.id < b.id) -> and (a.site = b.site);mysql> select a.* -> from demo a, demo b -> where a.id > b.id -> and (a.site = b.site);使用表别名: (表 demo)若去掉最后一行的“group by a.year”,输出:select b.year,b.value from test b,test a where b.year=a.year and b.month=1; 等效于两张不同的表a、b之间 通过字段year内部联结起来了。 联结,即与主键联结 的year会被全部检索出来。通过year自联结,即 把所有自联结字段year 保证输出。
  • 21. case _value when 实现: select name, sum( case subject when 'chinese' then score else 0 end) as 'chinese', sum( case subject when 'math' then score else 0 end) as 'math', sum( case subject when 'english' then score else 0 end) as 'english‘ from user group by name; //groub by name:即name不重复,根据name组织其他列存储过程实现: create procedure line_to_col() begin declare i int; declare _chinese int; declare _math int; declare _english int; declare _name varchar(10); declare test_cursor CURSOR for select name from user; select count(*) into i from user; CREATE TEMPORARY TABLE tmp_tab(name varchar(10), chinese_score int, math_socre int, english_score int); if i>0 then open test_cursor; repeat fetch test_cursor into _name; select score into _chinese from user where subject = 'chinese' and name =_name; select score into _math from user where subject = 'math' and name =_name; select score into _english from user where subject = 'english' and name =_name; insert into tmp_tab values(_name,_chinese,_math,_english); set i=i-1; until i=0 end repeat; close test_cursor; end if; select DISTINCT * from tmp_tab; drop table tmp_tab; end在写存储过程的时候遇到了两个问题,分别是关于游标和临时表。 因为user表中有重复的name,在设置游标时,我想直接过滤掉重复的用户,所以将游标设置成declare test_cursor CURSOR for select DISTINCT name from user;这样设置游标之后,执行存储过程,报错提示没有获取任何数据。小小同志跟我解释说,游标是遍历用的,怎么能distinct呢 ,只能对取数做distinct。 为了拼接输出内容,我建了一个临时表,第一次调用line_to_col的时候可以正常执行,第二次调用时就报错提示tmp_tab已存在。所以在存储过程中创建临时表,执行完后,需要及时把临时表删除掉,避免重复调用时出错。另外,小小跟我强调,临时表是放在内存里的,会耗资源,所以在用完之后需要及时删除掉。在创建表格时,您可以使用TEMPORARY关键词。只有在当前连接情况下,TEMPORARY表才是可见的。当连接关闭时,TEMPORARY表被自动取消清空。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为止。)您必须拥有CREATE TEMPORARY TABLES权限,才能创建临时表。
  • 22. (本页无文本内容)