在劫

吾生也有涯,而知也无涯 。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

启动MySQL:net start mysql
停止MySQL:net stop mysql
卸载MySQL:sc delete mysql
MySQL脚本基本组成:

  1. 标识符:
    标识符用来命名一些对象, 如数据库、表、列、变量等, 以便在脚本中的其他地方引用。MySQL标识符命名规则稍微有点繁琐, 这里我们使用万能命名规则: 标识符由字母、数字或下划线(_)组成, 且第一个字符必须是字母或下划线。
    对于标识符是否区分大小写取决于当前的操作系统, Windows下是不敏感的, 但对于大多数 linux\unix 系统来说, 这些标识符大小写是敏感的。
  2. 关键字:
    MySQL的关键字众多。
  3. 语句:
    MySQL语句是组成MySQL脚本的基本单位, 每条语句能完成特定的操作, 他是由 SQL 标准语句 + MySQL 扩展语句组成。
  4. 函数:
    MySQL函数用来实现数据库操作的一些高级功能, 这些函数大致分为以下几类: 字符串函数、数学函数、日期时间函数、搜索函数、加密函数、信息函数。
    MySQL数据类型:
  5. 数字类型
  • 整数: tinyint、smallint、mediumint、int、bigint

    MySQL整数数据类型 含义(有符号)
    tinyint(m) 1个字节 范围(-128~127)
    smallint(m) 2个字节 范围(-32768~32767)
    mediumint(m) 3个字节 范围(-8388608~8388607)
    int(m) 4个字节 范围(-2147483648~2147483647)
    bigint(m) 8个字节 范围(+-9.22*10的18次方)
    取值范围如果加了unsigned,则最大值翻倍,如tinyint unsigned的取值范围为(0~256)。int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围
  • 浮点数: float、double、real、decimal

    MySQL浮点数数据类型 含义(有符号)
    float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位
    double(m,d) 双精度浮点型 16位精度(8字节) m总个数,d小数位
    设一个字段定义为float(5,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位
  • 定点数

    浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。 decimal(m,d) 参数m<65 是总个数,d<30且 d
  1. 日期和时间
  • date、time、datetime、timestamp、year

    MySQL日期时间数据类型 含义
    date 日期 '0000-00-00'
    time 时间 '00:00:00'
    datetime 日期时间 '0000-00-00 00:00:00'
    timestamp 自动存储记录修改时间
    若定义一个字段为timestamp,这个字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间
  1. 字符串类型
  • 字符串: char、varchar

  • 文本: tinytext、text、mediumtext、longtext

  • 二进制(可用来存储图片、音乐等): tinyblob、blob、mediumblob、longblob

    MySQL字符串数据类型 含义
    char(n) 固定长度,最多255个字符
    varchar(n) 固定长度,最多65535个字符
    tinytext 可变长度,最多255个字符
    text 可变长度,最多65535个字符
    mediumtext 可变长度,最多2的24次方-1个字符
    longtext 可变长度,最多2的32次方-1个字符
    char和varchar的区别: 1. char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉。所以char类型存储的字符串末尾不能有空格,varchar不限于此。 2. char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),所以varchar(4),存入3个字符将占用4个字节。 3. char类型的字符串检索速度要比varchar类型的快。
    varchar和text的区别: 1. varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),text是实际字符数+2个字节。 2. text类型不能有默认值。 3. varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text,在都创建索引的情况下,text的索引似乎不起作用。
    二进制数据(_Blob): 1. BLOB和_text存储方式不同,_TEXT以文本方式存储,英文存储区分大小写,而_Blob是以二进制方式存储,不分大小写。 2. BLOB存储的数据只能整体读出。 3. TEXT可以指定字符集,_BLO不用指定字符集。
MySQL属性关键字 含义
NULL 数据列可包含NULL值
NOT NULL 数据列不允许包含NULL值
DEFAULT 默认值
PRIMARY KEY 主键
AUTO_INCREMENT 自动递增,适用于整数类型
UNSIGNED 无符号
CHARACTER SET name 指定一个字符集

登录数据库:

登录MySQL:mysql -h 主机名 -u 用户名 -p

创建数据库:

CREATE DATABASE 数据库名 [其它选项];

CREATE DATABASE test_db CHARACTER SET GBK;
--创建名为test_db的数据库,并设定字符编码为GBK

选择要操作的数据库

登录时指定:mysql -D 所选择的数据库名 -h 主机名 -u 用户名 -p

在登录后使用USE语句指定:USE 数据库名;
--USE语句可以不加分号

创建数据库表

CREATE TABLE 表名称(列声明);

CREATE TABLE student(
	id int unsigned not null auto_increment primary key,
	name char(9) not null,
	sex char(4) not null,
	age tinyint unsigned nou null,
	tel char(13) null default "-"
);
--创建名为student的数据库表
create table student(columns) 为创建数据库表的命令, 列的名称以及该列的数据类型将在括号内完成;
括号内声明了5列内容, id、name、sex、age、tel为每列的名称, 后面跟的是数据类型描述, 列与列的描述之间用逗号(,)隔开;
以 "id int unsigned not null auto_increment primary key" 行进行介绍:
    "id" 为列的名称;
    "int" 指定该列的类型为 int(取值范围为 -8388608到8388607), 在后面我们又用 "unsigned" 加以修饰, 表示该类型为无符号型, 此时该列的取值范围为 0到16777215;
    "not null" 说明该列的值不能为空, 必须要填, 如果不指定该属性, 默认可为空;
    "auto_increment" 需在整数列中使用, 其作用是在插入数据时若该列为 NULL, MySQL将自动产生一个比现存值更大的唯一标识符值。在每张表中仅能有一个这样的值且所在列必须为索引列。
    "primary key" 表示该列是表的主键, 本列的值必须唯一, MySQL将自动索引该列

导入sql脚本

mysql -D test_db -u root -p < 脚本.sql

查询

SELECT 列名称 FROM 表名称 [查询条件];
--如果是查询所有的列,用 * 号表示
--SELECT * FROM 表名称 [查询条件];

按特定条件查询:
	WHERE关键字用于指定查询条件:SELECT 列名称 FROM 表名称 WHERE 条件;
--SELECT * FROM student WHERE sex="男";
--查询sex值为男的行

插入数据

INSERT [INTO] 表名 [(列名1, 列名2, ...)] VALUES (值1, 值2, ....);

插入部分数据,或者不按列的顺序插入:
INSERT INTO studen(name, sex, age) VALUES(...);


INSERT INTO的几种方式:
方式1、 INSERT INTO t1(field1,field2) VALUES(v001,v002);            // 明确只插入一条Value

方式2、 INSERT INTO t1(field1,field2) VALUES(v101,v102),(v201,v202),(v301,v302),(v401,v402);

在插入批量数据时方式2优于方式1.

方式3.1、  INSERT INTO t2(field1,field2) SELECT col1,col2 FROM t1 WHERE ……
由于可以指定插入到talbe2中的列,以及可以通过相对较复杂的查询语句进行数据源获取,可能使用起来会更加的灵活一些,但我们也必须注意,我们在指定目标表的列时,一定要将所有非空列都填上,否则将无法进行数据插入,还有一点比较容易出错的地方就是,当我们写成如下简写格式:

方式3.2、  INSERT INTO t2 SELECT id, name, address FROM t1

此时,我们如果略掉了目标表的列的话,则默认会对目标表的全部列进行数据插入,且SELECT后面的列的顺序 必须和目标表中的列的定义顺序完全一致 才能完成正确的数据插入,这是一个很容易被忽略的地方,值得注意。

更新表中数据:

UPDATE 表名称 SET 列名称=新值 WHERE 更新条件

删除表中数据:

DELETE FROM 表名称 WHERE  删除条件;

对表进行修改:

ALTER TABLE用于创建后对表进行修改:
添加列:
	ALTER TABLE 表名 ADD 列名 列数据类型 [AFTER 插入位置];
修改列:
	ALTER TABLE 表名 CHANGE 列名称 列新名称 新数据类型;
删除列:
	ALTER TABLE 表名 DROP 列名称;
重命名表:
	ALTER TABLE 表名 RENAME 新表名;
删除整张表:
	DROP TABLE 表名;
删除整个数据库:
	DROP DATABASE 数据库名;

查看显示所有数据库:

SHOW DATABASE;

查看当前使用数据库:

SELECT DATABASE();

查看数据库使用端口:

SHOW VARIABLES LIKE 'port';

查看当前数据库大小:

mysql> select concat(round(sum(data_length)/(1024*1024),2) + round(sum(index_length)/(1024*1024),2),'MB') as 'DB Size'
    -> from tables 
    -> where table_schema='INVOICE'

查看索引所占空间大小:

mysql> select concat(round(sum(index_length)/(1024*1024),2),'MB') as 'DB Size' 
    -> from tables 
    -> where table_schema='INVOICE';

查看数据库编码:

SHOW VARIBALES LIKE '%character%';

character_set_client      为客户端编码方式;

character_set_connection  为建立连接使用的编码;

character_set_database    为数据库的编码;

character_set_results     为结果集的编码;

character_set_server      为数据库服务器的编码;

查看数据编码的另一种方式:

STATUS; 
查看当前数据编码

查看数据库信息:

SHOW TABLES;

或者

select * from information_schema.tables where table_schema='databasename';

查看数据库所有用户信息:

SELECT DISTINCT CONCAT('user:' '',user,'''@''',host,''';') AS query FROM mysql.user;

查看某个具体用户权限:

SHOW GRANTS FOR 'root'@'localhost';

查看数据库的最大连接数:

SHOW VARIABLES LIKE '%max_connections%';

查看当前连接数,并发数:

SHOW STATUS LIKE 'Threads%';

Threads_cached : 代表当前此时此刻线程缓存中有多少空闲线程。
Threads_connected :代表当前已建立连接的数量,因为一个连接就需要一个线程,所以也可以看成当前被使用的线程数。
Threads_created :代表从最近一次服务启动,已创建线程的数量。
Threads_running :代表当前激活的(非睡眠状态)线程数。并不是代表正在使用的线程数,有时候连接已建立,但是连接处于sleep状态,这里相对应的线程也是sleep状态。

查看数据文件存放路径:

SHOW VARIABLES LIKE '%datadir%';

新建表并复制其他表:

复制表结构:
CREATE TABLE IF NOT EXISTS tb_new(LIKE db_table1);

复制表数据:
CREATE TABLE IF NOT EXISTS tb_new(SELECT * FROM db_table1);

清空数据:

TRUNCATE TABLE db.table;

DELETE FROM da.table;

删除数据表:

DROP db.table;

删除索引:

DROP INDEX index_name;

添加索引:

ADD FULLTEXT INDEX index_name USING BTREE (field1); 

ALTER TABLE db.table1 ADD UNIQUE INDEX index_name USING BTREE (field1);

删除字段:

ALTER TABLE db.table1 DROP COLUMN field1;

修改字段:

ALTER TABLE db.table1 
CHANGE COLUMN field_name new_field_name  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `id`;

向另一个数据库中拷贝表:

SELECT * INTO table2 IN  'Backup.mdb' FROM table1;

删除数据库:

DROP DATABASE db_name;

查看表结构

DESC tableName;

模糊查询

LIKE 'data%';
LIKE '%data';
LIKE '%data%';
LIKE '_data'; 查看data结尾的五个字母数据
LIKE '[CK]ars[eo]n%'; CK选一个,eo选一个和ars,n组成字符
LIKE '[M-Z]data'; M到Z之间的任意单个字母的所有名称
LIKE 'd[^c]%'; d开头,第二个字母不是c的所有名称

其他见正则表达式...

主键

表中每一个都应该具有唯一标识自己的列(一组列),这个列成为主键
作为主键必须满足以下条件:
1、任何两行都不具有相同的主键值,就是这列的值互不相同;
2、每个行都具有一个主键值,主键列不能设置NULL;
3、主键的值不允许进行修改和更新

设定主键:
CREATE TABLE t1(
	id int not null primary key
);
设定复合主键:
CREATE TABLE t1(
	id int not null,
	name char(20),
	primary key(id,name)
);
主键自增:
CREATE TABLE t1(
	id int not null primary key auto_increment
);
建完表设定主键
ALTER TABLE t ADD PRIMARY KEY (id);

外键

关键字:FOREIGN KEY,外键约束
实体A的某个字段,指向另一个实体B的主键,那么实体A的这个字段称为外键。
其中被指向的实体,成为主实体集(主表),也叫父实体集(父表)。
负责指向的实体集叫做从实体集(从表),也叫作子实体集(子表)。

1、增加子表记录的时候,需要判断是否有与之对应的附表记录?
2、当删除或更改附表记录的时候,子表应该如何处理相关记录?

定义父表:
CREATE TABLE web_class(
	class_id int unsigned primary key,
	class_teater varchar(20) not null
);

定义子表并设定外键:
CREATE TABLE web_student(
	stu_id int unsigned primary key auto_increment,
	stu_name varchar(20) not null,
	stu_class_id int unsigned,
	foreign key(stu_class_id) references web_class(class_id)
);

设置级联操作
级联操作(关联动作):操作一张表,影响另一张表
1、主表更新:
	on update[级联操作]
2、主表删除:
	on delete[级联操作]

上面级联操作常见的有三种形式:
cascade:同步操作,串联操作,也就是当主表的字段更新或者删除的时候,从表的外键也进行删除或者更新
set null:设置为空,当主表的字段更新或者删除的时候,子表的外键字段为空,前提是没有设置为非空约束
restrict:子表有匹配记录,就拒绝主表更新或删除

on update和on delete可以同时使用:
-- on update cascade on delete cascade //主表更新子表同步操作,主表删除子表也同步操作
-- on update cascade on delete set null
-- on update cascade on delete restrict

-- on update set null on delete cascade //主表更新子表设置为空,主表删除子表同步操作
-- on update set null on delete set null
-- on update set null on delete restrict

-- on update restrict on delete cascade //主表更新子表有匹配就拒绝主表更新,主表删除子表同步操作
-- on update restrict on delete set null
-- on update restrict on delete restrict

所以完整的外键定义语法:
	foreign key(从表的外键字段) references 主表名(主表的主键)
	on update cascade|set null|restrict on delete cascade|set null|restrict

删除外键:
	alter table web_student drop foreign key 'foreign_key_name';
	foreign_key_name不是外键的字段名,而是系统在定义外键的时候自动分配的一个名字,可以通过show create table table_name\G;查看

增加外键
	alter table table_name add foreign key(从表的外键字段) reference 主表名(主表的主键)级联操作;

	alter table 表名 add foreign key(从表的外键字段) references 主表名(主表的主键)
	on update cascade|set null|restrict on delete cascade|set null|restrict

外键的约束,只有在InnoDB存储引擎上存储才能执行	

多表操作

cross join(交叉连接):获取多个表中的交叉关系
inner join(内连接):获取两个表中字段匹配关系的记录
外连接:
	left join(左连接):获取左表所有记录,即使右表没有匹配记录
	right join(右连接):用于获取右表所有记录,即使左表没有对应匹配的记录

union:求两张表的并集
	SELECT * FROM tb1 union (SELECT * FROM tb2); //查询出来的表,以tb1的表查询结果的字段为准,且列数相同

子查询
	通过查询的结果为新表,然后对新表进行数据查询,一般发生在多对多关系中
	语法:
	select a.* from (select * from tb1 where 过滤条件) as a where 过滤条件;
	
	多张表
	select a.column1,a.column2,b.column1,b.column2... from (select * from tb1 where 过滤条件) as a , (select * from tb2 where 过滤条件) as b where 外键匹配 and 过滤条件;
	
	[注](select * from tb1 where 过滤条件) as a:表示tb2查询出来的结果作为a表,整条语句的意思是:tb2查询的结果作为a表,通过匹配规则查询a表的相关数据
	
	(select * from tb1 where 过滤条件) as a:只要把括号里面的当做一张表就好理解了。

交叉连接(笛卡尔积查询)
	1、SELECT *FROM CUSTOMER C, ORDERS O;
	2、SELECT c.id,c.name,o.order FROM CUSTOMER c CROSS JOIN O;

	查询两张表的所有相匹配的数据:
	SELECT * FROM table_1,table_2;
	查询两种表对应关系:
	SELECT * FROM table_1,table_2 WHERE table_1.c = table_2.c;

	table tab_1:为避免表名太长,所有用简单的字符tab_1代替

内连接
	1、隐式写法:
		SELECT * FROM table_1 tb1,table_2 tb2 WHERE tb1.c = tb2.c;
	2、显示写法:
	SELECT * FROM table_1 tb1 inner join table_2 tb2 on tb1.c = tb2.c;
	
	注意下面两种写法:
	SELECT * FROM table_1 tb1 inner join table_2 tb2 on tb1.c = tb2.c;
	SELECT * FROM table_2 tb2 inner join table_1 tb1 on tb1.c = tb2.c;
	列的排序不同,第一种table_1的列排在前面(从左向右),后者相反

外连接
	left join:
		SELECT * FROM table_1 left join table_2 on table_1.c = xx; 
		SELECT * FROM table_2 left join table_1 on table_2.c = xx; 
		上面两种方式,第一种table_1显示在前面,table——2显示在后面,第二种相反
	right join:
		SELECT * FROM table_1  RIGHT JOIN table_2 on table_1.c=xx;
		table_1在左边,table_2在右边

外连接不仅返回连接表中符合连接条件及查询条件的数据行,也返回左表(左外连接时)或右表(右外连接时)中仅符合查询条件但不符合连接条件的数据行

存储过程

储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。存储过程通常有以下优点:
1、编译优化,执行速度快
2、存储过程允许标准组件是编程,封装与抽象,简单调用
3、存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和教复杂的运算
4、存储过程可被作为一种机制来充分利用,限制与安全
5、存储过程减少网络流量

创建存储过程:
	CREATE PROCEDURE 过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型...]]) [特性...] 过程体
	
	DELIMITER //
	CREATE PROCEDURE myproc(OUT S INT)
		BEGIN
			SELECT COUNT(*) INTO s FROM students;
		END
	DELIMITER;

MySQL默认以“;”为分隔符,如果没有声明分隔符,则编译器会把存储过程当成SQL语句进行处理,编译过程会报错,所以要实现用"DELIMITER //"声明当前段分隔,让编译器把两个“//”直接的内容当做存储过程的代码,不执行这些代码;“DELIMITER;”的意为把分隔符还原。

存储过程根据需要可能会有输入,输出,输入输出参数,如果有多个参数用逗号分开。MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT:
IN:参数的值必须在调用存储过程时调用,在存储过程中修改该参数的值不能被返回,为默认值。
OUT:该值可在存储过程内部被改变,并可返回
INOUT:调用时指定,并且可被改变和返回
过程体:以BEGIN开始和END结束

DELIMITER //
  CREATE PROCEDURE in_param(IN p_in int)
    BEGIN
    SELECT p_in; //检索p_in
    SET p_in=2;	//设定p_in=2
    SELECT p_in; //检索p_in
    END;
    //
DELIMITER ;

#调用
SET @p_in=1; //设定p_in=1
CALL in_param(@p_in); //调用存储过程
SELECT @p_in; //检索p_in

变量
	DECLARE 变量名1[,变量名2...]数据类型 [默认值];
变量赋值
	SET 变量名 = 变量值[,变量名=变量值...]
	用户变量一般以@开头
	滥用用户变量会导致程序难以理解及管理
	在MySQL客户端使用用户变量
	SELECT 'Hello World' into @x;
	SELECT @x;
	
	SET @y='Goodbye Cruel World';
	SELECT @y;
	SET @z=1+2+3;
	SELECT @z;

在存储过程中使用用户变量
	CREATE PROCEDURE GreetWorld() SELECT CONCAT(@greeting,' World');
	SET @greeting='Hello';
	CALL GreetWorld();
在存储过程间传递全局范围的用户变量
	CREATE PROCEDURE p1() SET @last_proc='p1';
	CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc);
	CALL p1();
	CALL p2();

存储过程注释:-- 双杠

MySQL存储过程的调用
	用call和你过程名以及一个括号,括号里面根据需要,加入参数,参数包括输入参数、输出参数、输入输出参数

MySQL存储过程的查询
	#查询存储过程
	SELECT name FROM mysql.proc WHERE db='数据库名';
	SELECT routine_name FROM information_schema.routines WHERE routine_schema='数据库名';
	SHOW PROCEDURE STATUS WHERE db='数据库名';
	
	#查看存储过程详细信息
	SHOW CREATE PROCEDURE 数据库.存储过程名;

MySQL存储过程的修改
	ALTER PROCEDURE 更改用CREATE PROCEDURE 建立的预先指定的存储过程,其不会影响相关存储过程或存储功能
	ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
	characteristic:
	{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
	| SQL SECURITY { DEFINER | INVOKER }
	| COMMENT 'string'

	sp_name参数表示存储过程或函数的名称;
	characteristic参数指定存储函数的特性。
	CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;
	NO SQL表示子程序中不包含SQL语句;
	READS SQL DATA表示子程序中包含读数据的语句;
	MODIFIES SQL DATA表示子程序中包含写数据的语句。
	SQL SECURITY { DEFINER | INVOKER }指明谁有权限来执行,DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。
	COMMENT 'string'是注释信息

MySQL存储过程删除
	DROP PROCEDURE [过程1[,过程2…]]

变量作用域
	内部变量在其作用域范围内享有更高的优先权,当执行到end时,内部变量消失,不再可见了,在存储
过程外再也找不到这个内部变量,但是可以通过out参数或者将其值指派给会话变量来保存其值

DECLARE 变量名 数据类型 [DEFAULT ''];声明变量并设定默认值

条件语句
	IF--THEN--ELSE

	DROP PROCEDURE IF EXISTS proc3;
	DELIMITER //
	CREATE PROCEDURE proc3(IN parameter int)
	  BEGIN
	    DECLARE var int;
	    SET var=parameter+1;
	    IF var=0 THEN
	      INSERT INTO t VALUES (17);
	    END IF ;
	    IF parameter=0 THEN
	      UPDATE t SET s1=s1+1;
	    ELSE
	      UPDATE t SET s1=s1+2;
	    END IF ;
	  END ;
	  //
	DELIMITER ;

CASE-WHEN-THEN-ELSE语句
	DELIMITER //
	  CREATE PROCEDURE proc4 (IN parameter INT)
	    BEGIN
	      DECLARE var INT;
	      SET var=parameter+1;
	      CASE var
	        WHEN 0 THEN
	          INSERT INTO t VALUES (17);
	        WHEN 1 THEN
	          INSERT INTO t VALUES (18);
	        ELSE
	          INSERT INTO t VALUES (19);
	      END CASE ;
	    END ;
	  //
	DELIMITER ;
循环语句:
	WHILE-DO…END-WHILE

	DELIMITER //
	  CREATE PROCEDURE proc5()
	    BEGIN
	      DECLARE var INT;
	      SET var=0;
	      WHILE var<6 DO
	        INSERT INTO t VALUES (var);
	        SET var=var+1;
	      END WHILE ;
	    END;
	  //
	DELIMITER ;

	REPEAT...END REPEAT
	此语句的特点是执行操作后检查结果
	DELIMITER //
	  CREATE PROCEDURE proc6 ()
	    BEGIN
	      DECLARE v INT;
	      SET v=0;
	      REPEAT
	        INSERT INTO t VALUES(v);
	        SET v=v+1;
	        UNTIL v>=5
	      END REPEAT;
	    END;
	  //
	DELIMITER ;

	LOOP...END LOOP

	DELIMITER //
	  CREATE PROCEDURE proc7 ()
	    BEGIN
	      DECLARE v INT;
	      SET v=0;
	      LOOP_LABLE:LOOP
	        INSERT INTO t VALUES(v);
	        SET v=v+1;
	        IF v >=5 THEN
	          LEAVE LOOP_LABLE;
	        END IF;
	      END LOOP;
	    END;
	  //
	DELIMITER ;
LABLES标号
	标号可以用在begin repeat while或者loop语句前,语句标号只能在合法的语句前面使用,可以跳出循环,使运行指令到复合语句的最后一步。

ITERATE迭代 
	DELIMITER //
	  CREATE PROCEDURE proc8()
	  BEGIN
	    DECLARE v INT;
	    SET v=0;
	    LOOP_LABLE:LOOP
	      IF v=3 THEN
	        SET v=v+1;
	        ITERATE LOOP_LABLE;
	      END IF;
	      INSERT INTO t VALUES(v);
	      SET v=v+1;
	      IF v>=5 THEN
	        LEAVE LOOP_LABLE;
	      END IF;
	    END LOOP;
	  END;
	  //
	DELIMITER ;
存储过程的基本函数
	CHARSET(str) //返回字串字符集
	CONCAT (string2 [,... ]) //连接字串
	INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0
	LCASE (string2 ) //转换成小写
	LEFT (string2 ,length ) //从string2中的左边起取length个字符
	LENGTH (string ) //string长度
	LOAD_FILE (file_name ) //从文件读取内容
	LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定开始位置
	LPAD (string2 ,length ,pad ) //重复用pad加在string开头,直到字串长度为length
	LTRIM (string2 ) //去除前端空格
	REPEAT (string2 ,count ) //重复count次
	REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str
	RPAD (string2 ,length ,pad) //在str后用pad补充,直到长度为length
	RTRIM (string2 ) //去除后端空格
	STRCMP (string1 ,string2 ) //逐字符比较两字串大小,
	SUBSTRING (str , position [,length ]) //从str的position开始,取length个字符,
	注:mysql中处理字符串时,默认第一个字符下标为1,即参数position必须大于等于1
	TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
	UCASE (string2 ) //转换成大写
	RIGHT(string2,length) //取string2最后length个字符
	SPACE(count) //生成count个空格
	数学类
	ABS (number2 ) //绝对值
	BIN (decimal_number ) //十进制转二进制
	CEILING (number2 ) //向上取整
	CONV(number2,from_base,to_base) //进制转换
	FLOOR (number2 ) //向下取整
	FORMAT (number,decimal_places ) //保留小数位数
	HEX (DecimalNumber ) //转十六进制
	注:HEX()中可传入字符串,则返回其ASC-11码,如HEX('DEF')返回4142143
	也可以传入十进制整数,返回其十六进制编码,如HEX(25)返回19
	LEAST (number , number2 [,..]) //求最小值
	MOD (numerator ,denominator ) //求余
	POWER (number ,power ) //求指数
	RAND([seed]) //随机数
	ROUND (number [,decimals ]) //四舍五入,decimals为小数位数] 注:返回类型并非均为整数
	日期时间类
	ADDTIME (date2 ,time_interval ) //将time_interval加到date2
	CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区
	CURRENT_DATE ( ) //当前日期
	CURRENT_TIME ( ) //当前时间
	CURRENT_TIMESTAMP ( ) //当前时间戳
	DATE (datetime ) //返回datetime的日期部分
	DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或时间
	DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime
	DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去一个时间
	DATEDIFF (date1 ,date2 ) //两个日期差
	DAY (date ) //返回日期的天
	DAYNAME (date ) //英文星期
	DAYOFWEEK (date ) //星期(1-7) ,1为星期天
	DAYOFYEAR (date ) //一年中的第几天
	EXTRACT (interval_name FROM date ) //从date中提取日期的指定部分
	MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串
	MAKETIME (hour ,minute ,second ) //生成时间串
	MONTHNAME (date ) //英文月份名
	NOW ( ) //当前时间
	SEC_TO_TIME (seconds ) //秒数转成时间
	STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示
	TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
	TIME_TO_SEC (time ) //时间转秒数]
	WEEK (date_time [,start_of_week ]) //第几周
	YEAR (datetime ) //年份
	DAYOFMONTH(datetime) //月的第几天
	HOUR(datetime) //小时
	LAST_DAY(date) //date的月的最后日期
	MICROSECOND(datetime) //微秒
	MONTH(datetime) //月
	MINUTE(datetime) //分返回符号,正负或0
	SQRT(number2) //开平方 

MYSQL 事务处理主要有两种方法:
1、用 BEGIN, ROLLBACK, COMMIT来实现
    BEGIN 开始一个事务
    ROLLBACK 事务回滚
    COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:
    SET AUTOCOMMIT=0 禁止自动提交
    SET AUTOCOMMIT=1 开启自动提交

事务管理

    1、事务的原子性:一组事务,要么成功;要么撤回。
    2、稳定性 :有非法数据(外键约束之类),事务撤回。
    3、隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
    4、可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 选项 决定什么时候吧事务保存到日志里。
	在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交

事务控制语句:
    BEGIN或START TRANSACTION;显式地开启一个事务;
    COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改称为永久性的;
    ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
    SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
    RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
    ROLLBACK TO identifier;把事务回滚到标记点;
    SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。
MYSQL 事务处理主要有两种方法:
	1、用 BEGIN, ROLLBACK, COMMIT来实现
	    BEGIN 开始一个事务
	    ROLLBACK 事务回滚
	    COMMIT 事务确认
	2、直接用 SET 来改变 MySQL 的自动提交模式:
	    SET AUTOCOMMIT=0 禁止自动提交
	    SET AUTOCOMMIT=1 开启自动提交

mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb;  # 创建数据表
Query OK, 0 rows affected (0.04 sec)
 
mysql> select * from runoob_transaction_test;
Empty set (0.01 sec)
 
mysql> begin;  # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
 
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
 
mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)
 
mysql>  select * from runoob_transaction_test;
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
 
mysql> begin;    # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql>  insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
 
mysql> rollback;   # 回滚
Query OK, 0 rows affected (0.00 sec)
 
mysql>   select * from runoob_transaction_test;   # 因为回滚所以数据没有插入
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)

触发器

触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行
创建触发器语法:
CREATE TRIGGER trigger_name
trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_stmt

其中:
trigger_name:标识触发器名称,用户自行指定;
trigger_time:标识触发时机,取值为 BEFORE 或 AFTER;
trigger_event:标识触发事件,取值为 INSERT、UPDATE 或 DELETE;
tbl_name:标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt:触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句。
由此可见,可以建立6种触发器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE。

另外有一个限制是不能同时在一个表上建立2个相同类型的触发器,因此在一个表上最多建立6个触发器。

trigger_event 详解
MySQL 除了对 INSERT、UPDATE、DELETE 基本操作进行定义外,还定义了 LOAD DATA 和 REPLACE 语句,这两种语句也能引起上述6中类型的触发器的触发。
LOAD DATA 语句用于将一个文件装入到一个数据表中,相当与一系列的 INSERT 操作。
REPLACE 语句一般来说和 INSERT 语句很像,只是在表中有 primary key 或 unique 索引时,如果插入的数据和原来 primary key 或 unique 索引一致时,会先删除原来的数据,然后增加一条新数据,也就是说,一条 REPLACE 语句有时候等价于一条。
INSERT 语句,有时候等价于一条 DELETE 语句加上一条 INSERT 语句。
INSERT 型触发器:插入某一行时激活触发器,可能通过 INSERT、LOAD DATA、REPLACE 语句触发;
UPDATE 型触发器:更改某一行时激活触发器,可能通过 UPDATE 语句触发;
DELETE 型触发器:删除某一行时激活触发器,可能通过 DELETE、REPLACE 语句触发。

BEGIN … END 详解
在MySQL中,BEGIN … END 语句的语法为:

BEGIN
[statement_list]
END
其中,statement_list 代表一个或多个语句的列表,列表内的每条语句都必须用分号(;)来结尾。
而在MySQL中,分号是语句结束的标识符,遇到分号表示该段语句已经结束,MySQL可以开始执行了。因此,解释器遇到statement_list 中的分号后就开始执行,然后会报出错误,因为没有找到和 BEGIN 匹配的 END。
这时就会用到 DELIMITER 命令(DELIMITER 是定界符,分隔符的意思),它是一条命令,不需要语句结束标识,语法为:
DELIMITER new_delemiter
new_delemiter 可以设为1个或多个长度的符号,默认的是分号(;),我们可以把它修改为其他符号,如$:
DELIMITER $
在这之后的语句,以分号结束,解释器不会有什么反应,只有遇到了$,才认为是语句结束。注意,使用完之后,我们还应该记得把它给修改回来

NEW 与 OLD 详解
在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据;
在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据;
使用方法: NEW.columnName (columnName 为相应数据表某一列名)
另外,OLD 是只读的,而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用(如每插入一个学生前,都在其学号前加“2013”)

查看触发器
	SHOW TRIGGERS [FROM schema_name];
删除触发器
	DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

正则

SELECT * FROM users WHERE email NOT REGEXP '^[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z]{2,4}$'

临时表

mysql> CREATE TEMPORARY TABLE SalesSummary (
    -> product_name VARCHAR(50) NOT NULL
    -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00
    -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00
    -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0
);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO SalesSummary
    -> (product_name, total_sales, avg_unit_price, total_units_sold)
    -> VALUES
    -> ('cucumber', 100.25, 90, 2);

当你使用 SHOW TABLES命令显示数据表列表时,你将无法看到 SalesSummary表。
如果你退出当前MySQL会话,再使用 SELECT命令来读取原先创建的临时表数据,那你会发现数据库中没有该表的存在,因为在你退出时该临时表已经被销毁了

删除MySQL 临时表
	默认情况下,当你断开与数据库的连接后,临时表就会自动被销毁。当然你也可以在当前MySQL会话使用 DROP TABLE 命令来手动删除临时表。
	DROP TABLE SalesSummary;

序列使用

MySQL中使用序列的方法是使用AUTO_INCREMENT属性来定义列。

AUTO_INCREMENT属性1开始,以1为基数递增。

当插入记录时,如果把一个NULL插入到一个AUTO_INCREMENT列,MySQL将自动生成下一个序列编号。

当插入记录时,没有为AUTO_INCREMENT明确指定值,则等同插入NULL值。

当插入记录时,如果为AUTO_INCREMENT字段明确指定了一个数值,则会出现两种情况。

一、如果插入的值与已有的编号重复,会出现出错信息, 因为AUTO_INCREMENT数据列的值必须是唯一的。

二、如果插入的值大于已编号的值,则会把该插入到数据列中,并使在下一个编号将从这个新值 开始递增。

如果用UPDATE命令更新自增列,如果列值与已有的值重复,则会出错。如果大于已有值,则下一个编号从该值开始递增。

索引

主键和唯一索引的区别:
	键一定是唯一性索引,唯一性索引并不一定就是主键。
	1.主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。 
	2. 一个表中可以有多个唯一性索引,但只能有一个主键。 
	3. 主键列不允许空值,而唯一性索引列允许空值。 
	4. 索引可以提高查询的速度。 
	主键是逻辑键,索引是物理键,意思就是主键不实际存在,而索引实际存在在数据库中,主键一般都要建,主要是用来避免一张表中有相同的记录,索引一般可以不建,但如果需要对该表进行查询操作,则最好建,这样可以加快检索的速度。 
mysql> CREATE TABLE `wb_blog` ( 
    ->   `id` smallint(8) unsigned NOT NULL, 
    ->   `catid` smallint(5) unsigned NOT NULL DEFAULT '0', 
    ->   `title` varchar(80) NOT NULL DEFAULT '', 
    ->   `content` text NOT NULL, 
    ->   PRIMARY KEY (`id`), 
    ->   UNIQUE KEY `catename` (`catid`) 
    -> ) ; 
	为wb_blog表的'catid'字段创建名为catename的唯一索引
在创建表之后使用CREATE命令来创建
	CREATE UNIQUE INDEX catename ON wb_blog(catid);
删除唯一索引
	ALTER TABLE wb_blog DROP INDEX catename;

复制表

1.只复制表结构到新表
    CREATE TABLE 新表 SELECT * FROM 旧表 WHERE 1=2
    CREATE TABLE 新表 LIKE 旧表  

2.复制表结构及数据到新表
    CREATE TABLE 新表 SELECT * FROM 旧表 
3.复制旧表的数据到新表(假设两个表结构一样) 
    INSERT INTO 新表 SELECT * FROM 旧表  
4.复制旧表的数据到新表(假设两个表结构不一样)
    INSERT INTO 新表(字段1,字段2,.......) SELECT 字段1,字段2,...... FROM 旧表 
posted on 2017-11-20 02:24  长嘴大耳怪  阅读(217)  评论(0编辑  收藏  举报