有志者事竟成,破釜沉舟,百二秦关终属楚。 苦心人天不负,卧薪尝胆,三千越甲可吞吴。

提示:文章内容为《MySQL5.7从入门到精通》学习记录;按照实用及必须原则,选择其中部分章节进行针对学习。

MySQL学习记录

  • 学习记录
  • 学习任务
    • 3.数据库基本操作
    • 4.数据表的基本操作
      • 4.1 数据表的基本操作
      • 4.2 查看数据表结构
      • 4.3 修改数据表
      • 4.4 删除数据表
    • 5.数据类型和运算符
      • 5.1 MySQL数据类型介绍
      • 5.2 如何选择数据类型
      • 5.3 常见运算符介绍
    • 6.MySQL函数
      • 6.2 数学函数
      • 6.3 字符串函数
      • 6.5 条件判断函数
    • 7.查询数据
      • 7.1 基本查询语句
      • 7.2 单表查询
      • 7.2.1 查询所有字段
      • 7.2.2 查询指定字段
      • 7.2.3 查询指定记录
      • 7.2.4 带IN的关键字查询(查询指定范围内的条件记录)
      • 7.2.5 带BETWEEN AND 的范围查询
      • 7.2.6 带LIKE的字符匹配查询
      • 7.2.7 查询空值
      • 7.2.8 带AND的多条件查询
      • 7.2.9 带OR的多条件查询
      • 7.2.10 查询结果不重复
      • 7.2.11 对查询结果进行排序
      • 7.2.12 分组查询
      • 7.3 使用聚合函数查询
      • 7.3.1 COUNT()函数
      • 7.3.2 SUM()函数
      • 7.3.3 AVG()函数
      • 7.3.4 MAX()函数
      • 7.3.5 MIN()函数
      • 7.4.1 内连接查询
      • 7.4.2 外连接查询
      • 7.4.3 复合条件连接查询
      • 7.5 子查询
      • 7.5.1 带ANY、SOME关键字的子查询
      • 7.5.2 带ALL关键字的子查询
      • 7.5.3 带EXISTS 关键字的子查询
      • 7.5.4 带IN关键字的子查询
      • 7.5.5 带比较运算符的子查询
      • 7.6 合并查询结果
      • 7.7.1 为表取别名
      • 7.7.2 为字段取别名
    • 8.插入、更新与删除数据
      • 8.1 插入数据
    • 9.索引
      • 9.1 索引简介
      • 9.1.1 索引的含义和特点
    • 10.存储过程和函数
      • 10.1 创建存储过程和函数
      • 10.1.1 创建存储过程
    • 11.视图
      • 11.1 视图概述
      • 11.1.1 视图的含义
    • 16.性能优化
      • 16.2 优化查询
      • 16.2.1 分析查询语句
  • 全书配套代码合集
    • 第1章 例题
    • 第3章 例题
    • 第4章 例题
    • 第5章 例题
    • 第6章 例题
    • 第7章 例题
    • 第8章 例题
    • 第9章 例题
    • 第10章 例题
    • 第11章 例题
    • 第12章 例题
    • 第13章 例题
    • 第14章 例题
    • 第15章 例题
    • 第16章 例题
    • 第17章 例题
    • 第19章 例题

学习记录

20220608----学习开始
20220608----第五章《数据类型运算符》
20220609----第六章《MySQL函数》
20220610----第七章《查询数据》
20220701----第七章《查询数据》
20220702----第七章《查询数据》
20220704----第七章《查询数据》

学习任务

  • 3.1
  • 3.2
  • 4.1.1
  • 4.1.2
  • 4.1.4
  • 4.1.6
  • 4.1.7
  • 4.2.1
  • 4.2.2
  • 4.3.1
  • 4.3.2
  • 4.3.3
  • 4.3.4
  • 4.3.5
  • 4.4.1
  • 4.4.2
  • 5.1.1
  • 5.1.2
  • 5.1.3
  • 5.1.4
  • 5.1.5
  • 5.2
  • 5.3.1
  • 5.3.2
  • 5.3.4
  • 5.3.6
  • 6.2.1
  • 6.2.2
  • 6.2.3
  • 6.2.4
  • 6.2.8
  • 6.3.1
  • 6.3.2
  • 6.3.4
  • 6.3.13
  • 6.3.14
  • 6.4.1
  • 6.4.2
  • 6.4.12
  • 6.4.13
  • 6.5.1
  • 6.5.2
  • 6.5.3
  • 7.1
  • 7.2
  • 7.3
  • 7.4
  • 7.5.3
  • 7.5.4
  • 7.5.5
  • 7.6
  • 7.7.1
  • 7.7.2
  • 8.1
  • 8.2
  • 8.3
  • 9.1
  • 9.2
  • 10.1.1
  • 10.1.2
  • 10.1.3
  • 10.1.6
  • 10.2.1
  • 10.2.2
  • 10.5
  • 11.1.1
  • 11.1.2
  • 11.2
  • 11.3.1
  • 11.3.2
  • 11.3.3
  • 11.4
  • 11.5
  • 11.6
  • 14.4.1
  • 14.4.4
  • 16.2.1
  • 16.2.2
  • 16.2.3
  • 16.2.4

3.数据库基本操作

CREATE DATABASE database_name; # 创建数据库
DROP DATABASE database_name; # 删除数据库
SHOW ENGINES \G # 查看存储引擎

4.数据表的基本操作

4.1 数据表的基本操作

-- CREATE DATABASE test_db;
SHOW DATABASES;
-- SELECT USER,HOST,db,command FROM information_schema.PROCESSLIST;-- USE test_db;
-- CREATE  DATABASE test_db;USE test_db;
CREATE TABLE tb_emp2
(id INT (11) PRIMARY KEY, # 单字段主键;定义数据表tb_emp 2,其主键为id
NAME VARCHAR (25),
deptId INT (11),
salary FLOAT
);CREATE TABLE tb_emp3
(
id INT(11),
name VARCHAR(25),
deptId INT(11),
salary FLOAT,
PRIMARY KEY(id) # 单字段主键;定义数据表tb_emp 3,其主键为id
);CREATE TABLE tb_emp4 # 定义数据表tb_emp4,假设表中间没有主键id,为了唯一确定一个员工,可以把name、deptId联合起来做为主键(
name VARCHAR(25),
deptId INT(11),
salary FLOAT,
PRIMARY KEY(name,deptId)
);CREATE TABLE tb_emp6
(
id int(11) PRIMARY key,
name VARCHAR(25) NOT NULL, # 定义数据表tb_emp6,指定员工的名称不能为空
depId INT(11),
salary FLOAT
);CREATE TABLE tb_emp7
(
id      INT(11) PRIMARY KEY,
name   VARCHAR(25) NOT NULL,
deptId  INT(11) DEFAULT 0601,  # 默认约束指定某列默认值
salary  FLOAT
);CREATE TABLE tb_emp8
(
id      INT(11) PRIMARY KEY AUTO_INCREMENT, # 系统插入记录,系统自动生成字段主键值;MySQL主键值初始值为1;
name   VARCHAR(25) NOT NULL,
deptId  INT(11),
salary  FLOAT
);INSERT INTO tb_emp8 (name,salary)
VALUES('LUCY',10000),('Lura',12000),('Kevin',1500);

4.2 查看数据表结构

DESCRIBE tb_emp8; # 查看表基本结构语句
DESC tb_emp7;
SHOW CREATE TABLE tb_emp1; # 查看表详细信息
SHOW CREATE TABLE tb_emp1 \G # 查看表详细信息

4.3 修改数据表

SHOW TABLES;
ALTER TABLE tb_emp8 RENAME tb_deptment8; # 修改表名,不修改表结构
SHOW TABLES;DESC tb_emp7;
ALTER TABLE tb_emp7 MODIFY name VARCHAR(30); # 修改数据表中字段的数据类型
DESC tb_emp7;ALTER TABLE tb_emp7 CHANGE deptID DEPTID INT(10); # 修改数据表中的字段名
DESC tb_emp7;DESC tb_deptment8;
ALTER TABLE tb_deptment8 ADD managerId INT(10); # 添加一个没有完整性约束的INT类型的字段managerId(部门经理编号)DESC tb_deptment8;
ALTER TABLE tb_deptment8 ADD column1 VARCHAR(12) not null; # 添加一个不能为空的VARCHAR(12)
ALTER TABLE tb_deptment8 ADD column2 INT(12) FIRST;
ALTER TABLE tb_deptment8 ADD column3 INT(10) AFTER NAME;
ALTER TABLE tb_deptment8 DROP COLUMN2;

4.4 删除数据表

CREATE TABLE tb_emp1
(id INT(11),
name FLOAT,
salary FLOAT
);
DROP TABLE IF EXISTS tb_emp1 # 删除数据表tb_emp1CREATE TABLE tb_dept2
(
id       INT(11) PRIMARY KEY, # 主键所在表即是主表
name    VARCHAR(22),
location  VARCHAR(50)
);CREATE TABLE tb_emp
(
id       INT(11) PRIMARY KEY, # 关联字段中外键所在表即是从表
name     VARCHAR(25),
deptId   INT(11),
salary   FLOAT,
CONSTRAINT fk_emp_dept  FOREIGN KEY (deptId) REFERENCES tb_dept2(id)
); # fk_emp_dept(外键名)外键约束;depID(字段名)子表需要添加外键约束的字段列;tb_dept2(主表名)被子表外键依赖的表的名称;id(主键列)表示主表定义的主键列;SHOW CREATE TABLE tb_emp
SHOW ENGINES
DROP TABLE tb_dept2 # 提示:Cannot drop table 'tb_dept2' referenced by a foreign key constraint 'fk_emp_dept' on table 'tb_emp'存在外键约束,不能直接删除
ALTER TABLE tb_emp DROP FOREIGN KEY fk_emp_dept; # 解除子表关联的外键约束
DROP TABLE tb_dept2
SHOW TABLES;

5.数据类型和运算符

5.1 MySQL数据类型介绍

CREATE TABLE tb_emp1 (id INT (11),NAME VARCHAR (25),deptId INT (11),salary FLOAT);CREATE TABLE tmp1 (x TINYINT,y SMALLINT,z MEDIUMINT,m INT,n BIGINT
);
DESC tmp1;CREATE TABLE tmp2 (x FLOAT ( 5, 1 ),y DOUBLE ( 5, 1 ),z DECIMAL ( 5, 1 )
);
INSERT INTO tmp2 VALUES(5.12, 5.15, 5.123);
show WARNINGS;
SELECT * FROM tmp2;CREATE TABLE tmp3 ( y YEAR );
INSERT INTO tmp3 values(2010),('2020');
INSERT INTO tmp3 values ('2166'); # 插入数据超过year类型范围,不可正常插入
SELECT * FROM tmp3;DELETE FROM tmp3; # 删除表中数据
SELECT * FROM tmp3;
INSERT INTO tmp3 values('0'),('00'),('77'),('10'); # 插入数据
SELECT * FROM tmp3;DELETE FROM tmp3; # 首先删除表中的数据:
INSERT INTO tmp3 values(0),(78),(11); # 向表中插入数据:
SELECT * FROM tmp3; # 查看结果:CREATE TABLE tmp4 ( t TIME );
INSERT INTO tmp4 values('10:05:05 '), ('23:23'), ('2 10:10'), ('3 02'),('10');
SELECT * FROM tmp4;DELETE FROM tmp4; # 首先删除表中的数据:
INSERT INTO tmp4 values('101112'),(111213),( '0'); # 向表中插入数据:
INSERT INTO tmp4 values ( 107010); # 再向表中插入数据:
SELECT * FROM tmp4;DELETE FROM tmp4;
INSERT INTO tmp4 values (CURRENT_TIME) ,(NOW());
SELECT * From tmp4;CREATE TABLE tmp5 ( d DATE );
INSERT INTO tmp5 values('1998-08-08'),('19980808'),('20101010');
SELECT * FROM tmp5;CREATE TABLE tmp6 ( dt DATETIME );
INSERT INTO tmp6 VALUES ( '1998-08-08 08:08:08' ),( '19980808080808' ),( '20101010101010' );
INSERT INTO tmp6 values('99-09-09 09:09:09'),('990909090909'),('101010101010');
SELECT * FROM tmp6;CREATE TABLE tmp8 (ch CHAR (4),vch VARCHAR (4));
INSERT INTO tmp8 VALUES ('ab  ','ab  ');
CREATE TABLE tmp9 ( enm ENUM ( 'first', 'second', 'third' ) ); # ENUM字符串对象
INSERT INTO tmp9 values('first'),('second') ,('third') , (NULL);
SELECT * FROM tmp9;
SELECT enm, enm+0 FROM tmp9; # 查看索引值CREATE TABLE tmp11 ( s SET ( 'a', 'b', 'c', 'd' ) ); # 字符串对象
INSERT INTO tmp11 values('a'),( 'a,b,a'),('c,a,d');
SELECT * FROM tmp11;
INSERT INTO tmp11 values('a'),( 'a,b,a'),('c,a,d');
INSERT INTO tmp11 values ('a,x,b,y');CREATE TABLE tmp12( b BIT(4) ); # 位字段类型
INSERT INTO tmp12 VALUES(2), (9), (15);
SELECT BIN(b+0) FROM tmp12;CREATE TABLE tmp13 ( b BINARY ( 3 ), vb VARBINARY ( 30 ) );
INSERT INTO tmp13 VALUES(5,5);
SELECT length(b), length(vb) FROM tmp13;
SELECT b,vb,b = '5', b='5\0\0',vb='5',vb = '5\0\0' FROM tmp13;

5.2 如何选择数据类型

5.3 常见运算符介绍

CREATE TABLE tmp14 ( num INT );
INSERT INTO tmp14 VALUE (64);
SELECT num,num+10,num-3+5,num+5-3,num+36.5 FROM tmp14; # 对sum进行运算
SELECT * FROM TMP14;
SELECT num, num *2, num /2, num/3, num%3 FROM tmp14;
SELECT num, num / 0, num %0 FROM tmp14;
SELECT 1=0,'2'=2,2=2,'0.02'=0,'b'='b',(1+3)=(2+2),NULL=NULL;
SELECT 1<=>0, '2'<=>2, 2<=>2,'0.02'<=>0, 'b'<=>'b', (1+3) <=> (2+1),NULL<=>NULL; # 二者均为NULL返回1
SELECT 'good'<>'god', 1<>2, 4!=4, 5.5!=5, (1+3)!=(2+1),NULL<>NULL; # 不能用于空值判断
SELECT 'good'<='god', 1<=2, 4<=4, 5.5<=5, (1+3) <= (2+1),NULL<=NULL;
SELECT 'good'>='god', 1>=2, 4>=4, 5.5>=5, (1+3) >= (2+1),4>6,NULL>=NULL;SELECT 4 BETWEEN 4 AND 6, 4 BETWEEN 4 AND 6,12 BETWEEN 9 AND 10;
SELECT  'x' BETWEEN 'f' AND 'g', 'b' BETWEEN 'a' AND 'c';
SELECT least(2,0),least(20.0,3.0,100.5),least('a','c','b'),least(10,NULL);
SELECT greatest(2,0), greatest(20.0,3.0,100.5), greatest('a','c','b'),greatest(10,NULL);
SELECT 2 IN (1,3,5,'thks'), 'thks' IN (1,3,5,'thks');
SELECT NULL IN (1,3,5,'thks'),10 IN (1,3,NULL,'thks');SELECT 'stud' LIKE 'stud','stud' LIKE 'stu_','stud' LIKE '%d','stud' LIKE 't_ _ _','s' LIKE NULL,'630102' LIKE '%';
SELECT 'ssky' REGEXP '^s', 'ssky' REGEXP 'y$', 'ssky' REGEXP '.sky', 'ssky' REGEXP '[ab]';
SELECT NOT 10, NOT (1-1), NOT -5, NOT NULL, NOT 1 + 1;
SELECT  1 AND -1,1 AND 0,1 AND NULL, 0 AND NULL;
SELECT  1 && -1,1 && 0,1 && NULL, 0 && NULL;SELECT  1 OR -1 OR 0, 1 OR 2,1 OR NULL, 0 OR NULL, NULL OR NULL;
SELECT  1 || -1 || 0, 1 || 2,1 || NULL, 0 || NULL, NULL || NULL;

6.MySQL函数

6.2 数学函数

SELECT ABS(2), ABS(-3.3), ABS(-33);
SELECT PI()
SELECT SQRT(9), SQRT(40), SQRT(-49);
SELECT MOD(31,8),MOD(234, 10),MOD(45.5,6);
SELECT  CEIL(-3.35),CEILING(3.35);
SELECT FLOOR(-3.35), FLOOR(3.35);
SELECT RAND(),RAND(),RAND();
SELECT RAND(10),RAND(10),RAND(11);
SELECT LOG(3), LOG(-3);

6.3 字符串函数

SELECT CHAR_LENGTH('date'), CHAR_LENGTH('egg'); # HAR_LENGTH函数计算字符串字符个数
SELECT LENGTH('date'), LENGTH('egg');
SELECT CONCAT('My SQL', '5.6'),CONCAT('My',NULL, 'SQL');
SELECT CONCAT_WS('-', '1st','2nd', '3rd'), CONCAT_WS('*', '1st', NULL, '3rd');SELECT
INSERT ('Quest',2,4,'What') AS col1,
INSERT ('Quest',-1,4,'What') AS col2,
INSERT ('Quest',3,100,'Wh') AS col3;SELECT LOWER('BEAUTIFUL'),LCASE('Well');
SELECT UPPER('black'),UCASE('BLacK');
SELECT LOCATE('ball','football'),POSITION('ball'IN 'football'),INSTR ('football', 'ball'); # 查找字符串中指定子字符串的开始位置
SELECT REVERSE('abc'); # REVERSE函数反转字符串

6.5 条件判断函数

SELECT
IF( 12, 2, 3 ),
IF( 1 < 2, 'yes ', 'no' ),
IF( STRCMP( 'test', 'test1' ), 'no', 'yes' );SELECTIFNULL( 1, 2 ),IFNULL( NULL, 10 ),IFNULL( 1 / 0, 'wrong' );SELECT CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;
SELECT CASE WHEN 1< 0 THEN 'true' ELSE 'false' END;

7.查询数据

7.1 基本查询语句

CREATE TABLE fruits (f_id CHAR ( 10 ) NOT NULL,s_id INT NOT NULL,f_name CHAR ( 255 ) NOT NULL,f_price DECIMAL ( 8, 2 ) NOT NULL,
PRIMARY KEY ( f_id ));INSERT INTO fruits ( f_id, s_id, f_name, f_price ) # 插入练习数据
VALUES( 'a1', 101, 'apple', 5.2 ),( 'b1', 101, 'blackberry', 10.2 ),( 'bs1', 102, 'orange', 11.2 ),( 'bs2', 105, 'melon', 8.2 ),( 't1', 102, 'banana', 10.3 ),( 't2', 102, 'grape', 5.3 ),( 'o2', 103, 'coconut', 9.2 ),( 'c0', 101, 'cherry', 3.2 ),( 'a2', 103, 'apricot', 2.2 ),( 'l2', 104, 'lemon', 6.4 ),( 'b2', 104, 'berry', 7.6 ),( 'm1', 106, 'mango', 15.6 ),( 'm2', 105, 'xbabay', 2.6 ),( 't4', 107, 'xbababa', 3.6 ),( 'm3', 105, 'xxtt', 11.6 ),( 'b5', 107, 'xxxx', 3.6 );

7.2 单表查询

单表查询基本方式:查询所有字段、查询指定字段、查询指定记录、查询空值、多条件查询、查询结果排序

7.2.1 查询所有字段

SELECT * FROM FRUITS; # 检索所有字段的数据
SELECT f_name, f_price FROM fruits; # 查询某列所有数据

7.2.2 查询指定字段

SELECT f_name FROM fruits; # 查询单个指定字段
SELECT f_name, f_price FROM fruits; # 查询多个指定字段(关键字大写,数据列和表名小写)

7.2.3 查询指定记录

SELECT f_name, f_price
FROM fruits
WHERE f_price = 10.2; # 查询指定记录SELECT f_name, f_price, f_id
FROM fruits
WHERE f_price < 10;

7.2.4 带IN的关键字查询(查询指定范围内的条件记录)

SELECT s_id,f_name, f_price
FROM fruits
WHERE s_id IN (101,102,103) # 检索条件之间用逗号分开
ORDER BY f_name;SELECT s_id,f_name, f_price
FROM fruits
WHERE s_id NOT IN (101,102,103,104,105)
ORDER BY f_name;

7.2.5 带BETWEEN AND 的范围查询

SELECT f_name,f_price # 查询某个范围内的值
FROM fruits
WHERE f_price
BETWEEN 2.00 AND 10.20;SELECT f_name, f_price # 查询指定范围外的值
FROM fruits
WHERE f_price NOT BETWEEN 2.00 AND 10.20;

7.2.6 带LIKE的字符匹配查询

SELECT f_id, f_name # 查询以某个字母字符
FROM fruits
WHERE f_name LIKE 'b%';
SELECT f_id, f_name # 查询包含某个字符
FROM fruits
WHERE f_name LIKE '%g%';
SELECT f_name
FROM fruits
WHERE f_name LIKE 'b%y';

7.2.7 查询空值

CREATE TABLE customers
(c_id      int       NOT NULL AUTO_INCREMENT,c_name    char(50)  NOT NULL,c_address char(50)  NULL,c_city    char(50)  NULL,c_zip     char(10)  NULL,c_contact char(50)  NULL,c_email   char(255) NULL,PRIMARY KEY (c_id)
);INSERT INTO customers(c_id, c_name, c_address, c_city,
c_zip,  c_contact, c_email)
VALUES(10001, 'RedHook', '200 Street ', 'Tianjin', '300000',  'LiMing', 'LMing@163.com'),
(10002, 'Stars', '333 Fromage Lane','Dalian', '116000',  'Zhangbo','Jerry@hotmail.com'),
(10003, 'Netbhood', '1 Sunny Place', 'Qingdao',  '266000','LuoCong', NULL),
(10004, 'JOTO', '829 Riverside Drive', 'Haikou', '570000',  'YangShan', 'sam@hotmail.com');SELECT COUNT(*) AS cust_num  FROM customers;DESC customers
SELECT c_id, c_name,c_email FROM customers WHERE c_email IS NULL; # 查询字段为空数据
SELECT c_id, c_name,c_email FROM customers WHERE c_email IS NOT NULL; # 查询字段不为空数据

7.2.8 带AND的多条件查询

SELECT f_id,f_price,f_name FROM fruits WHERE s_id='101' AND f_price>=5; # AND操作符限定查询条件
SELECT f_id,f_price,f_name FROM fruits WHERE s_id IN ('101','102') AND f_price>=5 AND f_name='apple';

7.2.9 带OR的多条件查询

SELECT s_id,f_name,f_price FROM fruits WHERE s_id=101 OR s_id=102;
SELECT s_id,f_name,f_price FROM fruits WHERE s_id IN (101,102); # 使用IN操作符,可以实现更加复杂的嵌套查询

7.2.10 查询结果不重复

SELECT s_id FROM fruits;
SELECT DISTINCT s_id FROM fruits; # 使用DISTINCT去除重复记录

7.2.11 对查询结果进行排序

SELECT f_name FROM fruits ORDER BY f_name; # 使用OEDER BY对指定单列数据进行排序
SELECT f_name,f_price FROM fruits ORDER BY f_name,f_price; # 使用ORDER BY 对多列数据进行排序
SELECT f_name,f_price FROM fruits ORDER BY f_price DESC; # 指定方向排序
SELECT f_price,f_name FROM fruits ORDER BY f_price DESC,f_name;

7.2.12 分组查询

分组查询是对数据按照某个或多个字段分组,使用关键字GROUP BY关键字分组
GROUP BY 字段 [HAVING <条件表达式>]

SELECT s_id,COUNT(*) AS Total FROM fruits GROUP BY s_id;
# 分组过程使用COUNT函数,数据分为多个逻辑,并对每个组进行集合计算SELECT GROUP_CONCAT(s_id),GROUP_CONCAT(f_name) AS NAMES FROM fruits GROUP BY s_id; # GROUP_CONCAT()函数,将每个分组中各个字段值显示出来;HAVING在数据分组后进行过滤来选择分组,WHERE在分组前用来新选择记录;SELECT s_id, COUNT(*) AS Total
FROM fruits
GROUP BY s_id WITH ROLLUP; # 关键字WITH ROLLUP 在所有查询出的分组记录后增加以一条记录,记录查询出的所有记录总和,即统计记录数量;SELECT o_num,  SUM(quantity * item_price) AS orderTotal
FROM orderitems
GROUP BY o_num
HAVING SUM(quantity*item_price) >= 100
ORDER BY orderTotal; # GROUP BY 和 ORDER BY一起使用SELECT * From fruits LIMIT 4, 3; # 使用LIMIT子句,返回从第5个记录开始的,行数长度为3的记录

7.3 使用聚合函数查询

MySQL提供的查询功能可以对获取的数据进行分析和报告;常用函数功能包含:计算数据表中的行数总数,计算某个字段列下数据总和,计算最大值、最小值、平均值等。
MySQL聚合函数:AVG(平均值)、COUNT(某列行数)、MAX(某列最大值)、MIN(某列最小值)、SUM(某列值和)

7.3.1 COUNT()函数

COUNT(*)计算表中总的行数,不管某列有数值或为空值
COUNT(字段名)计算指定列下总的行数,计算时忽略空值行
SELECT COUNT(*) AS count_num FROM data_analysis; # 查询表中总的行数
SELECT COUNT(Occupation) AS Occupation_num FROM data_analysis; # 查询表中某个字段的总数
SELECT Term,COUNT(ListingNumber) FROM data_analysis GROUP BY Term; # 计算不同分组查询

7.3.2 SUM()函数

# SUM是一个求总和的函数,返回指定某列的总和
SELECT SUM(LoanOriginalAmount) AS amount_total FROM data_analysis WHERE ListingNumber = 213551; # WHERE指定查询值

7.3.3 AVG()函数

SELECT AVG(LoanOriginalAmount) AS AVG_LOAN FROM data_analysis    WHERE Term = 36 # 查看平均值
SELECT LoanOriginationQuarter, AVG(LoanOriginalAmount) FROM data_analysis GROUP BY LoanOriginationQuarter; # 查看平均值

7.3.4 MAX()函数

SELECT MAX(LoanOriginalAmount) AS MAX_LOAN FROM data_analysis GROUP BY Term;
SELECT MAX(ListingCreationDate) FROM data_analysis; # MAX()函数不仅适用于查找数值类型,也适用于字符类型

7.3.5 MIN()函数

SELECT MIN(LoanOriginalAmount) AS MIN_LOAN FROM data_analysis;

7.4.1 内连接查询

# 满足条件记录出现在结果关系中,两个或多个表中存在相同意义字段时,通过字段对不同表进行连接查询;完全限定表名(表名.列名)
# fruits表和suppliers表中都有相同数据类型的字段s_id,两个表通过s_id字段建立联系。接下来从fruits表中查询f_name、f_price字段,从suppliers表中查询s_id、s_name,SQL语句如下:SELECT suppliers.s_id, s_name,f_name, f_price # fruits中查询f_name,f_price;suppliers中查询s_id,s_name;
FROM fruits ,suppliers
WHERE fruits.s_id = suppliers.s_id;# fruits表和suppliers表之间,使用INNER JOIN语法进行内连接查询
SELECT suppliers.s_id, s_name,f_name, f_price # 涉及的查询只有一个表,这种查询成为自连接查询;物理上是一张表,逻辑上成为两张表;
FROM fruits INNER JOIN suppliers
ON fruits.s_id = suppliers.s_id;# 查询供应f_id= ‘a1’的水果供应商提供的其他水果种类
SELECT f1.f_id, f1.f_name
FROM fruits AS f1, fruits AS f2
WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';

7.4.2 外连接查询

 # 外连接中查询多个表中相关联的行;外连接包括左外连接或左连接和右外连接或右连接;# LEFT JOIN :返回包括左表中的所有记录和右表中连接字段相等的记录;# RIGHT JOIN :返回包括右表中的所有记录和左表中连接字段相等的记录;# LEFT JOIN左连接
# 左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。
CREATE TABLE orders
(o_num  int      NOT NULL AUTO_INCREMENT,o_date datetime NOT NULL,c_id   int      NOT NULL,PRIMARY KEY (o_num)
) ;INSERT INTO orders(o_num, o_date, c_id)
VALUES(30001, '2008-09-01', 10001),
(30002, '2008-09-12', 10003),
(30003, '2008-09-30', 10004),
(30004, '2008-10-03', 10005),
(30005, '2008-10-08', 10001);CREATE TABLE customers
(c_id      int       NOT NULL AUTO_INCREMENT,c_name    char(50)  NOT NULL,c_address char(50)  NULL,c_city    char(50)  NULL,c_zip     char(10)  NULL,c_contact char(50)  NULL,c_email   char(255) NULL,PRIMARY KEY (c_id)
);INSERT INTO customers(c_id, c_name, c_address, c_city,
c_zip,  c_contact, c_email)
VALUES(10001, 'RedHook', '200 Street ', 'Tianjin', '300000',  'LiMing', 'LMing@163.com'),
(10002, 'Stars', '333 Fromage Lane','Dalian', '116000',  'Zhangbo','Jerry@hotmail.com'),
(10003, 'Netbhood', '1 Sunny Place', 'Qingdao',  '266000','LuoCong', NULL),
(10004, 'JOTO', '829 Riverside Drive', 'Haikou', '570000',  'YangShan', 'sam@hotmail.com');SELECT COUNT(*) AS cust_num  FROM customers;DESC customers
DESC ordersSELECT customers.c_id, orders.o_num
FROM customers LEFT OUTER JOIN orders
ON customers.c_id = orders.c_id;# RIGHT JOIN右连接:右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,左表将返回空值。
# 在customers表和orders表中,查询所有订单,包括没有客户的订单,SQL语句如下:SELECT customers.c_id, orders.o_numFROM customers RIGHT OUTER JOIN ordersON customers.c_id = orders.c_id;

7.4.3 复合条件连接查询

# 复合条件连接查询是在连接查询的过程中,添加过滤条件,限制查询的结果,使查询结果更加精确;
# 在customers表和orders表中,使用INNER JOIN语法查询customers表中ID为10001的客户的订单信息,SQL语句如下:DESC customers
DESC ordersSELECT customers.c_id, orders.o_num
FROM customers INNER JOIN orders
ON customers.c_id = orders.c_id AND customers.c_id = 10001;# 在fruits表和suppliers表之间,使用INNER JOIN语法进行内连接查询,并对查询结果排序,SQL语句如下:
SELECT suppliers.s_id, s_name,f_name, f_price
FROM fruits INNER JOIN suppliers
ON fruits.s_id = suppliers.s_id
ORDER BY fruits.s_id;

7.5 子查询

# 子查询指的是一个查询语句嵌套在另一个查询语句内部的查询;
# SELECT 子句先计算子查询,子查询结果作为外层另一个查询的过滤条件;

7.5.1 带ANY、SOME关键字的子查询

CREATE table tbl1 ( num1 INT NOT NULL);
CREATE table tbl2 ( num2 INT NOT NULL);
INSERT INTO tbl1 values(1), (5), (13), (27); # 分别向两个表中插入数据:
INSERT INTO tbl2 values(6), (14), (11), (20);# ANY关键字接在一个比较操作符的后面,表示若与子查询返回的任何值比较为TRUE,则返回TRUE。
# 返回tbl2表的所有num2列,然后将tbl1中的num1的值与之进行比较,只要大于num2的任何1个值,即为符合查询条件的结果。SELECT num1 FROM tbl1 WHERE num1 > ANY (SELECT num2 FROM tbl2);

7.5.2 带ALL关键字的子查询

# 返回tbl1表中比tbl2表num2 列所有值都大的值,SQL语句如下:
SELECT num1 FROM tbl1 WHERE num1 > ALL (SELECT num2 FROM tbl2);

7.5.3 带EXISTS 关键字的子查询

# 查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中的记录,SQL语句如下:
SELECT * FROM fruits
WHERE EXISTS
(SELECT s_name FROM suppliers WHERE s_id = 107);# 查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中的f_price大于10.20的记录,SQL语句如下:SELECT * FROM fruitsWHERE f_price>10.20 AND EXISTS(SELECT s_name FROM suppliers WHERE s_id = 107);# 查询suppliers表中是否存在s_id=107的供应商,如果不存在则查询fruits表中的记录,SQL语句如下:SELECT * FROM fruitsWHERE NOT EXISTS(SELECT s_name FROM suppliers WHERE s_id = 107);
# 在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下:SELECT c_id FROM orders WHERE o_num IN(SELECT o_num  FROM orderitems WHERE f_id = 'c0');

7.5.4 带IN关键字的子查询

# 在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下:DESC orderitems
CREATE TABLE orderitems
(o_num      int          NOT NULL,o_item     int          NOT NULL,f_id       char(10)     NOT NULL,quantity   int          NOT NULL,item_price decimal(8,2) NOT NULL,PRIMARY KEY (o_num,o_item)
) ;
INSERT INTO orderitems(o_num, o_item, f_id, quantity, item_price)
VALUES(30001, 1, 'a1', 10, 5.2),
(30001, 2, 'b2', 3, 7.6),
(30001, 3, 'bs1', 5, 11.2),
(30001, 4, 'bs2', 15, 9.2),
(30002, 1, 'b3', 2, 20.0),
(30003, 1, 'c0', 100, 10),
(30004, 1, 'o2', 50, 2.50),
(30005, 1, 'c0', 5, 10),
(30005, 2, 'b1', 10, 8.99),
(30005, 3, 'a2', 10, 2.2),
(30005, 4, 'm1', 5, 14.99);# 在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下:
SELECT c_id FROM orders WHERE o_num IN
(SELECT o_num  FROM orderitems WHERE f_id = 'c0');
SELECT o_num  FROM orderitems WHERE f_id = 'c0';# 可以看到,符合条件的o_num列的值有两个:30003和30005,然后执行外层查询,在orders表中查询订单号等于30003或30005的客户c_id。嵌套子查询语句还可以写为如下形式,实现相同的效果:
SELECT c_id FROM orders WHERE o_num IN (30003, 30005);
# 与前一个例子类似,但是在SELECT语句中使用NOT IN关键字,SQL语句如下:
SELECT c_id FROM orders WHERE o_num NOT IN
(SELECT o_num  FROM orderitems WHERE f_id = 'c0');
SELECT * FROM orders;

7.5.5 带比较运算符的子查询

# 在suppliers表中查询s_city等于“Tianjin”的供应商s_id,然后在fruits表中查询所有该供应商提供的水果的种类,SQL语句如下:
DESC fruits
SELECT s_id, f_name FROM fruits
WHERE s_id =
(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin');SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin'
SELECT suppliers.s_id FROM suppliers WHERE suppliers.s_city = 'Tianjin'
# 在suppliers表中查询s_city等于“Tianjin”的供应商s_id,然后在fruits表中查询所有非该供应商提供的水果的种类,SQL语句如下:
SELECT s_id, f_name FROM fruits
WHERE s_id <>
(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin');

7.6 合并查询结果

SELECT s_id, f_name, f_price # 查询所有价格小于9的水果的信息,查询s_id等于101和103所有的水果的信息,使用UNION连接查询结果
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);SELECT s_id, f_name, f_price # UNION将多个SELECT语句的结果组合成一个结果集合。可以分开查看每个SELECT语句的结果FROM fruitsWHERE f_price < 9.0;
SELECT s_id, f_name, f_priceFROM fruitsWHERE s_id IN(101,103);SELECT s_id, f_name, f_price # 使用UNION ALL的功能是不删除重复行
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);

7.7.1 为表取别名

SELECT * FROM orders AS or_1
WHERE or_1.c_id = 10004;SELECT c.c_id, o.o_numFROM customers AS c LEFT OUTER JOIN orders AS oON c.c_id = o.c_id;SELECT f1.f_id, f1.f_nameFROM fruits AS f1, fruits AS f2WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';

7.7.2 为字段取别名

SELECT f1.f_name AS fruit_name, f1.f_price AS fruit_priceFROM fruits AS f1WHERE f1.f_price < 8;SELECT CONCAT(TRIM(s_name) , ' (',  TRIM(s_city), ')')FROM suppliersORDER BY s_name;SELECT CONCAT(TRIM(s_name) , ' (', TRIM(s_city), ')')AS suppliers_titleFROM suppliersORDER BY s_name;

8.插入、更新与删除数据

8.1 插入数据

数据插入方式:插入完整记录、插入记录一部分、插入多条记录、插入另一个查询的结果

9.索引

9.1 索引简介

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可以提高数据库中特定数据的查询速度

9.1.1 索引的含义和特点

10.存储过程和函数

存储过程就是一条或多条SQL语句的集合,可以视为批文件,但其作用不限于批处理

10.1 创建存储过程和函数

存储程序可以分为存储过程和函数
MySQL中创建存储过程和函数使用的语句分别是:CREATE PROCEDURE和CREATE FUNCTION

10.1.1 创建存储过程

11.视图

数据库中的视图是一个虚拟表
视图包含一些列带有名称的行和列数据

11.1 视图概述

视图是一个或者多个表中导出的,视图的行为与表非常相似,但视图是一个虚拟表

11.1.1 视图的含义

16.性能优化

MySQL性能优化就是通过合理安排资源,调整系统参数使MySQL运行更快、更节省资源

16.2 优化查询

16.2.1 分析查询语句

EXPLAIN SELECT * FROM fruits WHERE f_name='apple';  /*分析未使用索引时的查询情况*/
CREATE INDEX index_name ON fruits(f_name);          /*创建索引*/
EXPLAIN SELECT * FROM fruits WHERE f_name='apple';  /*分析使用索引时的查询情况*/

全书配套代码合集

第1章 例题

CREATE TABLE students
(student_id INT UNSIGNED,name VARCHAR(30),sex CHAR(1),birth DATE,PRIMARY KEY (student_id)
);INSERT INTO students (student_id, name, sex, birth) VALUES (41048101, 'Lucy Green', '1', '1990-02-14');SELECT name FROM students WHERE student_id = 41048101;

第3章 例题

查看当前所有存在的数据库
SHOW databases;【例3.1】创建测试数据库test_db,
CREATE DATABASE test_db;【例3.2】查看创建好的数据库test_db的定义,
SHOW CREATE DATABASE test_db\G;【例3.3】删除测试数据库test_db,
DROP DATABASE test_db;查看存储引擎
SHOW ENGINES \G;

第4章 例题

【例4.1】创建员工表tb_emp1。
CREATE  DATABASE test_db;
USE test_db;
CREATE TABLE tb_emp1
(
id      INT(11),
name   VARCHAR(25),
deptId  INT(11),
salary  FLOAT
);
【例4.2】定义数据表tb_emp 2,其主键为id,SQL语句如下:
CREATE TABLE tb_emp2
(
id      INT(11) PRIMARY KEY,
name    VARCHAR(25),
deptId  INT(11),
salary  FLOAT
);
【例4.3】定义数据表tb_emp 3,其主键为id,SQL语句如下:
CREATE TABLE tb_emp3
(
id INT(11),
name VARCHAR(25),
deptId INT(11),
salary FLOAT,
PRIMARY KEY(id)
);
【例4.4】定义数据表tb_emp4,假设表中间没有主键id,为了唯一确定一个员工,可以把name、deptId联合起来做为主键,SQL语句如下:
CREATE TABLE tb_emp4(
name VARCHAR(25),
deptId INT(11),
salary FLOAT,
PRIMARY KEY(name,deptId)
);
【例4.5】定义数据表tb_emp5,并在tb_emp5表上创建外键约束。
创建一个部门表tb_dept1,SQL语句如下:
CREATE TABLE tb_dept1
(
id       INT(11) PRIMARY KEY,
name    VARCHAR(22)  NOT NULL,
location  VARCHAR(50)
);定义数据表tb_emp5,让它的键deptId作为外键关联到tb_dept1的主键id,SQL语句为:
CREATE TABLE tb_emp5
(
id      INT(11) PRIMARY KEY,
name   VARCHAR(25),
deptId  INT(11),
salary   FLOAT,
CONSTRAINT fk_emp_dept1 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
【例4.6】定义数据表tb_emp6,指定员工的名称不能为空,SQL语句如下:
CREATE TABLE tb_emp6
(
id     INT(11) PRIMARY KEY,
name   VARCHAR(25) NOT NULL,
deptId  INT(11),
salary  FLOAT
);
【例4.7】定义数据表tb_dept2,指定部门的名称唯一,SQL语句如下:
CREATE TABLE tb_dept2
(
id      INT(11) PRIMARY KEY,
name    VARCHAR(22) UNIQUE,
location  VARCHAR(50)
);
【例4.8】定义数据表tb_dept3,指定部门的名称唯一,SQL语句如下:
CREATE TABLE tb_dept3
(
id      INT(11) PRIMARY KEY,
name    VARCHAR(22),
location  VARCHAR(50),
CONSTRAINT STH UNIQUE(name)
);
【例4.9】定义数据表tb_emp7,指定员工的部门编号默认为1111,SQL语句如下:
CREATE TABLE tb_emp7
(
id      INT(11) PRIMARY KEY,
name   VARCHAR(25) NOT NULL,
deptId  INT(11) DEFAULT 1111,
salary  FLOAT
);
【例4.10】定义数据表tb_emp8,指定员工的编号自动递增,SQL语句如下:
CREATE TABLE tb_emp8
(
id      INT(11) PRIMARY KEY AUTO_INCREMENT,
name   VARCHAR(25) NOT NULL,
deptId  INT(11),
salary  FLOAT
);
【例4.11】分别使用DESCRIBE和DESC查看表tb_dept1和表tb_emp1的表结构。
查看tb_dept1表结构,SQL语句如下:
DESCRIBE tb_dept1;
查看tb_emp1表结构,SQL语句如下:DESC tb_emp1;【例4.12】使用SHOW CREATE TABLE查看表tb_emp1的详细信息,SQL语句如下:SHOW CREATE TABLE tb_emp1;
使用参数’\G’之后的结果如下:SHOW CREATE TABLE tb_emp1\G【例4.13】将数据表tb_dept3改名为tb_deptment3。
ALTER TABLE tb_dept3 RENAME tb_deptment3;例4.14】将数据表tb_dept1中name字段的数据类型由VARCHAR(22)修改成VARCHAR(30)。
执行修改表名操作之前,使用DESC查看tb_dept表结构,结果如下:DESC tb_dept1;
ALTER TABLE tb_dept1 MODIFY name VARCHAR(30);【例4.15】将数据表tb_dept1中的location字段名称改为loc,数据类型保持不变,SQL语句如下:
ALTER TABLE tb_dept1 CHANGE location loc VARCHAR(50);【例4.16】 将数据表tb_dept1中的loc字段名称改为location,同时将数据类型变为VARCHAR(60),SQL语句如下:
ALTER TABLE tb_dept1CHANGE loc location VARCHAR(60);【例4.17】在数据表tb_dept1中添加一个没有完整性约束的INT类型的字段managerId(部门经理编号),SQL语句如下:
ALTER TABLE tb_dept1 ADD managerId INT(10);【例4.18】在数据表tb_dept1中添加一个不能为空的VARCHAR(12)类型的字段column1,SQL语句如下:
ALTER TABLE tb_dept1 ADD column1 VARCHAR(12) not null;【例4.19】在数据表tb_dept1中添加一个INT类型的字段column2,SQL语句如下:
ALTER TABLE tb_dept 1ADD column2 INT(11) FIRST;【例4.20】在数据表tb_dept1中name列后添加一个INT类型的字段column3,SQL语句如下:
ALTER TABLE tb_dept1 ADD column3 INT(11) AFTER name;【例4.21】删除数据表tb_dept1表中的column2字段。
ALTER TABLE tb_dept1 DROP column2;【例4.22】将数据表tb_dept中的column1字段修改为表的第一个字段,SQL语句如下:
ALTER TABLE tb_dept1 MODIFY column1 VARCHAR(12) FIRST;
【例4.23】将数据表tb_dept1中的column1字段插入到location字段后面,SQL语句如下:
ALTER TABLE tb_dept1 MODIFY column1 VARCHAR(12) AFTER location;
【例4.24】将数据表tb_deptment3的存储引擎修改为MyISAM。
在修改存储引擎之前,先使用SHOW CREATE TABLE查看表tb_deptment3当前的存储引擎,结果如下。SHOW CREATE TABLE tb_deptment3 \GALTER TABLE tb_deptment3 ENGINE=MyISAM;SHOW CREATE TABLE tb_deptment3 \G
【例4.25】删除数据表tb_emp9中的外键约束。
首先创建表tb_emp9,创建外键deptId关联tb_dept1表的主键id,SQL语句如下:
CREATE TABLE tb_emp9
(
id      INT(11) PRIMARY KEY,
name   VARCHAR(25),
deptId  INT(11),
salary   FLOAT,
CONSTRAINT fk_emp_dept  FOREIGN KEY (deptId) REFERENCES tb_dept1(id)
);
使用SHOW CREATE TABLE查看表tb_emp9的结构,结果如下:SHOW CREATE TABLE tb_emp9 \G
ALTER TABLE tb_emp9 DROP FOREIGN KEY fk_emp_dept;SHOW CREATE TABLE tb_emp9 \G
【例4.26】删除数据表tb_dept2,SQL语句如下:
DROP TABLE IF EXISTS tb_dept2;
在数据库中创建两个关联表,首先,创建表tb_dept2,SQL语句如下:
CREATE TABLE tb_dept2
(
id       INT(11) PRIMARY KEY,
name    VARCHAR(22),
location  VARCHAR(50)
);
接下来创建表tb_emp,SQL语句如下:
CREATE TABLE tb_emp
(
id       INT(11) PRIMARY KEY,
name    VARCHAR(25),
deptId   INT(11),
salary   FLOAT,
CONSTRAINT fk_emp_dept  FOREIGN KEY (deptId) REFERENCES tb_dept2(id)
);
使用SHOW CREATE TABLE命令查看表tb_emp的外键约束,结果如下:SHOW CREATE TABLE tb_emp\G
【例4.27】删除被数据表tb_emp关联的数据表tb_dept2。DROP TABLE tb_dept2;
ALTER TABLE tb_emp DROP FOREIGN KEY fk_emp_dept;
DROP TABLE tb_dept2;show tables;

第5章 例题

【例5.1】创建表tmp1,其中字段x、y、z、m、n数据类型依次为TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,SQL语句如下:
CREATE TABLE tmp1 ( x TINYINT,  y SMALLINT,  z MEDIUMINT,  m INT,  n BIGINT );DESC tmp1;
【例5.2】创建表tmp2,其中字段x、y、z数据类型依次为FLOAT(5,1)、DOUBLE(5,1)和DECIMAL(5,1),向表中插入数据5.12、5.15和5.123,SQL语句如下:
CREATE TABLE tmp2 ( x FLOAT(5,1),  y DOUBLE(5,1),  z DECIMAL(5,1) );
向表中插入数据:
INSERT INTO tmp2 VALUES(5.12, 5.15, 5.123);
SHOW WARNINGS;【例5.3】创建数据表tmp3,定义数据类型为YEAR的字段y,向表中插入值2010,’2010’,’2166’,SQL语句如下:
首先创建表tmp3:
CREATE TABLE tmp3(  y YEAR );
向表中插入数据:
INSERT INTO tmp3 values(2010),('2010');
再次向表中插入数据:
INSERT INTO tmp3 values ('2166');
SHOW WARNINGS;
SELECT * FROM tmp3;
【例5.4】向tmp3表中y字段插入2位字符串表示的YEAR值,分别为’0’、’00’、’77’和’10’,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp3;
向表中插入数据:
INSERT INTO tmp3 values('0'),('00'),('77'),('10');
查看结果:
SELECT * FROM tmp3;
【例5.5】向tmp3表中y字段插入2位数字表示表示的YEAR值,分别为0、78和11,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp3;
向表中插入数据:
INSERT INTO tmp3 values(0),(78),(11);
查看结果:
SELECT * FROM tmp3;
【例5.6】 创建数据表tmp4,定义数据类型为TIME的字段t,向表中插入值’10:05:05’,’23:23’,’2 10:10’,’3 02’,’10’,SQL语句如下:
首先创建表tmp4,
CREATE TABLE tmp4( t TIME );
向表中插入数据:
INSERT INTO tmp4 values('10:05:05 '), ('23:23'), ('2 10:10'), ('3 02'),('10');
查看结果:
SELECT * FROM tmp4;
【例5.7】向表tmp4中插入值’101112’,111213,’0’,107010,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp4;
向表中插入数据:
INSERT INTO tmp4 values('101112'),(111213),( '0');
再向表中插入数据:
INSERT INTO tmp4 values ( 107010);
show warnings;
【例5.8】向tmp4表中插入系统当前时间,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp4;
向表中插入数据:
INSERT INTO tmp4 values (CURRENT_TIME) ,(NOW());
查看结果:
SELECT * FROM tmp4;
【例5.9】创建数据表tmp5,定义数据类型为DATE的字段d,向表中插入“YYYY-MM-DD”和“YYYYMMDD”字符串格式日期,SQL语句如下:
首先创建表tmp5:
CREATE TABLE tmp5(d DATE);
Query OK, 0 rows affected (0.02 sec)
向表中插入“YYYY-MM-DD”和“YYYYMMDD”格式日期:
INSERT INTO tmp5 values('1998-08-08'),('19980808'),('20101010');
查看插入结果:
SELECT * FROM tmp5;
【例5.10】向tmp5表中插入“YY-MM-DD”和“YYMMDD”字符串格式日期,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp5;
向表中插入“YY-MM-DD”和“YYMMDD”格式日期:
INSERT INTO tmp5 values ('99-09-09'),( '990909'), ('000101') ,('111111');
查看插入结果:
SELECT * FROM tmp5;
【例5.11】向tmp5表中插入YY-MM-DD和YYMMDD数字格式日期,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp5;
向表中插入YY-MM-DD和YYMMDD数字格式日期:
INSERT INTO tmp5 values (99-09-09),(990909), ( 000101) ,( 111111);
查看插入结果:
SELECT * FROM tmp5;
【例5.12】向tmp5表中插入系统当前日期,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp5;
向表中插入系统当前日期:
INSERT INTO tmp5 values( CURRENT_DATE() ),( NOW() );
查看插入结果:
SELECT * FROM tmp5;
例5.13】创建数据表tmp6,定义数据类型为DATETIME的字段dt,向表中插入“YYYY-MM-DD HH:MM:SS”和“YYYYMMDDHHMMSS”字符串格式日期和时间值,SQL语句如下:
首先创建表tmp6:
CREATE TABLE tmp6(  dt DATETIME );
向表中插入“YYYY-MM-DD HH:MM:SS”和“YYYYMMDDHHMMSS”格式日期:
INSERT INTO tmp6 values('1998-08-08 08:08:08'),('19980808080808'),('20101010101010');
查看插入结果:
SELECT * FROM tmp6;
【例5.14】向tmp6表中插入“YY-MM-DD HH:MM:SS”和“YYMMDDHHMMSS”字符串格式日期和时间值,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp6;
向表中插入“YY-MM-DD HH:MM:SS”和“YYMMDDHHMMSS”格式日期:
INSERT INTO tmp6 values('99-09-09 09:09:09'),('990909090909'),('101010101010');
查看插入结果:
SELECT * FROM tmp6;
【例5.15】向tmp6表中插入YYYYMMDDHHMMSS 和YYMMDDHHMMSS数字格式日期和时间值,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp6;
向表中插入YYYYMMDDHHMMSS和YYMMDDHHMMSS数字格式日期和时间:
INSERT INTO tmp6 values(19990909090909), (101010101010);
查看插入结果:
SELECT * FROM tmp6;
【例5.16】向tmp6表中插入系统当前日期和时间值,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp6;
向表中插入系统当前日期:
INSERT INTO tmp6 values( NOW() );
查看插入结果:
SELECT * FROM tmp6;
【例 5.17】创建数据表tmp7,定义数据类型为TIMESTAMP的字段ts,向表中插入值’19950101010101’,’950505050505’,’1996-02-02 02:02:02’,’97@03@03 03@03@03’,121212121212,NOW(),SQL语句如下:
CREATE TABLE tmp7( ts TIMESTAMP);
向表中插入数据:
INSERT INTO tmp7 values ('19950101010101'),
('950505050505'),
('1996-02-02 02:02:02'),
('97@03@03 03@03@03'),
(121212121212),
( NOW() );
查看插入结果:
SELECT * FROM tmp7;【例5.18】向tmp7表中插入当前日期,查看插入值,更改时区为东10区,再次查看插入值,SQL语句如下:
首先删除表中的数据:
DELETE FROM tmp7;
向表中插入系统当前日期:
INSERT INTO tmp7 values( NOW() );
查看当前时区下日期值:
SELECT * FROM tmp7;
set time_zone='+10:00';
SELECT * FROM tmp7;【例5.19】下面将不同字符串保存到CHAR(4)和VARCHAR(4)列,说明CHAR和VARCHAR之间的差别,【例5.20】创建tmp8表,定义字段ch和vch数据类型依次为CHAR(4)、VARCHAR(4)向表中插入数据“ab  ”,SQL语句如下:创建表tmp8:
CREATE TABLE tmp8(
ch  CHAR(4),  vch  VARCHAR(4)
);输入数据:
INSERT INTO tmp8 VALUES('ab  ', 'ab  ');
查询结果:
SELECT concat('(', ch, ')'), concat('(',vch,')') FROM tmp8;例5.21】创建表tmp9,定义ENUM类型的列enm('first','second','third'),查看列成员的索引值,SQL语句如下:
首先,创建tmp9表:
CREATE TABLE tmp9( enm ENUM('first','second','third') );
插入各个列值:
INSERT INTO tmp9 values('first'),('second') ,('third') , (NULL);
查看索引值:
SELECT enm, enm+0 FROM tmp9;【例5.22】创建表tmp10,定义INT类型的soc字段,ENUM类型的字段level,列表值为('excellent','good', 'bad'),向表tmp10中插入数据’good’,1,2,3,’best’,SQL语句如下:
首先,创建数据表:
CREATE TABLE tmp10 (soc INT, level enum('excellent', 'good','bad') );
插入数据:
INSERT INTO tmp10 values(70,'good'), (90,1),(75,2),(50,3);
再次插入数据:
INSERT INTO tmp10 values (100,'best');
ERROR 1265 (01000): Data truncated for column 'level' at row 1
这里系统提示错误信息,可以看到,由于字符串值“best”不在ENUM列表中,所以对数据进行了阻止插入操作,查询结果如下:
SELECT * FROM tmp10;【例5.23】创建表tmp11,定义SET类型的字段s,取值列表为('a', 'b', 'c', 'd'),插入数据('a'),('a,b,a'),('c,a,d'),('a,x,b,y'),SQL语句如下:
首先创建表tmp11:
CREATE TABLE tmp11 ( s SET('a', 'b', 'c', 'd'));
插入数据:
INSERT INTO tmp11 values('a'),( 'a,b,a'),('c,a,d');
再次插入数据:
INSERT INTO tmp11 values ('a,x,b,y');
ERROR 1265 (01000): Data truncated for column 's' at row 1
由于插入了SET列不支持的值,因此MySQL给出错误提示。
查看结果:
SELECT * FROM tmp11;例5.24】创建表tmp12,定义BIT(4)类型的字段b,向表中插入数据2、9、15、16。
首先创建表tmp12,SQL语句如下:
CREATE TABLE tmp12( b BIT(4) );
插入数据:
INSERT INTO tmp12 VALUES(2), (9), (15);
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings:1
查询插入结果:
SELECT BIN(b+0) FROM tmp12;【例5.25】创建表tmp13,定义BINARY(3)类型的字段b和VARBINARY(3)类型的字段vb,并向表中插入数据’5’,比较两个字段的存储空间。
首先创建表tmp13,输入SQL语句如下:
CREATE TABLE tmp13(
b binary(3),  vb varbinary(30)
);
插入数据:
INSERT INTO tmp13 VALUES(5,5);
查看两个字段存储数据的长度:
SELECT length(b), length(vb) FROM tmp13;
SELECT b,vb,b = '5', b='5\0\0',vb='5',vb = '5\0\0' FROM tmp13;例5.26】创建表tmp14,定义数据类型为INT的字段num,插入值64,对num值进行算术运算:
首先创建表tmp14,输入语句如下:
CREATE TABLE tmp14 ( num INT);
向字段num插入数据64:
INSERT INTO tmp14 value(64);
接下来,对num值进行加法和减法运算:
SELECT num, num+10, num-3+5, num+5-3, num+36.5 FROM tmp14;例5.27】对tmp14表中的num进行乘法、除法运算。
SELECT num, num *2, num /2, num/3, num%3 FROM tmp14;【例5.28】用0除num。
SELECT num, num / 0, num %0 FROM tmp14;例5.29】使用’=’进行相等判断,SQL语句如下:
SELECT 1=0, '2'=2, 2=2,'0.02'=0, 'b'='b', (1+3) = (2+2),NULL=NULL;例5.30】使用’<=>’进行相等的判断,SQL语句如下:
SELECT 1<=>0, '2'<=>2, 2<=>2,'0.02'<=>0, 'b'<=>'b', (1+3) <=> (2+1),NULL<=>NULL;例5.31】使用’<>’和’!=’进行不相等的判断,SQL语句如下:例5.32】使用’<=’进行比较判断,SQL语句如下:
SELECT 'good'<='god', 1<=2, 4<=4, 5.5<=5, (1+3) <= (2+1),NULL<=NULL;例5.33】使用’<’进行比较判断,SQL语句如下:
SELECT 'good'<'god', 1<2, 4<4, 5.5<5, (1+3) < (2+1),NULL<NULL;例5.34】使用’>=’进行比较判断,SQL语句如下:
SELECT 'good'>='god', 1>=2, 4>=4, 5.5>=5, (1+3) >= (2+1),NULL>=NULL;
【例5.35】使用’>’进行比较判断,SQL语句如下:
SELECT 'good'>'god', 1>2, 4>4, 5.5>5, (1+3) > (2+1),NULL>NULL;【例5.36】使用IS NULL、ISNULL和IS NOT NULL判断NULL值和非NULL值,SQL语句如下:
SELECT NULL IS NULL, ISNULL(NULL),ISNULL(10), 10 IS NOT NULL;例5.37】使用BETWEEN AND 进行值区间判断,输入SQL语句如下:
SELECT 4 BETWEEN 4 AND 6, 4 BETWEEN 4 AND 6,12 BETWEEN 9 AND 10;
SELECT  'x' BETWEEN 'f' AND 'g', 'b' BETWEEN 'a' AND 'c';【例5.38】使用LEAST运算符进行大小判断,SQL语句如下:
SELECT least(2,0), least(20.0,3.0,100.5), least('a','c','b'),least(10,NULL);【例5.39】使用GREATEST运算符进行大小判断,SQL语句如下:
SELECT greatest(2,0), greatest(20.0,3.0,100.5), greatest('a','c','b'),greatest(10,NULL);【例5.40】使用IN、NOT IN运算符进行判断,SQL语句如下:
SELECT 2 IN (1,3,5,'thks'), 'thks' IN (1,3,5,'thks');【例5.41】存在NULL值时的IN查询,SQL语句如下:
SELECT NULL IN (1,3,5,'thks'),10 IN (1,3,NULL,'thks');【例5.42】使用运算符LIKE进行字符串匹配运算,SQL语句如下:
SELECT 'stud' LIKE 'stud', 'stud' LIKE 'stu_','stud' LIKE '%d','stud' LIKE 't_ _ _', 's' LIKE NULL;【例5.43】使用运算符REGEXP进行字符串匹配运算,SQL语句如下:
SELECT 'ssky' REGEXP '^s', 'ssky' REGEXP 'y$', 'ssky' REGEXP '.sky', 'ssky' REGEXP '[ab]';【例5.44】分别使用非运算符“NOT”和“!”进行逻辑判断,SQL语句如下:SELECT NOT 10, NOT (1-1), NOT -5, NOT NULL, NOT 1 + 1;SELECT !10, !(1-1), !-5, ! NULL, ! 1 + 1;【例5.45】分别使用与运算符“AND”和“&&”进行逻辑判断,SQL语句如下:SELECT  1 AND -1,1 AND 0,1 AND NULL, 0 AND NULL;SELECT  1 && -1,1 && 0,1 && NULL, 0 && NULL;【例5.46】分别使用或运算符“OR”和“||”进行逻辑判断,SQL语句如下:SELECT  1 OR -1 OR 0, 1 OR 2,1 OR NULL, 0 OR NULL, NULL OR NULL;SELECT  1 || -1 || 0, 1 || 2,1 || NULL, 0 || NULL, NULL || NULL;
【例5.47】使用异或运算符“XOR”进行逻辑判断,SQL语句如下:
SELECT 1 XOR 1, 0 XOR 0, 1 XOR 0, 1 XOR NULL, 1 XOR 1 XOR 1;
执行上面的语句,结果如下。SELECT 1 XOR 1, 0 XOR 0, 1 XOR 0, 1 XOR NULL, 1 XOR 1 XOR 1;【例5.48】使用位或运算符进行运算,SQL语句如下:SELECT 10 | 15, 9 | 4 | 2;【例5.49】使用位与运算符进行运算,SQL语句如下:SELECT 10 & 15, 9 &4& 2;
【例5.50】使用位异或运算符进行运算,SQL语句如下:SELECT 10 ^ 15, 1 ^0, 1 ^ 1;
【例5.51】使用位左移运算符进行运算,SQL语句如下:SELECT 1<<2, 4<<2;
【例5.52】使用位右移运算符进行运算,SQL语句如下:SELECT 1>>1, 16>>2;
【例5.53】使用位取反运算符进行运算,SQL语句如下:SELECT 5 & ~1;

第6章 例题

【例6.1】求2,-3.3和-33的绝对值,输入语句如下:
SELECT ABS(2), ABS(-3.3), ABS(-33);【例6.2】返回圆周率值,输入语句如下:SELECT pi();【例6.3】求9,40和-49的二次平方根,输入语句如下:SELECT SQRT(9), SQRT(40), SQRT(-49);【例6.4】对MOD(31,8),MOD(234, 10),MOD(45.5,6)进行求余运算,输入语句如下:SELECT MOD(31,8),MOD(234, 10),MOD(45.5,6);【例6.5】使用CEILING函数返回最小整数,输入语句如下:SELECT  CEIL(-3.35),CEILING(3.35);【例6.6】使用FLOOR函数返回最大整数,输入语句如下:SELECT FLOOR(-3.35), FLOOR(3.35);【例6.7】使用RAND()函数产生随机数,输入语句如下:SELECT RAND(),RAND(),RAND();【例6.8】使用RAND(x)函数产生随机数,输入语句如下:SELECT RAND(10),RAND(10),RAND(11);【例6.9】使用ROUND(x)函数对操作数进行四舍五入操作,输入语句如下: SELECT ROUND(-1.14),ROUND(-1.67), ROUND(1.14),ROUND(1.66);
【例6.10】使用ROUND(x,y)函数对操作数进行四舍五入操作,结果保留小数点后面指定y位,输入语句如下:SELECT ROUND(1.38, 1), ROUND(1.38, 0), ROUND(232.38, -1), round(232.38,-2);
【例6.11】使用TRUNCATE(x,y)函数对操作数进行四舍五入操作,结果保留小数点后面指定y位,输入语句如下:SELECT TRUNCATE(1.31,1), TRUNCATE(1.99,1), TRUNCATE(1.99,0), TRUNCATE(19.99,-1);
【例6.12】使用SIGN函数返回参数的符号,输入语句如下:SELECT SIGN(-21),SIGN(0), SIGN(21);
【例6.13】使用POW和POWER函数进行乘方运算,输入语句如下:SELECT POW(2,2), POWER(2,2),POW(2,-2), POWER(2,-2);【例6.14】使用EXP函数计算e的乘方,输入语句如下:SELECT EXP(3),EXP(-3),EXP(0);【例6.15】使用LOG(x)函数计算自然对数,输入语句如下:SELECT LOG(3), LOG(-3);【例6.16】使用LOG10计算以10为基数的对数,输入语句如下:SELECT LOG10(2), LOG10(100), LOG10(-100);
【例6.17】使用RADIANS将角度转换为弧度,输入语句如下:SELECT RADIANS(90),RADIANS(180);
【例6.18】使用DEGREES将弧度转换为角度,输入语句如下:SELECT DEGREES(PI()), DEGREES(PI() / 2);
【例6.19】使用SIN函数计算正弦值,输入语句如下:SELECT SIN(1), ROUND(SIN(PI()));
【例6.20】使用ASIN函数计算反正弦值,输入语句如下:SELECT ASIN(0.8414709848078965), ASIN(3);
【例6.21】使用COS函数计算余弦值,输入语句如下:SELECT COS(0),COS(PI()),COS(1);
【例6.22】使用ACOS函数计算反余弦值,输入语句如下:SELECT ACOS(1),ACOS(0), ROUND(ACOS(0.5403023058681398));
【例6.23】使用TAN函数计算正切值,输入语句如下:SELECT TAN(0.3), ROUND(TAN(PI()/4));
【例6.24】使用ATAN函数计算反正切值,输入语句如下:SELECT ATAN(0.30933624960962325), ATAN(1);
【例6.25】使用COT()函数计算余切值,输入语句如下,SELECT COT(0.3), 1/TAN(0.3),COT(PI() / 4);【例6.26】使用CHAR_LENGTH函数计算字符串字符个数,输入语句如下:SELECT CHAR_LENGTH('date'), CHAR_LENGTH('egg');【例6.27】使用LENGTH函数计算字符串长度,输入语句如下:SELECT LENGTH('date'), LENGTH('egg');【例6.28】使用CONCAT函数连接字符串,输入语句如下:SELECT CONCAT('My SQL', '5.6'),CONCAT('My',NULL, 'SQL');【例6.29】使用CONCAT_WS函数连接带分隔符的字符串,输入语句如下:SELECT CONCAT_WS('-', '1st','2nd', '3rd'), CONCAT_WS('*', '1st', NULL, '3rd');【例6.30】使用INSERT函数进行字符串替代操作,输入语句如下:SELECT INSERT('Quest', 2, 4, 'What') AS col1,
INSERT('Quest', -1, 4, 'What') AS col2,
INSERT('Quest', 3, 100, 'Wh') AS col3;【例6.31】使用LOWER函数或者LCASE函数将字符串中所有字母字符转换为小写,输入语句如下:SELECT LOWER('BEAUTIFUL'), LCASE('Well');
【例6.32】使用UPPER函数或者UCASE函数将字符串中所有字母字符转换为大写,输入语句如下:SELECT UPPER('black'), UCASE('BLacK');【例6.33】使用LEFT函数返回字符串中左边的字符,输入语句如下:SELECT LEFT('football', 5);
【例6.34】使用RIGHT函数返回字符串中右边的字符,输入语句如下:SELECT RIGHT('football', 4);
【例6.35】使用LPAD函数对字符串进行填充操作,输入语句如下:SELECT LPAD('hello',4,'??'), LPAD('hello',10,'??');
【例6.36】使用RPAD函数对字符串进行填充操作,输入语句如下:SELECT RPAD('hello',4,'?'), RPAD('hello',10,'?');
【例6.37】使用LTRIM函数删除字符串左边的空格,输入语句如下:SELECT '(  book  )',CONCAT('(',LTRIM('  book  '),')');
【例6.38】SELECT CONCAT( '(',  RTRIM ('  book  '), ')');SELECT '(  book  )',CONCAT('(', RTRIM ('  book  '),')');
【例6.39】SELECT CONCAT( '(',  TRIM('  book  ') , ')');SELECT '(  book  )',CONCAT('(', TRIM('  book  '),')');
【例6.40】使用TRIM(s1 FROM s)函数删除字符串中两端指定的字符,输入语句如下:SELECT TRIM('xy' FROM 'xyxboxyokxxyxy') ;
【例6.41】使用REPEAT函数重复生成相同的字符串,输入语句如下:SELECT REPEAT('MySQL', 3);
【例6.42】使用SPACE函数生成由空格组成的字符串,输入语句如下:SELECT CONCAT('(', SPACE(6), ')' );
【例6.43】使用REPLACE函数进行字符串替代操作,输入语句如下:SELECT REPLACE('xxx.mysql.com', 'x', 'w');
【例6.44】使用STRCMP函数比较字符串大小,输入语句如下:SELECT STRCMP('txt', 'txt2'),STRCMP('txt2', 'txt'), STRCMP('txt', 'txt');
【例6.45】使用SUBSTRING函数获取指定位置处的子字符串,输入语句如下:SELECT SUBSTRING('breakfast',5) AS col1, SUBSTRING('breakfast',5,3) AS col2,SUBSTRING('lunch', -3) AS col3,
SUBSTRING('lunch', -5, 3) AS col4;
【例6.46】使用MID()函数获取指定位置处的子字符串,输入语句如下:SELECT MID('breakfast',5) as col1,
MID('breakfast',5,3) as col2,
MID('lunch', -3) as col3,
MID('lunch', -5, 3) as col4;【例6.47】使用LOCATE,POSITION,INSTR函数查找字符串中指定子字符串的开始位置,输入语句如下:SELECT LOCATE('ball','football'),POSITION('ball'IN 'football'),INSTR ('football', 'ball');【例6.48】使用REVERSE函数反转字符串,输入语句如下:SELECT REVERSE('abc');【例6.49】使用ELT函数返回指定位置字符串,输入语句如下:SELECT ELT(3,'1st','2nd','3rd'), ELT(3,'net','os');
【例6.50】使用FIELD函数返回指定字符串第一次出现的位置,输入语句如下:SELECT FIELD('Hi', 'hihi', 'Hey', 'Hi', 'bas') as col1,FIELD('Hi', 'Hey', 'Lo', 'Hilo',  'foo') as col2;
【例6.51】使用FIND_IN_SET()函数返回子字符串在字符串列表中的位置,输入语句如下:SELECT FIND_IN_SET('Hi','hihi,Hey,Hi,bas');
【例6.52】使用MAKE_SET根据二进制位选取指定字符串,输入语句如下:SELECT  MAKE_SET(1,'a','b','c') as col1,MAKE_SET(1 | 4,'hello','nice','world') as col2,MAKE_SET(1 | 4,'hello','nice',NULL,'world') as col3,MAKE_SET(0,'a','b','c') as col4;【例6.53】使用日期函数获取系统当前日期,输入语句如下:SELECT CURDATE(),CURRENT_DATE(), CURDATE() + 0;【例6.54】使用时间函数获取系统当前时间,输入语句如下:SELECT CURTIME(),CURRENT_TIME(),CURTIME() + 0;【例6.55】使用日期时间函数获取当前系统日期和时间,输入语句如下:SELECT CURRENT_TIMESTAMP(),LOCALTIME(),NOW(),SYSDATE();【例6.56】使用UNIX_TIMESTAMP函数返回UNIX格式的时间戳,输入语句如下:SELECT UNIX_TIMESTAMP(), UNIX_TIMESTAMP(NOW()), NOW();
【例6.57】使用FROM_UNIXTIME函数将UNIX时间戳转换为普通格式时间,输入语句如下:SELECT FROM_UNIXTIME('1364098609');
【例6.58】使用UTC_DATE()函数返回当前UTC日期值,输入语句如下:SELECT UTC_DATE(), UTC_DATE() + 0;
【例6.59】使用UTC_TIME()函数返回当前UTC时间值,输入语句如下:SELECT UTC_TIME(), UTC_TIME() + 0;
【例6.60】使用MONTH()函数返回指定日期中的月份,输入语句如下:SELECT MONTH('2013-02-13');
【例6.61】使用MONTHNAME()函数返回指定日期中的月份的名称,输入语句如下:SELECT MONTHNAME('2013-02-13');
【例6.62】使用DAYNAME()函数返回指定日期的工作日名称,输入语句如下:SELECT DAYNAME('2013-02-13');
【例6.63】使用DAYOFWEEK()函数返回日期对应的周索引,输入语句如下:SELECT DAYOFWEEK('2011-02-13');
【例6.64】使用WEEKDAY()函数返回日期对应的工作日索引,输入语句如下:SELECT WEEKDAY('2011-02-13 22:23:00'), WEEKDAY('2011-07-01');
【例6.65】使用WEEK()函数查询指定日期是一年中的第几周,输入语句如下:SELECT WEEK('2011-02-20'),WEEK('2011-02-20',0), WEEK('2011-02-20',1);
【例6.66】使用WEEKOFYEAR()查询指定日期是一年中的第几周,输入语句如下:SELECT WEEK('2011-02-20',3), WEEKOFYEAR('2011-02-20');
【例6.67】使用DAYOFYEAR()函数返回指定日期在一年中的位置,输入语句如下:SELECT DAYOFYEAR('2011-02-20');
【例6.68】使用DAYOFYEAR()函数返回指定日期在一个月中的位置,输入语句如下:SELECT DAYOFMONTH('2011-02-20');
【例6.69】使用YEAR()函数返回指定日期对应的年份,输入语句如下:SELECT YEAR('11-02-03'),YEAR('96-02-03');
【例6.70】使用QUARTER()函数返回指定日期对应的季度,输入语句如下:SELECT QUARTER('11-04-01');
【例6.71】使用MINUTE()函数返回指定时间的分钟值,输入语句如下:SELECT MINUTE('11-02-03 10:10:03');
【例6.72】使用SECOND()函数返回指定时间的秒值,输入语句如下:SELECT SECOND('10:05:03');
【例6.73】使用EXTRACT函数提取日期或者时间值,输入语句如下:SELECT EXTRACT(YEAR FROM '2011-07-02') AS col1,EXTRACT(YEAR_MONTH FROM '2011-07-12 01:02:03') AS col2,EXTRACT(DAY_MINUTE FROM '2011-07-12 01:02:03') AS col3;
【例6.74】使用TIME_TO_SEC函数将时间值转换为秒值,输入语句如下:SELECT TIME_TO_SEC('23:23:00');
【例6.75】使用SEC_TO_TIME()函数将秒值转换为时间格式,输入语句如下:SELECT SEC_TO_TIME(2345),SEC_TO_TIME(2345)+0,TIME_TO_SEC('23:23:00'), SEC_TO_TIME(84180);【例6.76】使用DATE_ADD()和ADDDATE()函数执行日期加操作,输入语句如下:SELECT DATE_ADD('2010-12-31 23:59:59', INTERVAL 1 SECOND) AS col1,ADDDATE('2010-12-31 23:59:59', INTERVAL 1 SECOND) AS col2,DATE_ADD('2010-12-31 23:59:59', INTERVAL '1:1' MINUTE_SECOND) AS col3;【例6.77】使用DATE_SUB和SUBDATE函数执行日期减操作,输入语句如下:SELECT DATE_SUB('2011-01-02', INTERVAL 31 DAY) AS col1,SUBDATE('2011-01-02', INTERVAL 31 DAY) AS col2,DATE_SUB('2011-01-01 00:01:00',INTERVAL '0 0:1:1' DAY_SECOND) AS col3;【例6.78】使用ADDTIME进行时间加操作,输入语句如下:SELECT ADDTIME('2000-12-31 23:59:59','1:1:1'), ADDTIME('02:02:02', '02:00:00');【例6.79】使用SUBTIME()函数执行时间减操作,输入语句如下:SELECT SUBTIME('2000-12-31 23:59:59','1:1:1'), SUBTIME('02:02:02','02:00:00');【例6.80】使用DATEDIFF()函数计算两个日期之间的间隔天数,输入语句如下:SELECT DATEDIFF('2010-12-31 23:59:59','2010-12-30') AS col1,DATEDIFF('2010-11-30 23:59:59','2010-12-31') AS col2;【例6.81】使用DATE_FORMAT()函数格式化输出日期和时间值,输入语句如下:SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y') AS col1,DATE_FORMAT('1997-10-04 22:23:00','%D %y %a %d %m %b %j') AS col2;【例6.82】使用TIME_FORMAT()函数格式化输入时间值,输入语句如下:SELECT TIME_FORMAT('16:00:00', '%H %k %h %I %l');【例6.83】使用GET_FORMAT()函数显示不同格式化类型下的格式字符串,输入语句如下:SELECT GET_FORMAT(DATE,'EUR'), GET_FORMAT(DATE,'USA');【例6.84】在DATE_FORMAT()函数中,使用GET_FORMAT函数返回的显示格式字符串来显示指定的日期值,输入语句如下:SELECT DATE_FORMAT('2000-10-05 22:23:00', GET_FORMAT(DATE,'USA') );【例6.85】使用IF()函数进行条件判断,输入语句如下:SELECT IF(12,2,3),IF(1<2,'yes ','no'),IF(STRCMP('test','test1'),'no','yes');
【例6.86】使用IFNULL()函数进行条件判断,输入语句如下:SELECT IFNULL(1,2), IFNULL(NULL,10), IFNULL(1/0, 'wrong');
【例6.87】使用CASE value WHEN语句执行分支操作,输入语句如下:SELECT CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;
【例6.88】使用CASE WHEN语句执行分支操作,输入语句如下:SELECT CASE WHEN 1<0 THEN 'true' ELSE 'false' END;
【例6.89】查看当前MySQL版本号,输入语句如下:SELECT VERSION();
【例6.90】查看当前用户的连接数,输入语句如下:SELECT CONNECTION_ID();
【例6.91】使用SHOW PROCESSLIST命令输出当前用户的连接信息,输入语句如下:SHOW PROCESSLIST;
【例6.92】查看当前使用的数据库,输入语句如下:SELECT DATABASE(),SCHEMA();
【例6.93】获取当前登录用户名称,输入语句如下:SELECT USER(), CURRENT_USER(), SYSTEM_USER();
【例6.94】使用CHARSET()函数返回字符串使用的字符集,输入语句如下:SELECT CHARSET('abc'),CHARSET(CONVERT('abc' USING latin1)),CHARSET(VERSION());
【例6.95】使用COLLATION()函数返回字符串排列方式,输入语句如下:SELECT COLLATION('abc'),COLLATION(CONVERT('abc' USING utf8));
【例6.96】使用SELECT LAST_INSERT_ID查看最后一个自动生成的列值,执行过程如下:
1.一次插入一条记录
首先创建表worker,其Id字段带有AUTO_INCREMENT约束,输入语句如下:CREATE TABLE worker (Id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,Name VARCHAR(30));
分别单独向表worker中插入2条记录:INSERT INTO worker VALUES(NULL, 'jimy');INSERT INTO worker VALUES(NULL, 'Tom');SELECT * FROM worker;SELECT LAST_INSERT_ID();
2.一次同时插入多条记录
接下来,向表中插入多条记录,输入语句如下:INSERT INTO worker VALUES(NULL, 'Kevin'),(NULL,'Michal'),(NULL,'Nick');
查询已经插入的的记录,SELECT * FROM worker;SELECT LAST_INSERT_ID();
【例6.97】使用PASSWORD函数加密密码,输入语句如下:SELECT PASSWORD('newpwd');
【例6.98】使用MD5函数加密字符串,输入语句如下:SELECT MD5 ('mypwd');
【例6.99】使用ENCODE加密字符串,输入语句如下:SELECT ENCODE('secret','cry'), LENGTH(ENCODE('secret','cry'));
【例6.100】使用DECODE函数解密被ENCODE加密的字符串,输入语句如下:SELECT DECODE(ENCODE('secret','cry'),'cry');
【例6.101】使用FORMAT函数格式化数字,保留小数点位数为指定值,输入语句如下:SELECT FORMAT(12332.123456, 4), FORMAT(12332.1,4), FORMAT(12332.2,0);
【例6.102】使用CONV函数在不同进制数值之间转换,输入语句如下:SELECT CONV('a',16,2),CONV(15,10,2),CONV(15,10,8),CONV(15,10,16);
【例6.103】使用INET_ATON函数将字符串网络点地址转换为数值网络地址,输入语句如下:SELECT INET_ATON('209.207.224.40');
【例6.104】使用INET_NTOA函数将数值网络地址转换为字符串网络点地址,输入语句如下:SELECT INET_NTOA(3520061480);
【例6.105】使用加锁、解锁函数,输入语句如下:SELECT GET_LOCK('lock1',10) AS GetLock,IS_USED_LOCK('lock1') AS ISUsedLock,IS_FREE_LOCK('lock1') AS ISFreeLock,RELEASE_LOCK('lock1') AS ReleaseLock;
【例6.106】使用BENCHMARK重复执行指定函数。
首先,使用PASSWORD函数加密密码,输入语句如下:SELECT PASSWORD ( 'newpwd' );SELECT BENCHMARK( 500000, PASSWORD ('newpwd') );
【例6.107】使用CONVERT()函数改变字符串的默认字符集,输入语句如下:SELECT CHARSET('string'),  CHARSET(CONVERT('string' USING latin1));
【例6.108】使用CAST和CONVERT函数进行数据类型的转换,SQL语句如下:SELECT CAST(100 AS CHAR(2)), CONVERT('2010-10-01 12:12:12',TIME);

第7章 例题

CREATE TABLE fruits
(
f_id    char(10)        NOT NULL,
s_id    INT         NOT NULL,
f_name  char(255)   NOT NULL,
f_price decimal(8,2)    NOT NULL,
PRIMARY KEY(f_id)
);
为了演示如何使用SELECT语句,需要插入如下数据:INSERT INTO fruits (f_id, s_id, f_name, f_price)VALUES('a1', 101,'apple',5.2),('b1',101,'blackberry', 10.2),('bs1',102,'orange', 11.2),('bs2',105,'melon',8.2),('t1',102,'banana', 10.3),('t2',102,'grape', 5.3),('o2',103,'coconut', 9.2),('c0',101,'cherry', 3.2),('a2',103, 'apricot',2.2),('l2',104,'lemon', 6.4),('b2',104,'berry', 7.6),('m1',106,'mango', 15.6),('m2',105,'xbabay', 2.6),('t4',107,'xbababa', 3.6),('m3',105,'xxtt', 11.6),('b5',107,'xxxx', 3.6);
使用SELECT语句查询f_id字段的数据。SELECT f_id, f_name FROM fruits;
【例7.1】从fruits表中检索所有字段的数据,SQL语句如下:SELECT * FROM fruits;
【例7.2】查询fruits表中f_name列所有水果名称,SQL语句如下:
SELECT f_name FROM fruits;
【例7.3】例如,从fruits表中获取f_name和f_price两列,SQL语句如下:
SELECT f_name, f_price FROM fruits;
【例7.4】查询价格为10.2元的水果的名称,SQL语句如下:
SELECT f_name, f_price
FROM fruits
WHERE f_price = 10.2;
【例7.5】查找名称为“apple”的水果的价格,SQL语句如下:
SELECT f_name, f_price
FROM fruits
WHERE f_name = 'apple';
【例7.6】查询价格小于10的水果的名称,SQL语句如下:
SELECT f_name, f_price
FROM fruits
WHERE f_price < 10;【例7.7】s_id为101和102的记录,SQL语句如下:
SELECT s_id,f_name, f_price
FROM fruits
WHERE s_id IN (101,102)
ORDER BY f_name;【例7.8】查询所有s_id不等于101也不等于102的记录,SQL语句如下:
SELECT s_id,f_name, f_price
FROM fruits
WHERE s_id NOT IN (101,102)
ORDER BY f_name;【例7.9】查询价格在2.00元到10.20元之间的水果名称和价格,SQL语句如下:
SELECT f_name, f_price FROM fruits WHERE f_price BETWEEN 2.00 AND 10.20;
查询结果如下:SELECT f_name, f_priceFROM fruitsWHERE f_price BETWEEN 2.00 AND 10.20;
【例7.10】查询价格在2.00元到10.20元之外的水果名称和价格,SQL语句如下:
SELECT f_name, f_price
FROM fruits
WHERE f_price NOT BETWEEN 2.00 AND 10.20;【例7.11】查找所有以’b’字母开头的水果,SQL语句如下:
SELECT f_id, f_name
FROM fruits
WHERE f_name LIKE 'b%';
【例7.12】在fruits表中,查询f_name中包含字母’g’的记录,SQL语句如下:
SELECT f_id, f_name
FROM fruits
WHERE f_name LIKE '%g%';
【例7.13】查询以’b’开头,并以’y’结尾的水果的名称,SQL语句如下:
SELECT f_name
FROM fruits
WHERE f_name LIKE 'b%y';【例7.14】在fruits表中,查询以字母’y’结尾,且’y’前面只有4个字母的记录,SQL语句如下:
SELECT f_id, f_name FROM fruits WHERE f_name LIKE '----y';下面,在数据库中创建数据表customers,该表中包含了本章中需要用到的数据。
CREATE TABLE customers
(c_id      int       NOT NULL AUTO_INCREMENT,c_name    char(50)  NOT NULL,c_address char(50)  NULL,c_city    char(50)  NULL,c_zip     char(10)  NULL,c_contact char(50)  NULL,c_email   char(255) NULL,PRIMARY KEY (c_id)
);
为了演示需要插入数据,请读者插入执行以下语句。
INSERT INTO customers(c_id, c_name, c_address, c_city,
c_zip,  c_contact, c_email)
VALUES(10001, 'RedHook', '200 Street ', 'Tianjin', '300000',  'LiMing', 'LMing@163.com'),
(10002, 'Stars', '333 Fromage Lane','Dalian', '116000',  'Zhangbo','Jerry@hotmail.com'),
(10003, 'Netbhood', '1 Sunny Place', 'Qingdao',  '266000','LuoCong', NULL),
(10004, 'JOTO', '829 Riverside Drive', 'Haikou', '570000',  'YangShan', 'sam@hotmail.com');SELECT COUNT(*) AS cust_num  FROM customers;【例7.15】查询customers表中c_email为空的记录的c_id、c_name和c_email字段值,SQL语句如下:
SELECT c_id, c_name,c_email FROM customers WHERE c_email IS NULL;
查询结果如下:SELECT c_id, c_name,c_email FROM customers WHERE c_email IS NULL;【例7.16】查询customers表中c_email不为空的记录的c_id、c_name和c_email字段值,SQL语句如下:
SELECT c_id, c_name,c_email FROM customers WHERE c_email IS NOT NULL;【例7.17】在fruits表中查询s_id = 101,并且f_price大于等于5的水果价格和名称,SQL语句如下:
SELECT f_id, f_price, f_name FROM fruits WHERE s_id = '101' AND f_price >=5;【例7.18】在fruits表中查询s_id = 101或者102,且f_price大于5,并且f_name=‘apple’的水果价格和名称,SQL语句如下:SELECT f_id, f_price, f_name FROM fruits
WHERE s_id IN('101', '102') AND f_price >= 5 AND f_name = 'apple';【例7.19】查询s_id=101或者s_id=102的水果供应商的f_price和f_name,SQL语句如下:
SELECT s_id,f_name, f_price FROM fruits WHERE s_id = 101 OR s_id = 102;
查询结果如下:SELECT s_id,f_name, f_priceFROM fruitsWHERE s_id = 101 OR s_id = 102;【例7.20】查询s_id=101或者s_id=102的水果供应商的f_price和f_name,SQL语句如下:
SELECT s_id,f_name, f_price FROM fruits WHERE s_id IN(101,102);
查询结果如下:SELECT s_id,f_name, f_priceFROM fruitsWHERE s_id IN(101,102);【例7.21】查询fruits表中s_id字段的值,返回s_id字段值且不得重复,SQL语句如下:
SELECT DISTINCT s_id FROM fruits;【例7.22】查询fruits表的f_name字段值,并对其进行排序,SQL语句如下:SELECT f_name FROM fruits ORDER BY f_name;【例7.23】查询fruits表中的f_name和f_price字段,先按f_name排序,再按f_price排序,SQL语句如下:
SELECT f_name, f_price FROM fruits ORDER BY f_name, f_price;【例7.24】查询fruits表中的f_name和f_price字段,对结果按f_price降序方式排序,SQL语句如下:
SELECT f_name, f_price FROM fruits ORDER BY f_price DESC;
【例7.25】查询fruits表,先按f_price降序排序,再按f_name字段升序排序,SQL语句如下:
SELECT f_price, f_name FROM fruits ORDER BY f_price DESC, f_name;【例7.26】根据s_id对fruits表中的数据进行分组,SQL语句如下:
SELECT s_id, COUNT(*) AS Total FROM fruits GROUP BY s_id;【例7.27】根据s_id对fruits表中的数据进行分组,将每个供应商的水果名称显示出来,SQL语句如下:
SELECT s_id, GROUP_CONCAT(f_name) AS Names FROM fruits GROUP BY s_id;【例7.28】根据s_id对fruits表中的数据进行分组,并显示水果种类大于1的分组信息,SQL语句如下:
SELECT s_id, GROUP_CONCAT(f_name) AS Names
FROM fruits
GROUP BY s_id HAVING COUNT(f_name) > 1;【例7.29】根据s_id对fruits表中的数据进行分组,并显示记录数量,SQL语句如下:
SELECT s_id, COUNT(*) AS Total
FROM fruits
GROUP BY s_id WITH ROLLUP;【例7.30】根据s_id和f_name字段对fruits表中的数据进行分组, SQL语句如下,SELECT * FROM fruits group by s_id,f_name;为了演示效果,首先创建数据表,SQL语句如下:
CREATE TABLE orderitems
(o_num      int          NOT NULL,o_item     int          NOT NULL,f_id       char(10)     NOT NULL,quantity   int          NOT NULL,item_price decimal(8,2) NOT NULL,PRIMARY KEY (o_num,o_item)
) ;
然后插入演示数据。SQL语句如下:
INSERT INTO orderitems(o_num, o_item, f_id, quantity, item_price)
VALUES(30001, 1, 'a1', 10, 5.2),
(30001, 2, 'b2', 3, 7.6),
(30001, 3, 'bs1', 5, 11.2),
(30001, 4, 'bs2', 15, 9.2),
(30002, 1, 'b3', 2, 20.0),
(30003, 1, 'c0', 100, 10),
(30004, 1, 'o2', 50, 2.50),
(30005, 1, 'c0', 5, 10),
(30005, 2, 'b1', 10, 8.99),
(30005, 3, 'a2', 10, 2.2),
(30005, 4, 'm1', 5, 14.99);
【例7.31】查询订单价格大于100的订单号和总订单价格,SQL语句如下:
SELECT o_num,  SUM(quantity * item_price) AS orderTotal
FROM orderitems
GROUP BY o_num
HAVING SUM(quantity*item_price) >= 100;
可以看到,返回的结果中orderTotal列的总订单价格并没有按照一定顺序显示,接下来,使用ORDER BY关键字按总订单价格排序显示结果,SQL语句如下:
SELECT o_num,  SUM(quantity * item_price) AS orderTotal
FROM orderitems
GROUP BY o_num
HAVING SUM(quantity*item_price) >= 100
ORDER BY orderTotal;【例7.32】显示fruits表查询结果的前4行,SQL语句如下:
SELECT * From fruits LIMIT 4;【例7.33】在fruits表中,使用LIMIT子句,返回从第5个记录开始的,行数长度为3的记录,SQL语句如下:
SELECT * From fruits LIMIT 4, 3;【例7.34】查询customers表中总的行数,SQL语句如下:SELECT COUNT(*) AS cust_num FROM customers;【例7.35】查询customers表中有电子邮箱的顾客的总数,SQL语句如下:SELECT COUNT(c_email) AS email_numFROM customers;【例7.36】在orderitems表中,使用COUNT()函数统计不同订单号中订购的水果种类,SQL语句如下:SELECT o_num, COUNT(f_id)FROM orderitems GROUP BY o_num;【例7.37】在orderitems表中查询30005号订单一共购买的水果总量,SQL语句如下:SELECT SUM(quantity) AS items_totalFROM orderitemsWHERE o_num = 30005;【例7.38】在orderitems表中,使用SUM()函数统计不同订单号中订购的水果总量,SQL语句如下:SELECT o_num, SUM(quantity) AS items_totalFROM orderitemsGROUP BY o_num;【例7.39】在fruits表中,查询s_id=103的供应商的水果价格的平均值,SQL语句如下:SELECT AVG(f_price) AS avg_priceFROM fruitsWHERE s_id = 103;【例7.40】在fruits表中,查询每一个供应商的水果价格的平均值,SQL语句如下:SELECT s_id,AVG(f_price) AS avg_priceFROM fruitsGROUP BY s_id;【例7.41】在fruits表中查找市场上价格最高的水果,SQL语句如下:
SELECT MAX(f_price) AS max_price FROM fruits;
【例7.42】在fruits表中查找不同供应商提供的价格最高的水果,SQL语句如下:SELECT s_id, MAX(f_price) AS max_priceFROM fruitsGROUP BY s_id;
【例7.43】在fruits表中查找f_name的最大值,SQL语句如下:SELECT MAX(f_name) FROM fruits;【例7.44】在fruits表中查找市场上价格最低的水果,SQL语句如下:
SELECT MIN(f_price) AS min_price FROM fruits;
【例7.45】在fruits表中查找不同供应商提供的价格最低的水果,SQL语句如下:SELECT s_id, MIN(f_price) AS min_priceFROM fruitsGROUP BY s_id;为了演示的需要,首先创建数据表suppliers,SQL语句如下:
CREATE TABLE suppliers
(s_id      int      NOT NULL AUTO_INCREMENT,s_name    char(50) NOT NULL,s_city    char(50) NULL,s_zip     char(10) NULL,s_call    CHAR(50) NOT NULL,PRIMARY KEY (s_id)
) ;
插入需要演示的数据,SQL语句如下:
INSERT INTO suppliers(s_id, s_name,s_city,  s_zip, s_call)
VALUES(101,'FastFruit Inc.','Tianjin','300000','48075'),
(102,'LT Supplies','Chongqing','400000','44333'),
(103,'ACME','Shanghai','200000','90046'),
(104,'FNK Inc.','Zhongshan','528437','11111'),
(105,'Good Set','Taiyuang','030000', '22222'),
(106,'Just Eat Ours','Beijing','010', '45678'),
(107,'DK Inc.','Zhengzhou','450000', '33332');
【例7.46】在fruits表和suppliers表之间使用内连接查询。
查询之前,查看两个表的结构:DESC fruits;DESC suppliers;由结果可以看到,fruits表和suppliers表中都有相同数据类型的字段s_id,两个表通过s_id字段建立联系。接下来从fruits表中查询f_name、f_price字段,从suppliers表中查询s_id、s_name,SQL语句如下:SELECT suppliers.s_id, s_name,f_name, f_priceFROM fruits ,suppliersWHERE fruits.s_id = suppliers.s_id;【例7.47】在fruits表和suppliers表之间,使用INNER JOIN语法进行内连接查询,SQL语句如下:SELECT suppliers.s_id, s_name,f_name, f_priceFROM fruits INNER JOIN suppliersON fruits.s_id = suppliers.s_id;【例7.48】查询供应f_id= ‘a1’的水果供应商提供的其他水果种类,SQL语句如下:SELECT f1.f_id, f1.f_nameFROM fruits AS f1, fruits AS f2WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';1.LEFT JOIN左连接
左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。
首先创建表orders,SQL语句如下:
CREATE TABLE orders
(o_num  int      NOT NULL AUTO_INCREMENT,o_date datetime NOT NULL,c_id   int      NOT NULL,PRIMARY KEY (o_num)
) ;
插入需要演示的数据,SQL语句如下:
INSERT INTO orders(o_num, o_date, c_id)
VALUES(30001, '2008-09-01', 10001),
(30002, '2008-09-12', 10003),
(30003, '2008-09-30', 10004),
(30004, '2008-10-03', 10005),
(30005, '2008-10-08', 10001);
【例7.49】在customers表和orders表中,查询所有客户,包括没有订单的客户,SQL语句如下:SELECT customers.c_id, orders.o_numFROM customers LEFT OUTER JOIN ordersON customers.c_id = orders.c_id;
2.RIGHT JOIN右连接
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,左表将返回空值。
【例7.50】在customers表和orders表中,查询所有订单,包括没有客户的订单,SQL语句如下:SELECT customers.c_id, orders.o_numFROM customers RIGHT OUTER JOIN ordersON customers.c_id = orders.c_id;【例7.51】在customers表和orders表中,使用INNER JOIN语法查询customers表中ID为10001的客户的订单信息,SQL语句如下:SELECT customers.c_id, orders.o_numFROM customers INNER JOIN ordersON customers.c_id = orders.c_id AND customers.c_id = 10001;【例7.52】在fruits表和suppliers表之间,使用INNER JOIN语法进行内连接查询,并对查询结果排序,SQL语句如下:SELECT suppliers.s_id, s_name,f_name, f_priceFROM fruits INNER JOIN suppliersON fruits.s_id = suppliers.s_idORDER BY fruits.s_id;下面定义两个表tb1和tb2:
CREATE table tbl1 ( num1 INT NOT NULL);
CREATE table tbl2 ( num2 INT NOT NULL);
分别向两个表中插入数据:
INSERT INTO tbl1 values(1), (5), (13), (27);
INSERT INTO tbl2 values(6), (14), (11), (20);
ANY关键字接在一个比较操作符的后面,表示若与子查询返回的任何值比较为TRUE,则返回TRUE。
【例7.53】返回tbl2表的所有num2列,然后将tbl1中的num1的值与之进行比较,只要大于num2的任何1个值,即为符合查询条件的结果。SELECT num1 FROM tbl1 WHERE num1 > ANY (SELECT num2 FROM tbl2);
【例7.54】返回tbl1表中比tbl2表num2 列所有值都大的值,SQL语句如下:SELECT num1 FROM tbl1 WHERE num1 > ALL (SELECT num2 FROM tbl2);【例7.55】查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中的记录,SQL语句如下:SELECT * FROM fruitsWHERE EXISTS(SELECT s_name FROM suppliers WHERE s_id = 107);【例7.56】查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中的f_price大于10.20的记录,SQL语句如下:SELECT * FROM fruitsWHERE f_price>10.20 AND EXISTS(SELECT s_name FROM suppliers WHERE s_id = 107);【例7.57】查询suppliers表中是否存在s_id=107的供应商,如果不存在则查询fruits表中的记录,SQL语句如下:SELECT * FROM fruitsWHERE NOT EXISTS(SELECT s_name FROM suppliers WHERE s_id = 107);
【例7.58】在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下:SELECT c_id FROM orders WHERE o_num IN(SELECT o_num  FROM orderitems WHERE f_id = 'c0');SELECT o_num  FROM orderitems WHERE f_id = 'c0';
可以看到,符合条件的o_num列的值有两个:30003和30005,然后执行外层查询,在orders表中查询订单号等于30003或30005的客户c_id。嵌套子查询语句还可以写为如下形式,实现相同的效果:SELECT c_id FROM orders WHERE o_num IN (30003, 30005);
【例7.59】与前一个例子类似,但是在SELECT语句中使用NOT IN关键字,SQL语句如下:SELECT c_id FROM orders WHERE o_num NOT IN(SELECT o_num  FROM orderitems WHERE f_id = 'c0');SELECT * FROM orders;【例7.60】在suppliers表中查询s_city等于“Tianjin”的供应商s_id,然后在fruits表中查询所有该供应商提供的水果的种类,SQL语句如下:
SELECT s_id, f_name FROM fruits
WHERE s_id =
(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin');【例7.61】在suppliers表中查询s_city等于“Tianjin”的供应商s_id,然后在fruits表中查询所有非该供应商提供的水果的种类,SQL语句如下:SELECT s_id, f_name FROM fruitsWHERE s_id <>(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin');【例7.62】查询所有价格小于9的水果的信息,查询s_id等于101和103所有的水果的信息,使用UNION连接查询结果,SQL语句如下:
SELECT s_id, f_name, f_price
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);如前所述,UNION将多个SELECT语句的结果组合成一个结果集合。可以分开查看每个SELECT语句的结果:SELECT s_id, f_name, f_priceFROM fruitsWHERE f_price < 9.0;SELECT s_id, f_name, f_priceFROM fruitsWHERE s_id IN(101,103);【例7.63】查询所有价格小于9的水果的信息,查询s_id等于101和103的所有水果的信息,使用UNION ALL连接查询结果,SQL语句如下:
SELECT s_id, f_name, f_price
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);【例7.64】为orders表取别名o,查询30001订单的下单日期,SQL语句如下:
SELECT * FROM orders AS o
WHERE o.o_num = 30001;
在这里orders AS o代码表示为orders表取别名为o,指定过滤条件时直接使用o代替orders,查询结果如下:
+-------+---------------------+-------+
| o_num | o_date        | c_id  |
+-------+---------------------+-------+
| 30001 | 2008-09-01 00:00:00 | 10001 |
+-------+---------------------+-------+
【例7.65】为customers和orders表分别取别名,并进行连接查询,SQL语句如下:SELECT c.c_id, o.o_numFROM customers AS c LEFT OUTER JOIN orders AS oON c.c_id = o.c_id;SELECT f1.f_id, f1.f_nameFROM fruits AS f1, fruits AS f2WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';【例7.66】查询fruits表,为f_name取别名fruit_name,f_price取别名fruit_price,为fruits表取别名f1,查询表中f_price < 8的水果的名称,SQL语句如下:SELECT f1.f_name AS fruit_name, f1.f_price AS fruit_priceFROM fruits AS f1WHERE f1.f_price < 8;【例7.67】查询suppliers表中字段s_name和s_city,使用CONCAT函数连接这两个字段值,并取列别名为suppliers_title。
如果没有对连接后的值取别名,其显示列名称将会不够直观,SQL语句如下:SELECT CONCAT(TRIM(s_name) , ' (',  TRIM(s_city), ')')FROM suppliersORDER BY s_name;SELECT CONCAT(TRIM(s_name) , ' (', TRIM(s_city), ')')AS suppliers_titleFROM suppliersORDER BY s_name;【例7.68】在fruits表中,查询f_name字段以字母’b’开头的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP '^b';【例7.69】在fruits表中,查询f_name字段以“be”开头的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP '^be';【例7.70】在fruits表中,查询f_name字段以字母’y’结尾的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'y$';【例7.71】在fruits表中,查询f_name字段以字符串“rry”结尾的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'rry$';【例7.72】在fruits表中,查询f_name字段值包含字母’a’与’g’且两个字母之间只有一个字母的记录,SQL语句如下,SELECT * FROM fruits WHERE f_name REGEXP 'a.g';
【例7.73】在fruits表中,查询f_name字段值以字母’b’开头,且’b’后面出现字母’a’的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP '^ba*';【例7.74】在fruits表中,查询f_name字段值以字母’b’开头,且’b’后面出现字母’a’至少一次的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP '^ba+';
【例7.75】在fruits表中,查询f_name字段值包含字符串“on”的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'on';
【例7.76】在fruits表中,查询f_name字段值包含字符串“on”或者“ap”的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'on|ap';
【例7.77】在fruits表中,使用LIKE运算符查询f_name字段值为“on”的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name LIKE 'on';
【例7.78】在fruits表中,查找f_name字段中包含字母’o’或者’t’的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP '[ot]';
【例7.79】在fruits表,查询s_id字段中数值中包含4、5或者6的记录,SQL语句如下:SELECT * FROM fruits WHERE s_id REGEXP '[456]';
【例7.80】在fruits表中,查询f_id字段包含字母a~e和数字1~2以外的字符的记录,SQL语句如下:SELECT * FROM fruits WHERE f_id REGEXP '[^a-e1-2]';
【例7.81】在fruits表中,查询f_name字段值出现字母’x’至少2次的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'x{2,}';
【例7.82】在fruits表中,查询f_name字段值出现字符串“ba”最少1次,最多3次的记录,SQL语句如下:SELECT * FROM fruits WHERE f_name REGEXP 'ba{1,3}';

第8章 例题

本章将使用样例表person,创建语句如下:
CREATE TABLE person
(
id     INT UNSIGNED NOT NULL AUTO_INCREMENT,
name   CHAR(40) NOT NULL DEFAULT '',
age    INT NOT NULL DEFAULT 0,
info   CHAR(50) NULL,
PRIMARY KEY (id)
);
【例8.1】在person表中,插入一条新记录,id值为1,name值为Green,age值为21,info值为Lawyer,SQL语句如下:
执行插入操作之前,使用SELECT语句查看表中的数据:SELECT * FROM person;
Empty set (0.00 sec)INSERT INTO person (id ,name, age , info)VALUES (1,'Green', 21, 'Lawyer');SELECT * FROM person;【例8.2】在person表中,插入一条新记录,id值为2,name值为Suse,age值为22,info值为dancer,SQL语句如下:INSERT INTO person (age ,name, id , info)VALUES (22, 'Suse', 2, 'dancer');
【例8.3】在person表中,插入一条新记录,id值为3,name值为Mary,age值为24,info值为Musician,SQL语句如下:INSERT INTO person VALUES (3,'Mary', 24, 'Musician');SELECT * FROM person;【例8.4】在person表中,插入一条新记录,name值为Willam,age值为20,info值为sports man,SQL语句如下:INSERT INTO person (name, age,info)VALUES('Willam', 20, 'sports man');SELECT * FROM person;
【例8.5】在person表中,插入一条新记录,name值为laura,age值为25,SQL语句如下:INSERT INTO person (name, age ) VALUES ('Laura', 25);SELECT * FROM person;
【例8.6】在person表中,在name、age和info字段指定插入值,同时插入3条新记录,SQL语句如下:
INSERT INTO person(name, age, info)
VALUES ('Evans',27, 'secretary'),
('Dale',22, 'cook'),
('Edison',28, 'singer');SELECT * FROM person;
【例8.7】在person表中,不指定插入列表,同时插入2条新记录,SQL语句如下:
INSERT INTO person
VALUES (9,'Harry',21, 'magician'),
(NULL,'Harriet',19, 'pianist');
SELECT * FROM person;
【例8.8】从person_old表中查询所有的记录,并将其插入到person表中。
CREATE TABLE person_old
(
id     INT UNSIGNED NOT NULL AUTO_INCREMENT,
name   CHAR(40) NOT NULL DEFAULT '',
age    INT NOT NULL DEFAULT 0,
info   CHAR(50) NULL,
PRIMARY KEY (id)
);
向person_old表中添加两条记录:INSERT INTO person_oldVALUES (11,'Harry',20, 'student'), (12,'Beckham',31, 'police');SELECT * FROM person_old;INSERT INTO person(id, name, age, info)
SELECT id, name, age, info FROM person_old;
SELECT * FROM person;【例8.9】在person表中,更新id值为11的记录,将age字段值改为15,将name字段值改为LiMing,SQL语句如下:
UPDATE person SET age = 15, name='LiMing' WHERE id = 11;
更新操作执行前可以使用SELECT语句查看当前的数据:SELECT * FROM person WHERE id=11;UPDATE person SET age = 15, name='LiMing' WHERE id = 11;SELECT * FROM person WHERE id=11;
【例8.10】在person表中,更新age值为19~22的记录,将info字段值都改为student,SQL语句如下:
UPDATE person SET info='student'  WHERE id  BETWEEN 19 AND 22;
SELECT * FROM person WHERE age BETWEEN 19 AND 22;
UPDATE person SET info='student' WHERE age BETWEEN 19 AND 22;
SELECT * FROM person WHERE age BETWEEN 19 AND 22;
【例8.11】在person表中,删除id等于11的记录,SQL语句如下:
SELECT * FROM person WHERE id=11;
DELETE FROM person WHERE id = 11;
SELECT * FROM person WHERE id=11;
【例8.12】在person表中,使用DELETE语句同时删除多条记录,在前面UPDATE语句中将age字段值在19~22之间的记录的info字段值修改为student,在这里删除这些记录,SQL语句如下:SELECT * FROM person WHERE age BETWEEN 19 AND 22;DELETE FROM person WHERE age BETWEEN 19 AND 22;SELECT * FROM person WHERE age BETWEEN 19 AND 22;
【例8.13】删除person表中所有记录,SQL语句如下:
DELETE FROM person;
SELECT * FROM person;
DELETE FROM person;
SELECT * FROM person;

第9章 例题

【例9.1】在book表中的year_publication字段上建立普通索引,SQL语句如下:
CREATE TABLE book
(
bookid              INT NOT NULL,
bookname            VARCHAR(255) NOT NULL,
authors             VARCHAR(255) NOT NULL,
info                VARCHAR(255) NULL,
comment             VARCHAR(255) NULL,
year_publication    YEAR NOT NULL,
INDEX(year_publication)
);SHOW CREATE table book \G
explain select * from book where year_publication=1990 \G
【例9.2】创建一个表t1,在表中的id字段上使用UNIQUE关键字创建唯一索引。
CREATE TABLE t1
(
id    INT NOT NULL,
name CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
);
SHOW CREATE table t1 \G【例9.3】创建一个表t2,在表中的name字段上创建单列索引。
表结构如下:
CREATE TABLE t2
(
id   INT NOT NULL,
name CHAR(50) NULL,
INDEX SingleIdx(name(20))
);SHOW CREATE table t2 \G【例9.4】创建表t3,在表中的id、name和age字段上建立组合索引,SQL语句如下:
CREATE TABLE t3
(
id    INT NOT NULL,
name CHAR(30)  NOT NULL,
age  INT NOT  NULL,
info VARCHAR(255),
INDEX MultiIdx(id, name, age(100))
);
该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:SHOW CREATE table t3 \Gexplain select * from t3 where id=1 AND name='joe' \G【例9.5】创建表t4,在表中的info字段上建立全文索引,SQL语句如下:
CREATE TABLE t4
(
id    INT NOT NULL,
name CHAR(30) NOT NULL,
age  INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
) ENGINE=MyISAM;SHOW CREATE table t4 \G【例9.6】创建表t5,在空间类型为GEOMETRY的字段上创建空间索引,SQL语句如下:
CREATE TABLE t5
( g GEOMETRY NOT NULL, SPATIAL INDEX spatIdx(g) )ENGINE=MyISAM;
该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:SHOW CREATE table t5 \G
【例9.7】在book表中的bookname字段上建立名为BkNameIdx的普通索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkNameIdx ( bookname(30) );
添加索引之前,使用SHOW INDEX语句查看指定表中创建的索引:SHOW INDEX FROM book \G下面使用ALTER TABLE 在bookname字段上添加索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkNameIdx( bookname(30) );
使用SHOW INDEX语句查看表中的索引:SHOW INDEX FROM book \G【例9.8】在book表的bookId字段上建立名称为UniqidIdx 的唯一索引,SQL语句如下:
ALTER TABLE book ADD UNIQUE INDEX UniqidIdx ( bookId );
使用SHOW INDEX语句查看表中的索引:SHOW INDEX FROM book \G【例9.9】在book表的comment字段上建立单列索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkcmtIdx ( comment(50) );
使用SHOW INDEX语句查看表中的索引:【例9.10】在book表的authors和info字段上建立组合索引,SQL语句如下:
ALTER TABLE book ADD INDEX BkAuAndInfoIdx ( authors(20),info(50) );
使用SHOW INDEX语句查看表中的索引:【例9.11】创建表t6,在t6表上使用ALTER TABLE创建全文索引,SQL语句如下:
首先创建表t6,语句如下:
CREATE TABLE t6
(
id    INT NOT NULL,
info  CHAR(255)
) ENGINE=MyISAM;
注意修改ENGINE参数为MyISAM,MySQL默认引擎InnoDB不支持全文索引。
使用ALTER TABLE语句在info字段上创建全文索引:
ALTER TABLE t6 ADD FULLTEXT INDEX infoFTIdx ( info );
使用SHOW INDEX语句查看索引:SHOW index from t6 \G【例9.12】创建表t7,在t7的空间数据类型字段g上创建名称为spatIdx的空间索引,SQL语句如下:
CREATE TABLE t7 ( g GEOMETRY NOT NULL )ENGINE=MyISAM;
使用ALTER TABLE在表t7的g字段建立空间索引:
ALTER TABLE t7 ADD SPATIAL INDEX spatIdx(g);
使用SHOW INDEX语句查看索引:SHOW index from t7 \G2.使用CREATE INDEX创建索引
CREATE INDEX语句可以在已经存在的表上添加索引,MySQL中CREATE INDEX被映射到一个ALTER TABLE语句上,基本语法结构为:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
ON table_name (col_name[length],…) [ASC | DESC]
可以看到CREATE INDEX语句和ALTER INDEX语句的语法基本一样,只是关键字不同。
在这里,使用相同的表book,假设该表中没有任何索引值,创建book表语句如下:
CREATE TABLE book
(
bookid              INT NOT NULL,
bookname            VARCHAR(255) NOT NULL,
authors             VARCHAR(255) NOT NULL,
info                VARCHAR(255) NULL,
comment             VARCHAR(255) NULL,
year_publication    YEAR NOT NULL
);
提示:读者可以将该数据库中的book表删除,按上面的语句重新建立,然后进行下面的操作。
【例9.13】在book表中的bookname字段上建立名为BkNameIdx的普通索引,SQL语句如下:
CREATE INDEX BkNameIdx ON book(bookname);
语句执行完毕之后,将在book表中创建名称为BkNameIdx的普通索引。读者可以使用SHOW INDEX或者SHOW CREATE TABLE语句查看book表中的索引,其索引内容与前面介绍相同。
【例9.14】在book表的bookId字段上建立名称为UniqidIdx 的唯一索引,SQL语句如下:
CREATE UNIQUE INDEX UniqidIdx  ON book ( bookId );
语句执行完毕之后,将在book表中创建名称为UniqidIdx 的唯一索引。
【例9.15】在book表的comment字段上建立单列索引,SQL语句如下:
CREATE INDEX BkcmtIdx ON book(comment(50) );
语句执行完毕之后,将在book表的comment字段上建立一个名为BkcmtIdx的单列索引,长度为50。
【例9.16】在book表的authors和info字段上建立组合索引,SQL语句如下:
CREATE INDEX BkAuAndInfoIdx ON book ( authors(20),info(50) );
语句执行完毕之后,将在book表的authors和info字段上建立了一个名为BkAuAndInfoIdx的组合索引,authors的索引序号为1,长度为20,info的索引序号为2,长度为50。
【例9.17】删除表t6,重新建立表t6,在t6表中使用CREATE INDEX语句,在CHAR类型的info字段上创建全文索引,SQL语句如下:
首先删除表t6,并重新建立该表,分别输入下面语句:drop table t6;
Query OK, 0 rows affected (0.00 sec)CREATE TABLE t6(id    INT NOT NULL,info  CHAR(255)) ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)
使用CREATE INDEX在t6表的info字段上创建名称为infoFTIdx的全文索引:
CREATE FULLTEXT INDEX ON t6(info);
语句执行完毕之后,将在t6表中创建名称为infoFTIdx的索引,该索引在info字段上创建,类型为FULLTEXT,允许空值。
【例9.18】删除表t7,重新创建表t7,在t7表中使用CREATE INDEX语句,在空间数据类型字段g上创建名称为spatIdx的空间索引,SQL语句如下:
首先删除表t7,并重新建立该表,分别输入下面语句:drop table t7;
Query OK, 0 rows affected (0.00 sec)CREATE TABLE t7 ( g GEOMETRY NOT NULL )ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)
使用CREATE INDEX语句在表t7的g字段建立空间索引,
CREATE SPATIAL INDEX spatIdx ON t7 (g);
语句执行完毕之后,将在t7表中创建名称为spatIdx的空间索引,该索引在g字段上创建。
9.3  删除索引
MySQL中删除索引使用ALTER TABLE或者DROP INDEX语句,两者可实现相同的功能,DROP INDEX语句在内部被映射到一个ALTER TABLE语句中。
1.使用ALTER TABLE删除索引
ALTER TABLE删除索引的基本语法格式如下:
ALTER TABLE table_name DROP INDEX index_name;
【例9.19】删除book表中的名称为UniqidIdx的唯一索引,SQL语
句如下:
首先查看book表中是否有名称为UniqidIdx的索引,输入SHOW语句如下:SHOW CREATE table book \GALTER TABLE book DROP INDEX UniqidIdx;SHOW CREATE table book \G2.使用DROP INDEX语句删除索引
DROP INDEX删除索引的基本语法格式如下:
DROP INDEX index_name ON table_name;
【例9.20】删除book表中名称为BkAuAndInfoIdx的组合索引,SQL语句如下:DROP INDEX BkAuAndInfoIdx ON book;SHOW CREATE table book \G

第10章 例题

【例10.1】创建查看fruits表的存储过程,代码如下:
CREATE PROCEDURE Proc()BEGINSELECT * FROM fruits;END ;
这行代码创建了一个查看fruits表的存储过程,每次调用这个存储过程的时候都会执行SELECT语句查看表的内容,代码的执行过程如下:DELIMITER //CREATE PROCEDURE Proc()BEGINSELECT * FROM fruits;END //
Query OK, 0 rows affected (0.00 sec)DELIMITER ;【例10.2】创建名称为CountProc的存储过程,代码如下:
CREATE PROCEDURE CountProc (OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM fruits;
END;
上述代码的作用是创建一个获取fruits表记录条数的存储过程,名称是CountProc,COUNT(*) 计算后把结果放入参数param1中。代码的执行结果如下:DELIMITER // CREATE PROCEDURE CountProc(OUT param1 INT)BEGINSELECT COUNT(*) INTO param1 FROM fruits;END //
Query OK, 0 rows affected (0.00 sec)DELIMITER ;
当使用DELIMITER命令时,应该避免使用反斜杠(’\’)字符,因为反斜线是MySQL的转义字符。【例10.3】创建存储函数,名称为NameByZip,该函数返回SELECT语句的查询结果,数值类型为字符串型,代码如下:
CREATE FUNCTION NameByZip ()RETURNS CHAR(50)RETURN  (SELECT s_name FROM suppliers WHERE s_call= '48075');
创建一个f的存储函数,参数定义为空,返回一个INT类型的结果。代码的执行结果如下:DELIMITER //CREATE FUNCTION NameByZip()RETURNS CHAR(50)RETURN   (SELECT s_name FROM suppliers WHERE s_call= '48075');//DELIMITER ;【例10.4】定义名称为myparam的变量,类型为INT类型,默认值为100,代码如下:
DECLARE  myparam  INT  DEFAULT 100;【例10.5】声明3个变量,分别为var1、var2和var3,数据类型为INT,使用SET为变量赋值,代码如下:
DECLARE var1, var2, var3 INT;
SET var1 = 10, var2 = 20;
SET var3 = var1 + var2;
MySQL中还可以通过SELECT ... INTO为一个或多个变量赋值,语法如下:
SELECT col_name[,...] INTO var_name[,...] table_expr;
这个SELECT语法把选定的列直接存储到对应位置的变量。col_name表示字段名称;var_name表示定义的变量名称;table_expr表示查询条件表达式,包括表名称和WHERE子句。
【例10.6】声明变量fruitname和fruitprice,通过SELECT ... INTO语句查询指定记录并为变量赋值,代码如下:
DECLARE fruitname CHAR(50);
DECLARE fruitprice DECIMAL(8,2);SELECT f_name,f_price INTO fruitname, fruitprice
FROM fruits WHERE f_id ='a1';【例10.7】定义"ERROR 1148(42000)"错误,名称为command_not_allowed。可以用两种不同的方法来定义,代码如下:
//方法一:使用sqlstate_value
DECLARE  command_not_allowed CONDITION FOR SQLSTATE '42000';
//方法二:使用mysql_error_code
DECLARE  command_not_allowed CONDITION  FOR  1148
2.定义处理程序
定义处理程序时,使用DECLARE语句的语法如下:
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type:CONTINUE | EXIT | UNDOcondition_value:SQLSTATE [VALUE] sqlstate_value| condition_name| SQLWARNING| NOT FOUND| SQLEXCEPTION| mysql_error_code
【例10.8】定义处理程序的几种方式,代码如下:
//方法一:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='NO_SUCH_TABLE';//方法二:捕获mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info=' NO_SUCH_TABLE ';//方法三:先定义条件,然后调用
DECLARE  no_such_table  CONDITION  FOR  1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info=' NO_SUCH_TABLE ';//方法四:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';//方法五:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info=' NO_SUCH_TABLE ';//方法六:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR'; 【例10.9】定义条件和处理程序,具体执行的过程如下:CREATE TABLE test.t (s1 int,primary key (s1));
Query OK, 0 rows affected (0.00 sec)DELIMITER //CREATE PROCEDURE handlerdemo ()BEGINDECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;SET @x = 1;INSERT INTO test.t VALUES (1);SET @x = 2;INSERT INTO test.t VALUES (1);SET @x = 3;END;//
Query OK, 0 rows affected (0.00 sec)DELIMITER ;/*调用存储过程*/CALL handlerdemo();
Query OK, 0 rows affected (0.00 sec)
/*查看调用过程结果*/SELECT @x;【例10.10】声明名称为cursor_fruit的光标,代码如下:
DECLARE cursor_fruit CURSOR FOR SELECT f_name, f_price FROM fruits ;
上面的示例中,光标的名称为cur_fruit,SELECT语句部分从fruits表中查询出f_name和f_price字段的值。
【例10.12】使用名称为cursor_fruit的光标。将查询出来的数据存入fruit_name和fruit_price这两个变量中,代码如下:
FETCH  cursor_fruit INTO fruit_name, fruit_price ;
上面的示例中,将光标cursor_fruit中SELECT语句查询出来的信息存入fruit_name和fruit_price中。fruit_name和fruit_price必须在前面已经定义。【例10.13】关闭名称为cursor_fruit的光标,代码如下:
CLOSE  cursor_fruit; 【例10.14】IF语句的示例,代码如下:
IF val IS NULLTHEN SELECT 'val is NULL';ELSE SELECT 'val is not NULL';
END IF;
【例10.15】使用CASE流程控制语句的第1种格式,判断val值等于1、等于2,或者两者都不等,语句如下:
CASE valWHEN 1 THEN SELECT 'val is 1';WHEN 2 THEN SELECT 'val is 2';ELSE SELECT 'val is not 1 or 2';
END CASE;
当val值为1时,输出字符串“val is 1”;当val值为2时,输出字符串“val is 2”;否则输出字符串“val is not 1 or 2”。
CASE语句的第2种格式如下:
CASEWHEN expr_condition THEN statement_list[WHEN expr_condition THEN statement_list] ...[ELSE statement_list]
END CASE
【例10.16】使用CASE流程控制语句的第2种格式,判断val是否为空、小于0、大于0或者等于0,语句如下:
CASEWHEN val IS NULL THEN SELECT 'val is NULL';WHEN val < 0 THEN SELECT 'val is less than 0';WHEN val > 0 THEN SELECT 'val is greater than 0';ELSE SELECT 'val is 0';
END CASE;
当val值为空,输出字符串“val is NULL”;当val值小于0时,输出字符串“val is less than 0”;当val值大于0时,输出字符串“val is greater than 0”;否则输出字符串“val is 0”。【例10.17】使用LOOP语句进行循环操作,id值小于等于10之前,将重复执行循环过程,代码如下:
DECLARE id INT DEFAULT 0;
add_loop: LOOP
SET id = id + 1;IF id >= 10 THEN  LEAVE add_loop;END IF;
END LOOP add_ loop; 【例10.18】使用LEAVE语句退出循环,代码如下:
add_num: LOOP
SET @count=@count+1;
IF @count=50 THEN LEAVE add_num ;
END LOOP add_num ;
该示例循环执行count加1的操作。当count的值等于50时,使用LEAVE语句跳出循环。【例10.19】ITERATE语句示例,代码如下:
CREATE PROCEDURE doiterate()
BEGIN
DECLARE p1 INT DEFAULT 0;
my_loop: LOOPSET p1= p1 + 1;IF p1 < 10 THEN ITERATE my_loop;ELSEIF p1 > 20 THEN LEAVE my_loop;END IF;SELECT 'p1 is between 10 and 20';
END LOOP my_loop;
END【例10.20】REPEAT语句示例,id值小于等于10之前,将重复执行循环过程,代码如下:
DECLARE id INT DEFAULT 0;
REPEAT
SET id = id + 1;
UNTIL  id >= 10
END REPEAT;
该示例循环执行id加1的操作。当id值小于10时,循环重复执行;当id值大于或者等于10时,使用LEAVE语句退出循环。REPEAT循环都以END REPEAT结束。【例10.21】WHILE语句示例,id值小于等于10之前,将重复执行循环过程,代码如下:
DECLARE i INT DEFAULT 0;
WHILE i < 10 DO
SET i = i + 1;
END WHILE;【例10.22】定义名为CountProc1的存储过程,然后调用这个存储过程,代码执行如下:
定义存储过程:DELIMITER //CREATE PROCEDURE CountProc1 (IN sid INT, OUT num INT)BEGINSELECT COUNT(*) INTO num FROM fruits WHERE s_id = sid;END //
Query OK, 0 rows affected (0.00 sec)DELIMITER ;
调用存储过程:CALL CountProc1 (101, @num);
Query OK, 1 row affected (0.00 sec)
查看返回结果:select @num;【例10.23】定义存储函数CountProc2,然后调用这个函数,代码如下:DELIMITER //CREATE FUNCTION  CountProc2 (sid INT)RETURNS INTBEGINRETURN (SELECT COUNT(*) FROM fruits WHERE s_id = sid);END //
Query OK, 0 rows affected (0.00 sec)DELIMITER ;
调用存储函数:SELECT CountProc2(101);【例10.24】SHOW STATUS语句示例,代码如下:
SHOW PROCEDURE STATUS LIKE 'C%'\G【例10.25】SHOW CREATE语句示例,代码如下:
SHOW CREATE FUNCTION test.CountProc \G【例10.26】从Routines表中查询名称为CountProc的存储函数的信息,代码如下:
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='CountProc'  AND  ROUTINE_TYPE = 'FUNCTION' \G【例10.27】修改存储过程CountProc的定义。将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行,代码如下:
ALTER  PROCEDURE  CountProc
MODIFIES SQL DATA
SQL SECURITY INVOKER ;
执行代码,并查看修改后的信息。结果显示如下:
//执行ALTER PROCEDURE语句ALTER  PROCEDURE  CountProcMODIFIES SQL DATA  SQL SECURITY INVOKER ;
Query OK, 0 rows affected (0.00 sec)
//查询修改后的CountProc表信息  SELECT SPECIFIC_NAME,SQL_DATA_ACCESS,SECURITY_TYPEFROM information_schema.RoutinesWHERE ROUTINE_NAME='CountProc' AND ROUTINE_TYPE='PROCEDURE';【例10.28】修改存储函数CountProc的定义。将读写权限改为READS SQL DATA,并加上注释信息“FIND NAME”,代码如下:
ALTER  FUNCTION  CountProc
READS SQL DATA
COMMENT 'FIND NAME' ;
执行代码,并查看修改后的信息。结果显示如下:
//执行ALTER FUNCTION语句ALTER  FUNCTION  CountProc  READS SQL DATA  COMMENT 'FIND NAME' ;
Query OK, 0 rows affected (0.00 sec)
//查询修改后f表的信息SELECT SPECIFIC_NAME,SQL_DATA_ACCESS,ROUTINE_COMMENT
FROM information_schema.Routines
WHERE ROUTINE_NAME='CountProc'  AND  ROUTINE_TYPE = 'FUNCTION'  ;【例10.29】删除存储过程和存储函数,代码如下:
DROP PROCEDURE CountProc;
DROP FUNCTION CountProc;

第11章 例题

/*样例表*/
CREATE TABLE student
(s_id  INT,name  VARCHAR(40)
);CREATE TABLE stu_info
(s_id   INT,glass  VARCHAR(40),addr   VARCHAR(90)
);【例11.1】在t表格上创建一个名为view_t的视图,代码如下:
CREATE TABLE t (qty INT, price INT);         /*创建基本表t*/
INSERT INTO t VALUES(3, 50);                 /*插入记录*/
CREATE VIEW view_t AS SELECT quantity, price, quantity *price FROM t;    /*创建视图view_t*/
SELECT * FROM view_t;【例11.2】在t表格上创建一个名为view_t2的视图,代码如下:
CREATE VIEW view_t2(qty, price, total ) AS SELECT quantity, price, quantity *price FROM t;
SELECT * FROM view_t2;【例11.3】在表student和表stu_info上创建视图stu_glass,代码如下:
INSERT INTO student VALUES(1,'wanglin1'),(2,'gaoli'),(3,'zhanghai');                /*插入记录*/
INSERT INTO stu_info VALUES(1, 'wuban','henan'),(2,'liuban','hebei'),(3,'qiban','shandong');CREATE VIEW stu_glass (id,name, glass) AS SELECT student.s_id,student.name ,stu_info.glass FROM student ,stu_info WHERE student.s_id=stu_info.s_id;SELECT * FROM stu_glass;【例11.4】通过DESCRIBE语句查看视图view_t的定义,代码如下:
DESCRIBE view_t;【例11.5】下面将通过一个例子来学习使用SHOW TABLE STATUS命令查看视图信息,代码如下:
SHOW TABLE STATUS LIKE 'view_t' \G;
SHOW TABLE STATUS LIKE 't' \G;【例11.6】SHOW CREATE VIEW查看视图的详细定义,代码如下:
SHOW CREATE VIEW view_t \G;【例11.7】在views表中查看视图的详细定义,代码如下:
SELECT * FROM information_schema.views \G;【例11.8】修改视图view_t,代码如下:
DESC view_t;
CREATE OR REPLACE VIEW view_t AS SELECT * FROM t;
DESC view_t;【例11.9】使用ALTER语句修改视图view_t,代码如下:
DESC view_t;
ALTER VIEW view_t AS SELECT quantity FROM t;
DESC view_t;【例11.10】使用UPDATE语句更新视图view_t,代码如下:
SELECT * FROM view_t;          /*查看更新之前的视图*/
SELECT * FROM t;               /*查看更新之前的表*/
UPDATE view_t SET quantity=5;  /*更新视图*/
SELECT * FROM t;               /*查看更新之后的表*/
SELECT * FROM view_t;          /*查看更新之后的视图*/
SELECT * FROM view_t2;【例11.11】使用INSERT语句在基本表t中插入一条记录,代码如下:
INSERT INTO t VALUES (3,5);
SELECT * FROM t;
SELECT * FROM view_t2;【例11.12】删除stu_glass视图,代码如下:
DROP VIEW IF EXISTS stu_glass;
SHOW CREATE VIEW stu_glass;

第12章 例题

【例11.1】在t表格上创建一个名为view_t的视图,代码如下:
首先创建基本表并插入数据,语句如下:
CREATE TABLE t (quantity INT, price INT);
INSERT INTO t VALUES(3, 50);
创建视图语句为:
CREATE VIEW view_t AS SELECT quantity, price, quantity *price FROM t;SELECT * FROM view_t;【例11.2】在t表格上创建一个名为view_t2的视图,代码如下:CREATE VIEW view_t2(qty, price, total ) AS SELECT quantity, price, quantity *price FROM t;
语句执行成功,查看view_t2视图中的数据:SELECT * FROM view_t2;
【例11.3】在表student和表stu_info上创建视图stu_glass,代码如下:
首先向两个表中插入数据,输入语句如下:INSERT INTO student VALUES(1,'wanglin1'),(2,'gaoli'),(3,'zhanghai');INSERT INTO stu_info VALUES(1, 'wuban','henan'),(2,'liuban','hebei'),(3,'qiban','shandong');CREATE VIEW stu_glass (id,name, glass) AS SELECT student.s_id,student.name ,stu_info.glass
FROM student ,stu_info WHERE student.s_id=stu_info.s_id;SELECT * FROM stu_glass;【例11.4】通过DESCRIBE语句查看视图view_t的定义,代码如下:
DESCRIBE view_t;
代码执行如下:DESCRIBE view_t;【例11.5】下面将通过一个例子来学习使用SHOW TABLE STATUS命令查看视图信息,代码如下:
SHOW TABLE STATUS LIKE 'view_t' \G执行结果显示,表的说明Comment的值为VIEW说明该表为视图,其他的信息也为NULL说明这是一个虚表。用同样的语句来查看一下数据表t的信息,执行结果如下:SHOW TABLE STATUS LIKE 't' \G【例11.6】SHOW CREATE VIEW查看视图的详细定义,代码如下:
SHOW CREATE VIEW view_t \G【例11.7】在views表中查看视图的详细定义,代码如下:SELECT * FROM information_schema.views\G【例11.8】修改视图view_t,代码如下:
CREATE OR REPLACE VIEW view_t AS SELECT * FROM t;
首先通过DESC查看一下更改之前的视图,以便与更改之后的视图进行对比。执行的结果如下:DESC view_t;CREATE OR REPLACE VIEW view_t AS SELECT * FROM t;DESC view_t;【例11.9】使用ALTER语句修改视图view_t,代码如下:
ALTER VIEW view_t AS SELECT quantity FROM t;
执行结果如下:DESC view_t;ALTER VIEW view_t AS SELECT quantity FROM t;DESC view_t;【例11.10】使用UPDATE语句更新视图view_t,代码如下:
UPDATE view_t SET quantity=5;
执行视图更新之前,查看基本表和视图的信息,执行结果如下:SELECT * FROM view_t;SELECT * FROM t;使用UPDATE语句更新视图view_t,执行过程如下:UPDATE view_t SET quantity=5;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0查看视图更新之后,基本表的内容:SELECT * FROM t;SELECT * FROM view_t;SELECT * FROM view_t2;对视图view_t更新后,基本表t的内容也更新了,同样当对基本表t更新后,另外一个视图view_t2中的内容也会更新。
【例11.11】使用INSERT语句在基本表t中插入一条记录,代码如下:
INSERT INTO t VALUES (3,5);
执行结果如下:INSERT INTO t VALUES(3,5);
Query OK, 1 row affected (0.04 sec)SELECT * FROM t;SELECT * FROM view_t2;【例11.12】使用DELETE语句在删除视图view_t2中的一条记录,代码如下:
DELETE FROM view_t2 WHERE price=5;
执行结果如下:DELETE FROM view_t2 WHERE price=5;
Query OK, 1 row affected (0.03 sec)SELECT * FROM view_t2;SELECT * FROM t;【例11.13】删除stu_glass视图,代码如下:
DROP VIEW IF EXISTS stu_glass;SHOW CREATE VIEW stu_glass;

第13章 例题

【例13.1】使用root用户登录到本地mysql服务器的test库中
mysql -uroot -p -hlocalhost test【例13.2】使用root用户登录到本地mysql服务器的test库中,执行一条查询语句
mysql -uroot -p -hlocalhost test -e "DESC person;"【例13.3】使用CREATE USER创建一个用户,用户名是jeffrey,密码是mypass,主机名是localhost
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';【例13.4】使用GRANT语句创建一个新的用户testUser,密码为testpwd。用户 testUser对所有的数据有查询和更新权限,并授于对所有数据表的SELECT和UPDATE权限
GRANT SELECT,UPDATE  ON *.* TO 'testUser'@'localhost' IDENTIFIED BY 'testpwd';    /*创建账户并授予权限*/
SELECT Host,User,Select_priv,Update_priv, FROM mysql.user where user='testUser';  /*查看账户权限信息*/【例13.5】使用INSERT创建一个新账户,其用户名称为customer1,主机名称为localhost,密码为customer1:
INSERT INTO user (Host,User,Password) VALUES('localhost','customer1',PASSWORD('customer1'));【例13.6】使用DROP USER删除用户'jeffrey'@'localhost'
DROP USER 'jeffrey'@'localhost';【例13.7】使用DELETE删除用户'customer1'@'localhost'
DELETE FROM mysql.user WHERE host='localhost' and user='customer1';【例13.8】使用mysqladmin将root用户的密码修改为“rootpwd”
mysqladmin -u root -p password "123456"【例13.9】使用UPDATE语句将root用户的密码修改为“rootpwd2”:
UPDATE mysql.user set Password=password("rootpwd2")
WHERE User="root" and Host="localhost";【例13.10】使用SET语句将root用户的密码修改为“rootpwd3”:
SET PASSWORD=password("rootpwd3");【例13.11】使用SET语句将testUser用户的密码修改为“newpwd”:
SET PASSWORD FOR 'testUser'@'localhost'=password("newpwd");【例13.12】使用UPDATE语句将testUser用户的密码修改为“newpwd2”:
UPDATE   mysql.user set Password=PASSWORD("newpwd2")
WHERE User="testUser" and Host="localhost";【例13.13】使用GRANT语句将testUser用户的密码修改为“newpwd3”:
GRANT USAGE ON *.* TO 'testUser'@'localhost' IDENTIFIED BY 'newpwd3';【例13.14】testUser用户使用SET语句将自身的密码修改为“newpwd4”:
SET PASSWORD = PASSWORD("newpwd4");
【例13.15】使用GRANT语句创建一个新的用户grantUser,密码为“grantpwd”。用户grantUser对所有的数据有查询、插入权限,并授于GRANT权限。GRANT语句及其执行结果如下:
MySQL> GRANT SELECT,INSERT ON *.* TO 'grantUser'@'localhost'  IDENTIFIED BY 'grantpwd' WITH GRANT OPTION;
Query OK, 0 rows affected (0.03 sec)
结果显示执行成功,使用SELECT语句查询用户testUser2的权限:
MySQL> SELECT Host,User,Select_priv,Insert_priv, Grant_priv FROM mysql.user where user='grantUser';
+-----------+------------+-------------+--------------+-------------+
| Host    | User    | Select_priv | Insert_priv | Grant_priv |
+-----------+------------+-------------+--------------+--------------+
| localhost | testUser2 | Y        | Y        | Y        |
+-----------+------------+-------------+--------------+--------------+
1 row in set (0.00 sec)
【例13.16】使用REVOKE语句取消用户testUser的更新权限。REVOKE语句及其执行结果如下:
MySQL> REVOKE UPDATE ON *.* FROM 'testUser'@'localhost';
Query OK, 0 rows affected (0.00 sec)
执行结果显示执行成功,使用SELECT语句查询用户test的权限:
MySQL> SELECT Host,User,Select_priv,Update_priv,Grant_priv FROM MySQL.user where user='testUser';【例13.17】使用SHOW GRANTS语句查询用户testUser的权限信息。SHOW GRANTS语句及其执行结果如下:
MySQL> SHOW GRANTS FOR 'testUser'@'localhost';2. 案例操作过程打开MySQL客户端工具,输入登录命令,登录MySQL。
C:\>mysql -u root -p
Enter password: **
输入正确密码,按回车,出现欢迎信息表示登录成功。选择mysql数据库为当前数据库。
MySQL> use mysql;
Database changed
出现Database changed信息表明切换数据库成功。创建新账户,用户名称为newAdmin,密码为pw1,允许其从本地主机访问MySQL。
使用GRANT语句创建新账户,创建过程如下:
MySQL> GRANT SELECT, UPDATE(id, name, age)-> ON test_db.person_old-> TO 'newAdmin'@'localhost' IDENTIFIED BY 'pw1'-> WITH MAX_CONNECTIONS_PER_HOUR 30;SELECT host, user, select_priv, update_priv FROM user WHERE user='newAdmin';SELECT host, db, user, table_name, table_priv, column_priv
FROM tables_priv WHERE user='newAdmin';SELECT host, db, user, table_name, column_name, column_priv
FROM columns_priv WHERE user='newAdmin';
3条SQL语句的查询结果分别如下:
MySQL> SELECT host, user, select_priv, update_priv FROM user WHERE user='newAdmin';MySQL> SELECT host, db, user, table_name, table_priv, column_priv-> FROM tables_priv WHERE user='newAdmin';MySQL> SELECT host, db, user, table_name, column_name, column_priv-> FROM columns_priv WHERE user='newAdmin';使用SHOW GRANTS语句查看newAdmin的权限信息。
查看newAdmin账户的权限信息,输入语句如下:
SHOW GRANTS FOR 'newAdmin'@'localhost';使用newAdmin用户登录MySQL。
退出当前登录,使用EXIT命令,语句如下:
MySQL> exit
Bye
使用newAdmin账户登录MySQL,语句如下:
C:\>MySQL -u newAdmin -p
Enter password: ***
输入密码正确后,出现“mysql>”提示符,登录成功。使用newAdmin用户查看test_db数据库中person_dd表中的数据。
newAdmin用户被授予test数据库中person表中3个字段上的查询权限,因此可以执行SELECT语句查看这几个字段的值,执行过程如下:
MySQL> SELECT * FROM test_db.person_dd LIMIT 5;使用newAdmin用户向person_dd表中插入一条新记录,查看语句执行结果。
插入新记录,输入语句如下:
INSERT INTO test_db.person_old(name, age,info) VALUES('gaga', 30);
执行结果如下:
ERROR 1142 (42000): INSERT command denied to user 'newAdmin'@'localhost' for table 'person'
可以看到,语句不能执行,错误信息表明newAdmin用户不能对person表进行插入操作。因此,用户不可以执行没有被授权的操作语句。退出当前登录,使用root用户重新登录,收回newAdmin账户的权限。
输入退出命令:
exit
重新以root用户登录MySQL,并选择mysql数据库为当前数据库。
输入语句收回newAdmin账户的权限,执行过程如下:
REVOKE SELECT, UPDATE ON test.person FROM 'newAdmin'@'localhost';
执行结果如下:
MySQL> REVOKE SELECT, UPDATE ON test.person FROM 'newAdmin'@'localhost';
Query OK, 0 rows affected (0.00 sec)删除newAdmin的账户信息。
删除指定账户,可以使用DROP USER语句,输入如下:
DROP USER 'newAdmin'@'localhost';

第14章 例题


CREATE DATABASE booksDB;
user booksDB;CREATE TABLE books
(bk_id  INT NOT NULL PRIMARY KEY,bk_title VARCHAR(50) NOT NULL,copyright YEAR NOT NULL
);
INSERT INTO books
VALUES (11078, 'Learning MySQL', 2010),
(11033, 'Study Html', 2011),
(11035, 'How to use php', 2003),
(11072, 'Teach youself javascript', 2005),
(11028, 'Learing C++', 2005),
(11069, 'MySQL professional', 2009),
(11026, 'Guide to MySQL 5.5', 2008),
(11041, 'Inside VC++', 2011);CREATE TABLE authors
(auth_id     INT NOT NULL PRIMARY KEY,auth_name  VARCHAR(20),auth_gender CHAR(1)
);
INSERT INTO authors
VALUES (1001, 'WriterX' ,'f'),
(1002, 'WriterA' ,'f'),
(1003, 'WriterB' ,'m'),
(1004, 'WriterC' ,'f'),
(1011, 'WriterD' ,'f'),
(1012, 'WriterE' ,'m'),
(1013, 'WriterF' ,'m'),
(1014, 'WriterG' ,'f'),
(1015, 'WriterH' ,'f');CREATE TABLE authorbook
(auth_id  INT NOT NULL,bk_id   INT NOT NULL,PRIMARY KEY (auth_id, bk_id),FOREIGN KEY (auth_id) REFERENCES authors (auth_id),FOREIGN KEY (bk_id) REFERENCES books (bk_id)
);INSERT INTO authorbook
VALUES (1001, 11033), (1002, 11035), (1003, 11072), (1004, 11028),
(1011, 11078), (1012, 11026), (1012, 11041), (1014, 11069);【例14.1】使用mysqldump命令备份数据库中的所有表
mysqldump -u root -p booksdb > C:/backup/booksdb_20110101.sql【例14.2】备份booksDB数据库中的books表
mysqldump -u root -p booksDB books > C:/backup/books_20110101.sql【例14.3】使用mysqldump备份booksDB和test数据库
mysqldump -u root -p --databases  booksDB test> C:\backup\books_testDB_20110101.sql【例14.4】使用mysqldump备份服务器中的所有数据库
mysqldump  -u root -p --all-databases > C:/backup/alldbinMySQL.sql【例14.5】使用mysqlhotcopy备份test数据库到/usr/backup目录下
mysqlhotcopy  -u root -p test /usr/backup【例14.6】使用mysql命令将C:\backup\booksdb_20110101.sql文件中的备份导入到数据库中
mysql -u root-p booksDB < C:/backup/booksdb_20110101.sql 【例14.7】使用root用户登录到服务器,然后使用souce导入本地的备份文件booksdb_20110101.sql
use booksdb;
source C:/backup/booksdb_20110101.sql【例14.8】从mysqlhotcopy拷贝的备份恢复数据库
cp –R  /usr/backup/test usr/local/mysql/data【例14.9】将www.abc.com主机上的MySQL数据库全部迁移到www.bcd.com主机上。在www.abc.com主机上执行的命令如下:
mysqldump -h www.bac.com -uroot -ppassword  dbname |
mysql -hwww.bcd.com -uroot -ppassword【例14.10】使用SELECT...INTO OUTFILE将test数据库中的person表中的记录导出到文本文件
SELECT *  FROM test.person INTO OUTFILE "C:/person0.txt";【例14.11】使用SELECT...INTO OUTFILE将test数据库中的person表中的记录导出到文本文件,使用FIELDS选项和LINES选项,要求字段之间使用逗号‘,’间隔,所有字段值用双引号括起来,定义转义字符定义为单引号‘\’’
SELECT * FROM test.person INTO OUTFILE "C:/person1.txt"FIELDS TERMINATED BY ','ENCLOSED BY '\"'ESCAPED BY '\''LINES TERMINATED BY '\r\n';【例14.12】使用SELECT...INTO OUTFILE将test数据库中的person表中的记录导出到文本文件,使用LINES选项,要求每行记录以字符串“> ”开始,以“<end>”字符串结尾
SELECT * FROM test.person INTO OUTFILE "C:/person2.txt"LINES STARTING BY '> 'TERMINATED BY '<end>';SELECT * FROM test.person INTO OUTFILE "C:/person2.txt"LINES STARTING BY '> 'TERMINATED BY '<end>\r\n';【例14.13】使用mysqldump将test数据库中的person表中的记录导出到文本文件
mysqldump -T C:/ test person -u root -p【例14.14】使用mysqldump命令将test数据库中的person表中的记录导出到文本文件,使用FIELDS选项,要求字段之间使用逗号‘,’间隔,所有字符类型字段值用双引号括起来,定义转义字符定义为问号‘?’,每行记录以回车换行符“\r\n”结尾
mysqldump -T C:\backup test person -u root -p --fields-terminated-by=, --fields-optionally-enclosed-by=\" --fields-escaped-by=? --lines-terminated-by=\r\n【例14.15】使用mysql语句导出test数据库中person表中的记录到文本文件
mysql -u root -p --execute="SELECT * FROM person;" test > C:\person3.txt【例14.16】使用mysql命令导出test数据库中person表中的记录到文本文件,使用--vertical参数显示结果
mysql -u root -p --vertical --execute="SELECT * FROM person;" test > C:\person4.txt【例14.17】使用mysql命令导出test数据库中person表中的记录到html文件
mysql -u root -p --html --execute="SELECT * FROM person;" test > C:\person5.html【例14.18】使用mysql命令导出test数据库中person表中的记录到xml文件
mysql -u root -p --xml --execute="SELECT * FROM person;" test > C:\person6.xml【例14.19】使用LOAD DATA命令将C:\person0.txt文件中的数据导入到test数据库中的person表
LOAD DATA  INFILE 'C:/person0.txt' INTO TABLE test.person;【例14.20】使用LOAD DATA命令将C:\person1.txt文件中的数据导入到test数据库中的person表,使用FIELDS选项和LINES选项,要求字段之间使用逗号‘,’间隔,所有字段值用双引号括起来,定义转义字符定义为单引号‘\’’
LOAD DATA  INFILE 'C:/person1.txt' INTO TABLE test.personFIELDS TERMINATED BY ','ENCLOSED BY '\"'ESCAPED BY '\''LINES TERMINATED BY '\r\n';【例14.21】使用mysqlimport命令将C:\backup目录下的person.txt文件内容导入到test数据库中,字段之间使用逗号‘,’间隔,字符类型字段值用双引号括起来,定义转义字符定义为问号‘?’,每行记录以回车换行符“\r\n”结尾
mysqlimport -u root -p test C:/backup/person.txt --fields-terminated-by=, --fields-optionally-enclosed-by=\" --fields-escaped-by=? --lines-terminated-by=\r\n

第15章 例题

【例15.1】使用SHOW VARIABLES语句查询日志设置,执行的语句及结果如下:SHOW VARIABLES LIKE 'log_%' ;
【例15.2】使用SHOW BINARY LOGS将查看二进制日志文件个数及文件名,执行命令及结果如下:SHOW BINARY LOGS;【例15.3】使用mysqlbinlog查看二进制日志,执行命令及结果如下:
C:\> mysqlbinlog D:/MySQL/log/binlog.000001【例15.4】使用PURGE MASTER LOGS删除创建时间比binlog.000003早的所有日志文件。
首先,为了演示语句操作过程,准备多个日志文件,读者可以对MySQL服务进行多次重新启动。例如这里有10个日志文件,如下:SHOW binary logs;执行删除命令如下:PURGE MASTER LOGS TO "binlog.000003";
Query OK, 0 rows affected (0.07 sec)
执行完成后,使用SHOW binary logs语句查看二进制日志:SHOW binary logs;
【例15.5】使用PURGE MASTER LOGS删除2011年8月30日前创建的所有日志文件,执行命令及结果如下:PURGE MASTER LOGS BEFORE '20130330';
Query OK, 0 rows affected (0.05 sec)
语句执行之后,2013年3月30日之前创建的日志文件都将被删除,但2013年3月30日的日志会被保留(读者可根据自己机器中创建日志的时间修改命令参数)。使用mysqlbinlog可以查看指定日志的创建时间,如前面的【例15.3】所示,部分日志内容如下:
C:\> mysqlbinlog D:\MySQL\log\mysql-bin.000001
【例15.6】使用mysqlbinlog恢复MySQL数据库到2013年3月30日15:27:48时的状态,执行命令及结果如下:
mysqlbinlog --stop-date="2013-03-30 15:27:48" D:\MySQL\log\binlog\binlog.000008 | mysql –uuser –ppass【例15.7】使用记事本查看MySQL错误日志。
首先,通过SHOW VARIABLES语句查询错误日志的存储路径和文件名:SHOW VARIABLES LIKE 'log_error';
可以看到错误的文件是Kevin.err,位于MySQL默认的数据目录下,使用记事本打开该文件,可以看到MySQL的错误日志:
130330 16:45:14 [Note] Plugin 'FEDERATED' is disabled.
130330 16:45:14 InnoDB: The InnoDB memory heap is disabled
130330 16:45:14 InnoDB: Mutexes and rw_locks use Windows interlocked functions
130330 16:45:14 InnoDB: Compressed tables use zlib 1.2.3
130330 16:45:15 InnoDB: Initializing buffer pool, size = 46.0M
130330 16:45:15 InnoDB: Completed initialization of buffer pool
130330 16:45:15 InnoDB: highest supported file format is Barracuda.
130330 16:45:15 InnoDB: Waiting for the background threads to start
130330 16:45:16 InnoDB: 1.1.7 started; log sequence number 1679264
130330 16:45:16 [Note] Event Scheduler: Loaded 0 events
130330 16:45:16 [Note] C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld: ready for connections.
Version: '5.6.10-log'  socket: ''  port: 3306  MySQL Community Server (GPL)
以上是错误日志文件的一部分,这里面记载了系统的一些错误。【例15.8】使用记事本查看MySQL通用查询日志。
使用记事本打开D:\mysql-5.6.10-win32\data\目录下的my-PC.log,可以看到如下内容:
C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld, Version: 5.6.10-log (MySQL Community Server
(GPL)). started with:
TCP Port: 3306, Named Pipe: (null)
Time                 Id Command    Argument
130330 17:24:32        1 Connect      root@localhost on 1 Query        select @@version_comment limit 1
130330 17:24:36        1 Query        SELECT DATABASE()1 Init DB        test
130330 17:24:53        1 Query         SELECT * FROM fruits
130330 17:24:55       1 Quit 【例15.9】直接删除MySQL通用查询日志。执行步骤如下:查看my.ini(或者my.cnf)查看通用查询日志的文件目录,在my.ini中通用查询日志配置如下。
[mysqld]
log
可以看到,配置文件中没有指定日志文件名和存储目录,通用查询日志文件存储在MySQL默认数据目录中。在数据目录中找到日志文件所在目录C:\Documents and Settings\All Users.WINDOWS\ Application Data\MySQL\MySQL Server 5.6\data\,删除该后缀为.err的文件。通过mysqladmin –flush logs命令建立新的日志文件,执行命令如下。
C:\> mysqladmin –u root –p flush-logs执行完该命令,可以看到,C:\Documents and Settings\All Users.WINDOWS\Application Data\MySQL\MySQL Server 5.6\data\目录中已经建立了新的日志文件Kevin.log。【例15.10】查看慢查询日志。使用文本编辑器打开数据目录下的Kevin-slow.log文件,文件部分如下:
C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld, Version: 5.6.10-log (MySQL Community Server
(GPL)). started with:
TCP Port: 3306, Named Pipe: (null)
Time Id Command Argument
# Time: 130330 17:50:35
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 136.500000  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
SET timestamp=1314697835;
SELECT BENCHMARK(100000000, PASSWORD('newpwd'));

第16章 例题

【例16.1】使用EXPLAIN语句来分析一个查询语句
EXPLAIN SELECT * FROM fruits;【例16.2】下面是查询语句中不使用索引和使用索引的对比。
EXPLAIN SELECT * FROM fruits WHERE f_name='apple';  /*分析未使用索引时的查询情况*/
CREATE INDEX index_name ON fruits(f_name);          /*创建索引*/
EXPLAIN SELECT * FROM fruits WHERE f_name='apple';  /*分析使用索引时的查询情况*/【例16.3】查询语句中使用LIKE关键字,并且匹配的字符串中含有‘%’符,EXPLAIN语句执行如下:
EXPLAIN SELECT * FROM fruits WHERE f_name like '%x';
EXPLAIN SELECT * FROM fruits WHERE f_name like 'x%';【例16.4】本例在表fruits中f_id、f_price字段创建多列索引,验证多列索引的使用情况。
CREATE INDEX index_id_price ON fruits(f_id, f_price);
EXPLAIN SELECT * FROM fruits WHERE f_id='l2';
EXPLAIN SELECT * FROM fruits WHERE f_price=5.2;【例16.5】查询语句使用OR关键字的情况:
EXPLAIN SELECT * FROM fruits WHERE f_name='apple' or s_id=101 \G;
EXPLAIN SELECT * FROM fruits WHERE f_name='apple' or f_id='l2' \G;【例16.6】下面的会员表(members)主要用来存储会员登录认证信息,
CREATE TABLE members (Id int(11) NOT NULL AUTO_INCREMENT,username varchar(255) DEFAULT NULL ,password varchar(255) DEFAULT NULL ,last_login_time datetime DEFAULT NULL ,last_login_ip varchar(255) DEFAULT NULL ,PRIMARY KEY (Id)
) ;CREATE TABLE members_detail (member_id int(11) NOT NULL DEFAULT 0,address varchar(255) DEFAULT NULL ,telephone varchar(16) DEFAULT NULL ,description text
) ;SELECT * FROM members LEFT JOIN members_detail ON members.id=members_detail.member_id【例16.7】会员信息表和会员组信息表如下:
CREATE TABLE vip(Id int(11) NOT NULL AUTO_INCREMENT,username varchar(255) DEFAULT NULL,password varchar(255) DEFAULT NULL,groupId INT(11) DEFAULT 0,PRIMARY KEY (Id)
) ;CREATE TABLE vip_group (Id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) DEFAULT NULL,remark varchar(255) DEFAULT NULL,PRIMARY KEY (Id)
) ;CREATE TABLE temp_vip (Id int(11) NOT NULL AUTO_INCREMENT,user_name varchar(255) DEFAULT NULL,group_name varchar(255) DEFAULT NULL,group_remark varchar(255) DEFAULT NULL,PRIMARY KEY (Id)
);INSERT INTO temp_vip(user_name, group_name, group_remark)
SELECT v.username,g.name,g.remark
FROM vip as v ,vip_group as g
WHERE v.groupId=g.Id;【例16.8】使用ANALYZE TABLE来分析message表,执行的语句及结果如下:
ANALYZE TABLE fruits;

第17章 例题


步骤1: 在Windows操作系统下安装好两台主机的MySQL服务器,配置好两台主机的IP地址,实现两台计算机可以网络连通。步骤2: 看下datadir的具体的路径。
mysql> show variables like '%datadir%';步骤3: 编译C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.6目录下面的配置文件my.ini。
[mysqld]
log_bin="D:/MySQLlog/binlog"
expire_logs_days = 10
max_binlog_size = 100M步骤4: 登录MySQL之后,可以执行show variables like ‘%log_bin%’命令来测试下log_bin是否成功开启,命令语句执行如下。
mysql> show variables like '%log_bin%';步骤5: 在master上配置复制所需要的账户,这里创建一个repl的用户。
mysql> grant replication slave on *.* to repl@'%' identified by '123';
mysql> flush privileges;步骤6: 在my.ini配置文件中配置Master主机的相关信息,如下所示。
[mysqld]
log_bin="D:/MySQLlog/binlog"
expire_logs_days = 10
max_binlog_size = 100Mserver-id = 1
binlog-do-db = test
binlog-ignore-db = mysql步骤7: 重启Master主机的MySQL5.6服务,然后输入show master status命令查询Master主机的信息。
mysql> show master status \G;步骤8: 将Master主机的数据备份出来,然后导入到Slave主机中去,具体执行语句如下。
C:\Program Files\MySQL\MySQL Server 5.6\bin>mysqldump –u root -p –h localhost test >c:\a.txt将c:/a.txt拷贝到slave主机上面去,然后执行以下操作:
C:\Program Files\MySQL\MySQL Server 5.6\bin>mysqldump -uroot -proot -hlocalhost
test <c:\a.txt步骤9: 配置Slave主机(192.168.0.206)在C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.6目录下面的配置文件my.ini,具体配置信息如下所示。
[mysql]
default-character-set=utf8
log_bin="D:/MySQLlog/binlog"
expire_logs_days=10
max_binlog_size = 100M[mysqld]
server-id = 2  步骤10: 重启Slave主机(192.168.0.206),在Slave主机(192.168.0.206)的MySQL中执行如下命令,关闭slave服务,执行如下所示。
mysql> stop slave;步骤11: 设置Slave从机实现复制相关的信息。命令执行如下。
mysql> change master to-> master_host='192.168.0.208',-> master_user='repl',-> master_password='123',-> master_log_file='binglog.000003',-> master_log_pos=120;步骤12: 继续执行操作,显示slave从机的状况,如下所示。
mysql> start slave;
mysql> show slave status \G;[18.2.3] Windows环境下主从复制测试步骤1: 在Master主机的MySQL环境下,执行如下命令。
mysql> use test;
mysql> create table rep_test(->   data integer-> );
mysql> insert into rep_test values(2);步骤2: 在Slave主机的MySQL环境下,查看主机刚才添加的表和数据是否成功同步到从机上上,命令执行如下所示。
mysql> use test;
mysql> show tables; mysql> use test;
mysql> show tables;
mysql> select *from rep_test; [18.3.1]  下载并安装MySQL5.6步骤1: 先下载mysql-5.6.10.tar.gz源文件。可以在下载页面http://dev.mysql.com/downloads/mysql/5.6.html#downloads下载mysql-5.6.10.tar.gz源码步骤2: 下载完mysql-5.6.10.tar.gz后,创建MySQL安装程序的目录和数据文件的目录。命令执行如下。
[root@localhost ~]# mkdir -p /usr/local/mysql
[root@localhost ~]# mkdir -p /usr/local/mysql/data
[root@localhost ~]# groupadd mysql
[root@localhost ~]# useradd -r -g mysql mysql步骤3: 解压缩MySQL源代码,这里使用的是cmake2.8.4来编译MySQL源代码。命令执行如下。
[root@localhost ~]# tar -zxvf mysql-5.6.10.tar.gz
[root@localhost ~]# cd mysql-5.6.10
[root@localhost mysql-5.6.10]# cmake .
[root@localhost mysql-5.6.10]# make && make install步骤4: 修改MySQL安装目录设置用户权限。
[root@localhost ~]# chown -R mysql.mysql /usr/local/mysql步骤5: 安装MySQL5.6的源码。命令执行如下。
[root@localhost ~]# cd /usr/local/mysql/scripts
[root@localhost scripts]# ./mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
[root@localhost ~]# cd /usr/local/mysql/support-files
[root@localhost support-files]# cp mysql.server /etc/rc.d/init.d/mysql
[root@localhost support-files]# cp my-default.cnf /etc/my.cnf
[root@localhost ~]# chkconfig --add mysql
[root@localhost ~]# chkconfig mysql on步骤6: 启动MySQL5.6服务。命令执行如下。
[root@localhost ~]# service mysql start步骤7: 在Fedora操作系统中登录MySQL5.6,默认用户root,密码为空,命令执行如下所示。
[root@localhost ~]# mysql[7.3.2]  单机主从复制前的准备工作步骤1: 初始化多实例数据库,首先要停止掉MySQL服务器。命令执行如下。
[root@localhost ~]# service mysql stop步骤2: 把常用到的工具添加到/usr/bin目录,命令执行如下。
[root@localhost~]#ln -s /usr/local/mysql/bin/mysqld_multi /usr/bin/mysqld_multi
[root@localhost~]#ln -s /usr/local/mysql/scripts/mysql_install_db
/usr/bin/mysql_install_db步骤3: 初始化三个数据目录并安装3个mysql服务,命令执行如下。
[root@localhost ~]# cd /usr/local/mysql/
[root@localhost mysql]# mkdir -p /usr/local/var/mysql1
[root@localhost mysql]# mkdir -p /usr/local/var/mysql2
[root@localhost mysql]# mkdir -p /usr/local/var/mysql3
[root@localhost mysql]# ./scripts/mysql_install_db --datadir=/usr/local/var/mysql1 --user=mysql
[root@localhost mysql]# ./scripts/mysql_install_db --datadir=/usr/local/var/mysql2 --user=mysql
[root@localhost mysql]# ./scripts/mysql_install_db --datadir=/usr/local/var/mysql3 --user=mysql步骤4: 从MySQL的源码中把mysqld_multi.server复制到/etc/init.d/目录下,命令执行如下。
[root@localhost ~]# cd /usr/local/mysql/support-files/
[root@localhost support-files]# cp ./mysqld_multi.server /etc/init.d/mysql_multi.server步骤5: 配置数据库配置文件。直接配置/etc/my.cnf,修改相应的属性,如下所示。# The MySQL server
[mysqld_multi]
mysqld          = /usr/local/mysql/bin/mysqld_safe
mysqladmin  = /usr/local/mysql/bin/mysqladmin
user        = root[mysqld1]
port        = 3306[mysqld2]
port        = 3307
socket      = /temp/mysql2.sock
datadir     = /usr/local/var/mysql2[mysqld3]
port        = 3308
socket      = /temp/mysql3.sock
datadir     = /usr/local/var/mysql3[mysqld]步骤6: 查看数据库的状态。命令执行如下。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf report步骤7: 使用mysqld_multi启动MySQL服务器,命令执行如下。
[root@localhost mysql1]# mysqld_multi --defaults-extra-file=/etc/my.cnf stop
[root@localhost mysql1]# mysqld_multi --defaults-extra-file=/etc/my.cnf start
[root@localhost mysql1]# mysqld_multi --defaults-extra-file=/etc/my.cnf report步骤8: 下面测试下MySQL服务器的状态,命令执行如下。
[root@localhost ~]# netstat -an|grep 330 步骤9: 下面登录查看下MySQL数据库,命令执行如下。
[root@localhost data]# mysql -u root -p -P 3306
[root@localhost data]# mysql -u root -p -P 3307
[root@localhost data]# mysql -u root -p -P 3308步骤10: 直接登录MySQL服务器,执行show variable 命令发现三个MySQL服务器的pid_file,socket参数都一样,命令执行如下。
mysql> show variables like 'socket';
mysql> show variables like 'pid%';此时,可以通过登录MySQL服务器自带参数,可以解决以上的问题。命令执行如下所示。
[root@localhost ~]# mysql -u root -S /tmp/mysql2.sock[18.3.3]  mysqld_multi实现单机主从复制步骤1: 使用mysqld_multi开启上一节已经设定好的三个MySQL服务,命令执行如下。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3
[root@localhost ~]# netstat -an|grep 330步骤2: 登录Master主服务器,设置一个复制使用的账户,并授予REPLICATION SLAVE权限。这里创建一个复制用户rep1。
[root@localhost ~]# mysql -u root -p -P 3306
mysql> grant replication slave on *.* to 'repl'@'localhost' identified by '123';
mysql> grant replication slave on *.* to 'repl'@'%' identified by '123';步骤3: 修改Master主数据库服务器的配置文件my.cnf,开启BINLOG,并设置server-id的值。需要重启服务器之后才生效。
[root@localhost ~]#vi /etc/my.cnf
[mysqld1]
port        = 3306
log-bin = /usr/local/var/mysql1/mysql-bin
server-id = 1[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1-3
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3 步骤4: 在Master主服务器上,设置度锁定有效,这个操作为了确保没有数据库操作,以便获得一致性的快照。
[root@localhost ~]# mysql -u root -P 3306 -S /tmp/mysql.sock
mysql> flush tables with read lock;步骤5: 用show master status 命令查看日志情况,查询得到主服务器上当前的二进制日志名和偏移量值。这个操作的目的是为了从数据库启动以后,从这个点开始进行数据的恢复。
mysql> show master status \G;步骤6: 主数据库服务此时可以做一个备份,可以在服务器停止的情况下直接使用系统拷贝命令。
[root@localhost mysql1]#tar –cvf data.tar data步骤7: 主数据库备份完成后,主数据库恢复写操作,命令执行如下。
mysql> unlock tables;
mysql> start slave;步骤8: 接下来继续编辑/etc/my.cnf文件,具体配置项如下。
# The MySQL server
[mysqld_multi]
mysqld          = /usr/local/mysql/bin/mysqld_safe
mysqladmin  = /usr/local/mysql/bin/mysqladmin
user        = root
[mysqld1]
port        = 3306
log-bin     = /usr/local/var/mysql1/mysql-bin
server-id   = 1[mysqld2]
port        = 3307
socket      = /temp/mysql2.sock
datadir     = /usr/local/var/mysql2
log-bin     = /usr/local/var/mysql2/mysql-bin
server-id   = 2[mysqld3]
port        = 3308
socket      = /temp/mysql3.sock
datadir     = /usr/local/var/mysql3
log-bin     = /usr/local/var/mysql3/mysql-bin
server-id   = 3[mysqld]步骤9: 重启Master主服务器,命令执行如下。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1-3
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf report步骤10: 对从数据库服务器做相应设置,此时需要制定复制使用的用户,主数据的IP地址,端口以及开始复制的日志文件和位置等,具体设置如下。
[root@localhost ~]# mysql -uroot -p -P 3307 -S /temp/mysql2.sock
mysql> show variables like '%log_bin%';
mysql> stop slave;
mysql> change master to-> master_host='127.0.0.1',-> master_user='repl',-> master_password='123',-> master_log_file='mysql-bin.000001',-> master_log_pos=120;步骤11: 在从服务器上执行show slave status\G命令查询从服务器的状态,命令执行如下。
mysql> start slave;
mysql> show slave status \G;步骤12: 此时发现从服务器已经成功设置,此时也可以执行show processlist \G命令查询从服务器的进程状态,命令执行如下。
mysql> show processlist \G;步骤13: 此时可以测试复制服务的正确性,在Master主数据库上执行一个更新操作,观察是否在从服务器上同步,下面在主数据库的test库上创建一个测试表,然后插入数据,命令执行如下。
[root@localhost ~]# mysql -uroot -p -P 3306 -S /tmp/mysql.sock
mysql> use test;
mysql> show tables; mysql> create table repl_test(id int);
mysql> insert into repl_test values(1),(2); 步骤14: 在从服务器上检测新的表是否被创建,数据是否同步,执行命令如下。
[root@localhost ~]# mysql -uroot -P 3307 -S /temp/mysql2.sock
mysql> use test;
mysql> show tables;
mysql> select * from repl_test; [18.3.4]  不同服务器之间实现主从复制步骤1: 确保主从服务器上安装了相同版本的数据库,设定主服务器的IP是192.168.1.100,从服务器的IP是192.168.1.101。步骤2: 登录主服务器,设置一个复制使用的账户,并授予REPLICATION SLAVE权限。这里创建一个复制用户rep1。
mysql> grant replication slave on *.* to 'rep1'@'192.168.1.101' identified by '123';步骤3: 修改主数据库服务器的配置文件my.cnf,开启BINLOG,并设置server-id的值。需要重启服务器之后才生效。
my.cnf中修改
[mysqld]
log-bin = /usr/local/var/mysql1/mysql-bin
server-id = 1步骤4: 在主服务器上,设置度锁定有效,这个操作为了确保没有数据库操作,以便获得一致性的快照。
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)步骤5: 查询主服务器上当前的二进制日志名和偏移值。
mysql> show master status;步骤6: 主数据库停止更新操作,需要生成数据库的备份,可以通过mysqldump导出数据或者使用ibbackup工具进行数据库的备份,主数据库备份完成后,主数据库恢复写操作,命令执行如下。
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)步骤7: 修改从数据库的配置文件my.cnf,增加server-id参数。
my.cnf
[mysqld]
Server-id = 2 步骤8: 修改从数据库的配置文件my.cnf,增加server-id参数。Server-id的值唯一的,不能和主数据库的配置相同,如果有多个从数据库,每个从数据库都必须有自己唯一的server-id值。
[root@localhost ~]# mysqld_safe --skip-slave-start &步骤9: 对从数据库服务器做相应的设置,指定复制使用的用户,主数据库服务器的IP、端口以及开始执行复制的日志文件和位置定,命令执行如下。
mysql> stop slave; mysql> change master to-> master_host='192.168.1.100',-> master_user='rep1',-> master_password='123',-> master_log_file='mysql-bin.000029',-> master_log_pos=109; 步骤10: 在从服务器上,启动slave线程。
mysql> start slave;步骤11: 在从服务器上执行show slave status\G命令查询从服务器的状态。
mysql> show slave status\G;
此时也可以执行show processlist \G命令查询从服务器的进程状态。
mysql> show processlist \G;[18.3.6]  指定复制的数据库或者表1. replicate-do- table和replicate-ignore-table的用法。
步骤1: 启动主从数据库,首先在主数据库test库中创建两个表,rep_t1和rep_t2表。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3
[root@localhost ~]# mysql -uroot -p -P 3306 -S /tmp/mysql.sockmysql> show databases;
mysql> show tables;
mysql> select * from rep_t1;
mysql> select * from rep_t2; 步骤2: 关闭数据库服务器,编辑从数据库配置参数replicate-do-table=test.rep_t1指定test数据库中的rep_t1表被复制,replicate-ignore-table=test.rep_t2指定test库中的rep_t2表不会被复制数据。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1-3Vi /etc/my.cnf
[mysqld2]
...
port        = 3307
socket      = /temp/mysql2.sock
server-id = 2
replicate-do-table=test.rep_t1
replicate-ignore-table=test.rep_t2步骤3: 启动主从服务器,命令执行如下。
mysql> start slave;
mysql> show slave status\G;步骤4: 主从服务器都成功启动后,下面开始更新主数据库test库中的rep_t1表和rep_t2表,修改主数据库中的数据如下。
mysql> insert into rep_t1 values(888);
mysql> insert into rep_t2 values(888);步骤5: 登录从数据库,查询test库中的表rep_t1和rep_t2的数据更新的情况,具体查询语句如下。
[root@localhost ~]# mysql -u root -P 3307 -S /temp/mysql2.sock
mysql> use test;
mysql> show tables;
mysql> select * from rep_t1;
mysql> select * from rep_t2;2.replicate-do-db和replicate-ignore-db的用法。步骤1: 启动主从数据库服务器,查询主数据库中的主要有哪些数据库库,命令执行如下。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3
[root@localhost ~]# mysql -uroot -P 3306 -S /tmp/mysql.sock
mysql> show databases; 步骤2: 使用mysqldump工具将主数据库中的所有信息导出到all.sql脚本文件中。
[root@localhost ~]# mysqldump -u root -P 3306 -S /tmp/mysql.sock --all-databases >all.sql步骤3: 登录从数据库,导入all.sql中的数据,保持从服务器与主数据库数据一致。
[root@localhost ~]# mysql -uroot -P 3307 -S /temp/mysql2.sock
mysql> show databases;
mysql> source ./all.sql
mysql> show databases; 步骤4: 关闭从数据库,然后编辑数据库的配置文件,replicate-do-db表示从服务器可以复制的数据库的名字,如果有多个数据库,那么可以重复写多个replicate-do-db配置,replicate-ignore-db表示从服务器复制过程中忽略复制该配置设置的数据库名称。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1-3vi /etc/my.cnf
[mysqld2]
....
port        = 3307
socket      = /tmp/mysql2.sock
server-id = 2
#replicate-do-table=test.rep_t1
#replicate-ignore-table=test.rep_t2
replicate-do-db=test
replicate-do-db=cc
replicate-ignore-db=tt步骤5: 启动主从数据库,然后在主数据库cc库中增加表cc_t1表,在tt库中增加表tt_t1表。
[root@localhost ~]# mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3
mysql> use cc;
mysql> create table cc_t1(data int);
mysql> use tt;
mysql> create table tt_t1(data int);步骤6: 登录从数据库,查询数据库cc库和tt库相应的数据是否更新。
[root@localhost ~]# mysql -uroot -P 3307 -S /tmp/mysql2.sock
mysql> show databases;
mysql> use cc;
mysql> show tables;
mysql> use tt;
mysql> show tables;[18.4]  查看Slave的复制进度 步骤1: 在主服务器上插入一个包含当前时间戳的记录,命令执行如下。
mysql> alter table rep_t3 add column createtime datetime;
mysql> insert into rep_t3 values(1,now());
mysql> select * from rep_t3;步骤2: 从服务器的IO线程停止下来,使得从数据库服务器暂时不写中继日志,停止时执行的SQL就是最后执行的SQL,命令执行如下。
mysql> stop slave;
mysql> select * from rep_t3;
mysql> select now();步骤3: 从数据库服务器上执行show processlist查看SQL线程的时间,这个时间说明了主服务器最后执行的更新操作大概是主服务器46秒前的更新操作,命令执行如下。
mysql> stop slave io_thread;
mysql> show processlist \G;18.5.1  了解服务器的状态步骤1: 一般使用show slave status命令来检查从服务器,如下例所示。
mysql> show slave status\G;18.5.2  服务器复制出错的原因问题一:出现”log event entry exceeded max_allowed_pack”错误。
如果在应用中出现使用大的BLOG列或者长字符串,那么在从服务器上回复时,可能会出现”log event entry exceeded max_allowed_pack”的错误,这是因为含有大文本的记录无法通过网络进行传输而导致错误,解决方法是在主从服务器上添加max_allowed_packet参数,该参数默认设置是1MB,如下。
mysql> SHOW VARIABLES LIKE 'MAX_ALLOWED_PACKET';
mysql> SET @@global.max_allowed_packet=16777216;问题二:多主复制时的自增长变量冲突问题。
大多数情况下使用一台主服务器对一台或者多台从服务器,但是在某些情况下,可能会存在多个服务器配置为复制主服务器,使用auto_increment时应采取特殊步骤以防止键值冲突,否则插入行时多个主服务器会视图使用相同的auto_increment值。步骤1: 创建表auto_t,系统默认的auto_increment_increment和auto_increment_offset参数都是1,增加数据默认的也是增加幅度为1增加,命令执行如下。
mysql> create table auto_t( data int primary key auto_increment )engine=myisam default charset=gbk;
mysql> show variables like 'auto_inc%';
mysql> insert into auto_t values(null),(null),(null);
mysql> select * from auto_t;步骤2: 重新设置参数auto_increment_increment的值为10,然后插入数据,命令执行如下。
mysql> set @@auto_increment_increment=10;
mysql> show variables like 'auto_inc%';
mysql> insert into auto_t values(null),(null),(null);
mysql> select * from auto_t;步骤3: 重新设置参数auto_increment_offset的值为5,再插入数据,命令执行如下。
mysql> set @@auto_increment_offset=5;
mysql> insert into auto_t values(null),(null),(null);
mysql> select * from auto_t;[18.6]  切换主从服务器步骤1: 首先要确保所有的从数据库都已经执行了relay log中的全部更新,看从数据库的状态是否是Has read all relay log,是否更新都已经执行完成。
mysql> stop slave IO_THREAD;
mysql> SHOW PROCESSLIST \G;步骤2: 在从数据库B上停止slave服务,然后执行reset master重置成主数据库。
mysql> stop slave;
mysql> reset master; 如果binlog没有设置,此时需要配置log-bin,在[mysql2]后面的配置选项添加log-bin选项,修改如下所示。
[mysqld2]
…
log-bin = /usr/local/var/mysql2/mysql-bin
配置完成后,重启数据库服务,登录数据库B,然后执行如下命令开启主数据库功能.
mysql> stop slave;
mysql> reset master; 步骤3: 在从数据库B上添加具有replication权限的用户rep1,查询主数据库状态,命令执行如下。
mysql> grant replication slave on *.* to 'rep1'@'localhost' identified by '123';
mysql> show master status;步骤4: 在从数据库C上配置复制的参数,具体配置如下。
mysql> change master to-> master_host='127.0.0.1', -> master_user='rep1',-> master_password='123',-> master_port=3307,-> master_log_file='mysql-bin.000002',-> master_log_pos=98;
mysql> start slave;步骤5: 在从数据库C上执行show slave status命令查看从数据库服务是否成功启动。
mysql> show slave status \G;步骤6: 在主数据库B和从数据库C上面测试数据库是否成功设置复制功能,首先查看主数据库B中test库中的表的情况,命令执行如下。
mysql> use test;
mysql> show tables;步骤7: 在主数据库B中增加表rep_t3,命令执行如下。
mysql> create table rep_t3(data int);步骤8: 在从数据库C中查询,看表是否成功复制到从数据库,命令执行如下。
mysql> show tables;

第19章 例题

[19.2]  Linux环境下MySQL Cluster安装和配置步骤1: 系统默认的网卡端口是eth0,这里使用的是eth2,首先编辑eth2的配置文件,设置IP地址、子网掩码和网关的配置信息。
[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# vi ifcfg-eth2步骤2: 使用ifconfig命令查看eth2端口IP地址是否成功设置,然后重新启动网络。
[root@localhost network-scripts]# ifconfig eth2
[root@localhost network-scripts]# service network restart步骤3: 使用chkconfig命令设置网卡进入系统时启动。想要每次开机就可以自动获取IP地址,此时需要开启服务,使用chkconfig命令是让网络服务在系统启动级别是2345时默认启动。
[root@localhost network-scripts]# chkconfig --level 2345 network on
[root@localhost network-scripts]# service network start步骤4: 将NetworkManager服务关闭掉,然后重启网络服务。
[root@localhost network-scripts]# chkconfig --level 0123456 NetworkManager off
[root@localhost network-scripts]# service NetworkManager stop
[root@localhost network-scripts]# service network stop
[root@localhost network-scripts]# service network start
[root@localhost ~]# ifconfig
[root@localhost ~]# ping 192.168.0.101[19.2.1] 安装MySQL Cluster7.2.8软件步骤1: 直接把之前源码安装的MySQL程序删除掉。
[root@localhost mysql]# cd /usr/local
[root@localhost local]# ls
[root@localhost local]# rm -rf mysql步骤2: 登录http://dev.mysql.com/downloads/cluster/#downloads网址,下载MySQL Cluster 7.2.8步骤3: 下载好mysql-cluster-gpl-7.2.8-linux2.6-i686.tar.gz文件之后,先对其进行解压缩。
[root@localhost ~]# gunzip  mysql-cluster-gpl-7.2.8-linux2.6-i686.tar.gz
[root@localhost ~]# tar -xvf mysql-cluster-gpl-7.2.8-linux2.6-i686.tar 步骤4: 假设每个节点计算机上都采用mysql用户来运行MySQL Cluster,首先添加mysql组,然后添加mysql用户。
[root@localhost ~]# groupadd mysql
[root@localhost ~]# useradd mysql -g mysql步骤5: 开始安装MySQL Cluster。
[root@localhost ~]# mkdir /usr/local/mysql-cluster
[root@localhost ~]# mv mysql-cluster-gpl-7.2.8-linux2.6-i686/*/usr/local/mysql-cluster/
[root@localhost ~]# cd /usr/local/mysql-cluster
[root@localhost mysql-cluster]# chown -R root .
[root@localhost mysql-cluster]# ls
[root@localhost mysql-cluster]# chown -R mysql ./data
[root@localhost mysql-cluster]# chown -R mysql .
[root@localhost mysql-cluster]# ./scripts/mysql_install_db --user=mysql提示错误信息:libaio.so.1: cannot open shared object file: No such file or directory。安装过程中可能缺少的 libaio 安装文件而导致的问题,接下来,安装该程序,操作如下。
[root@localhost ~]# rpm -ivh libaio-0.3.96-3.i386.rpm
[root@localhost ~]# cd /usr/local/mysql-cluster/
[root@localhost mysql-cluster]# ./scripts/mysql_install_db --user=mysql步骤6: 从上面安装信息可以发现To start mysqld at boot time you have to copy support-files/mysql.server to the right place for your system,接下来,首先创建my.cnf文件,并且开始初始化数据库,接着需要配置mysql服务,然后启动服务。
[root@localhost mysql-cluster]# cp ./support-files/my-medium.cnf /etc/my.cnf
cp: overwrite `/etc/my.cnf'? y
[root@localhost mysql-cluster]#
[root@localhost mysql-cluster]# cd /etc/init.d
[root@localhost init.d]# ln –s/usr/local/mysql-cluster/support-files/mysql.server /etc/init.d/mysql.server步骤7: 设置MySQL服务为自动启动服务。
[root@localhost ~]# cd /usr/local
[root@localhost local]# ln -s mysql-cluster mysql
接下来编辑/etc/profile环境配置文件,在该文件最后加上如下的两句配置信息。
[root@localhost ~]# vi /etc/profile
PATH=$PATH:/usr/local/mysql-cluster/bin
export PATH步骤8: 使用chkconfig 增加新的一项服务,系统从其之后服务自动运行。
[root@localhost ~]# cd /etc/rc.d/init.d/
[root@localhost init.d]# ls -al |grep mysql
lrwxrwxrwx  1 root root    51 2012-10-27 12:35 mysql.server -> /usr/local/mysql-cluster/support-files/mysql.server
[root@localhost init.d]# chkconfig --add mysql.server
[root@localhost local]# service mysql.server start步骤9: 简单的测试下当前的MySQL版本是否支持Cluster。
[root@localhost init.d]# mysql
mysql> show variables like '%ndb%';[19.2.2] 管理节点配置步骤步骤1: 拷贝/usr/local/mysql-cluster/bin/ndb_mgm,ndb_mgmd两个文件到/usr/local/bin目录下面去。
[root@localhost ~]# cd /usr/local/mysql-cluster/bin/
[root@localhost bin]# cp ./ndb_mgm* /usr/local/bin步骤2: 在管理节点服务器192.168.0.10的/var/lib/下创建目录mysql-cluster,并在该目录下面创建配置文件config.ini。
[root@localhost ~]# cd /var/lib
[root@localhost lib]# mkdir mysql-cluster
[root@localhost lib]# cd mysql-cluster/
[root@localhost mysql-cluster]# touch config.ini步骤3: 配置集群的测试环境,config.ini文件的配置信息如下。
[ndbd default]
NoOfReplicas=1                         #每个数据节点的镜像数量
DataMemory=200M                    #每个数据节点中给数据分配的内存
IndexMemory=20M                    #每个数据节点中给索引分配的内存
[ndb_mgmd]                          #配置管理节点
NodeId=1
hostname=192.168.0.100
datadir=/var/lib/mysql-cluster/    #管理节点数据(日志)目录
[ndbd]                              #数据节点配置
NodeId=2
hostname=192.168.0.101
datadir=/usr/local/mysql/data/     #数据节点目录
[ndbd]
NodeId=3
hostname=192.168.0.102
datadir=/usr/local/mysql/data/
[mysqld]
hostname=192.168.0.101
[mysqld]
hostname=192.168.0.102
[mysqld]                            # Options for mysqld process[19.2.3] 配置SQL节点和数据节点
SQL节点和数据节点的配置比较简单,只需要在MySQL Server的配置文件 my.cnf 中增加如下内容即可 # The MySQL server
[mysql_cluster]
ndb-connectstring=192.168.0.100        #数据节点定位管理节点的IP地址[mysqld]
Ndbcluster                          #运行NDB存储引擎
ndb-connectstring=192.168.0.100        #定位管理节点
port        = 3306
socket      = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16M
max_allowed_packet = 1M
table_open_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M[19.3.1]  Cluster的启动 步骤1: 在管理节点(192.168.0.100)上使用ndb_mgmd命令启动管理节点进程。
[root@localhost ~]# cd /var/lib/mysql-cluster/
[root@localhost mysql-cluster]# ndb_mgmd -f ./config.ini
MySQL Cluster Management Server mysql-5.5.27 ndb-7.2.8
[root@localhost mysql-cluster]# ps -ef |grep ndb步骤2: 启动IP地址为192.168.0.101和192.168.0.102的数据节点服务器服务,如果是第一次启动,则需要添加--initial参数,以便进行ndb节点的初始化工作。值得注意的是,在以后的启动过程中,是不能添加--initial参数的,否则ndbd程序会清除在之前建立的所有用于恢复的数据文件盒日志文件,如下所示。
[root@localhost bin]# ndbd --initial启动数据节点发生问题,连接不上,尝试关闭操作系统防火墙。
[root@localhost ~]# /etc/init.d/iptables stop
[root@localhost ~]# /sbin/chkconfig --level 2345 iptables off下面重新启动数据节点,效果如下所示。
[root@localhost bin]# ndbd --initial步骤3: 启动IP地址为192.168.0.101和192.168.0.102的SQL节点服务器服务,如下所示。
[root@localhost local]# service mysql.server start步骤4: 节点全部成功启动之后,用ndb_mgm工具查看集群的状态。
[root@localhost ~]# ndb_mgm
ndb_mgm> show19.3.2  Cluster的测试1. 测试NDB数据引擎
步骤1: 在其中一个IP地址为192.168.0.101的SQL节点的test库中创建存储引擎为NDB的表t,然后插入两条数据。
mysql> use test;
Database changed
mysql> create table t(->   data integer-> )engine = ndb; mysql> insert into t values(1);
mysql> insert into t values(2);步骤2: 在其中一个IP地址为192.168.0.102中查询test库中的t1表,看下两个SQL节点的数据是否是一致的。
mysql> select * from t;步骤3: 在SQL节点192.168.0.101上将测试表t的存储引擎改为MyISAM,再次插入测试输入,执行如下。
mysql> alter table t engine=myisam;
mysql> insert into t values(3);步骤4: 在SQL节点192.168.0.102上重新查询表t,如下。
mysql> select * from t;步骤5: 在SQL节点192.168.0.101上将测试表t的存储引擎改为NDB,如下。
mysql> alter table t engine=ndb;步骤6: 在SQL节点192.168.0.102上再次查询表t,结果如下。
mysql> select * from t;2. SQL节点故障测试步骤1: 将IP地址为192.168.0.101服务器上的MySQL服务停止。
[root@localhost mysql-cluster]# service mysql.server stop步骤2: 用ndb_mgm工具查看集群的状态。
[root@localhost ~]# ndb_mgm
ndb_mgm> show步骤3: 在IP地址为192.168.0.102的计算机上查看表t1。
mysql> select * from t;19.3.3 Cluster的关闭
MySQL Cluster关闭只需要使用ndb_mgm命令。执行如下所示。
[root@localhost mysql-cluster]# ndb_mgm -e shutdown同时也可以使用ndb_mgm工具进入管理界面后,使用shutdown命令。执行如下所示。
[root@localhost mysql-cluster]# ndb_mgm
ndb_mgm> shutdown19.4 维护MySQL Cluster[root@localhost ~]# ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
ndb_mgm> help也可以通过在help 后面接命令的名称,获取该命令的相关信息,如下所示。
ndb_mgm> help status19.4.1  Cluster的日志的管理
MySQL Cluster提供了两种日志,集群日志(clusterlog)主要是用来记录所有Cluster节点生
成的日志,节点日志(node log)记录了数据节点的本地时间。通常采用集群日志,集群日志记录了所有节点的数据,更方便进行管理,集群日志记录在config.ini同一个目录下面,测试环境是在/var/lib/mysql-cluster/目录下面,文件格式为ndb_<nodeid>_cluster.log,详细信息如下所示。[root@localhost mysql-cluster]# cd /var/lib/mysql-cluster/
[root@localhost mysql-cluster]# ls
config.ini  ndb_1_cluster.log  ndb_1_out.log  ndb_1.pid
[root@localhost mysql-cluster]# cat ndb_1_cluster.log通常可以使用ndb_mgm客户端管理日志信息,如下所示。步骤1: 在终端执行ndb_mgm命令,输入clusterlog info命令查询当前日志状态。
[root@localhost ~]# cd /var/lib/mysql-cluster/
[root@localhost mysql-cluster]# ndb_mgm
ndb_mgm> clusterlog info步骤2: 执行clusterlog off命令关闭日志。
ndb_mgm> clusterlog off
ndb_mgm> clusterlog info步骤3: 执行clusterlog on命令开启日志。
ndb_mgm> clusterlog on
ndb_mgm> clusterlog info[19.4.2]  Cluster的联机备份使用管理服务器进行Cluster物理备份,首先需要启动管理服务器(ndb_mgm),并执行”start backup”命令启动备份,具体执行如下所示。
ndb_mgm> start backup;
如果在备份的过程中想终止备份可以使用如下的命令。
[root@localhost mysql-cluster]# ndb_mgm
ndb_mgm> abort backup node_id 在IP地址为192.168.0.101的数据节点下,可以看到以下的数据文件。
[root@localhost ~]# cd /usr/local/mysql/data/BACKUP/BACKUP-1
[root@localhost BACKUP-1]#ls
在IP地址为192.168.0.102的数据节点下,可以看到以下的数据文件。
[root@localhost ~]# cd /usr/local/mysql/data/BACKUP/BACKUP-1
[root@localhost BACKUP-1]#ls [19.4.3]  Cluster的数据恢复步骤1: 备份之前,首先创建测试表t,然后添加若干条记录,如下所示。
mysql> select count(*) from t;步骤2: 在管理节点上执行start backup进行数据备份。
ndb_mgm> start backup;步骤3: 在IP地址为192.168.0.101的数据节点上执行如下数据还原的命令,如下所示。
[root@localhost mysql-cluster]# ndb_restore -b 3 -n 2 -c host=192.168.0.100:1186 –m –r /usr/local/mysql/data/BACKUP/BACKUP-3步骤4: 在IP地址为192.168.0.102的数据节点上执行如下数据还原的命令,如下所示。
[root@localhost mysql-cluster]# ndb_restore -b 3 -n 3 -c host=192.168.0.100:1186 –m –r /usr/local/mysql/data/BACKUP/BACKUP-319.5  Wndows操作系统中配置Cluster集群步骤1: MySQL Cluster的下载
配置集群需要使用MySQL Cluster满足集群要求,MySQL Cluster支持Linux、Mac OS X、Solaris和Windows操作系统。
MySQL Cluster的下载地址是http://www.mysql.com/downloads/cluster步骤2: 管理节点的安装配置
管理节点安装在C盘下,在IP地址为192.168.0.208的机器上创建目录c:/mysql/bin、c:/mysql/mysql-cluster和c:/mysql/bin/cluster-logs目录,然后将安装包解压后的mysql/bin目录中的ndb_mgmd.exe和ndb_mgm.exe复制到IP地址为192.168.0.208的c:/mysql/bin目录下。然后在192.168.0.208的c:/mysql/bin下生成my.ini和config.ini两个文件。
my.ini的配置信息如下:
[mysql_cluster]
#Option for management node process
config-file=C:/mysql/bin/config.ini
config.ini的配置信息如下:
[ndbd default]
NoOfReplicas=2                                 #每个数据节点的镜像数量
DataDir=D:/Program Files/mysqlcluster/datanode/mysql/bin/cluster-data
DataMemory=80M                              #每个数据节点中给数据分配的内存
IndexMemory=18M                             #每个数据节点中给索引分配的内存[ndb_mgmd]
HostName=192.168.0.208                         #管理节点的IP地址
DataDir=C:/mysql/bin/cluster-logs           #管理节点日志文件的目录 [ndbd]
HostName=192.168.0.102                         #192.168.0.102的主机作为数据节点[ndbd]
HostName=192.168.0.206                      #192.168.0.206的主机作为数据节点[mysqld]
HostName=192.168.0.102                      #192.168.0.102的主机作为SQL节点
[mysqld]
HostName=192.168.0.206                      #192.168.0.206的主机作为SQL节点步骤3: 数据节点的安装配置
将IP地址为192.168.0.102和192.168.0.206的两台机器同时作为SQL节点,在IP地址为192.168.0.206的计算机上创建以下目录结构。
D:/Program Files/mysqlcluster/datanode/mysql/bin
D:/Program Files/mysqlcluster/datanode/mysql/cluster-data
D:/Program Files/mysqlcluster/datanode/mysql/bin/cluster-data此时需要在下载的目录解压之后的文件mysql/bin中将ndbd.exe复制到192.168.0.206的D:/Program Files/mysqlcluster/datanode/mysql/bin目录下。接下来需要在该目录(D:/Program Files/mysqlcluster/datanode/mysql/bin)下创建my.ini文件,my.ini的配置信息如下:
[mysql_cluster]
ndb-connectstring=192.168.0.208                #定位管理节点步骤4: SQL节点的安装配置
在IP地址为192.168.0.206的计算机上创建D:/Program Files/mysqlcluster/sqlnode目录,然后将下载解压后的文件夹mysql直接整个复制到D:/Program Files/mysqlcluster/sqlnode目录下面,然后在D:/Program Files/mysqlcluster/sqlnode/mysql下面创建my.ini文件,my.ini的配置信息如下:
[mysqld]
ndbcluster                                  #运行 NDB存储引擎
ndb-connectstring=192.168.0.208                #定位管理节点步骤5: 启动管理节点
启动各个节点是有顺序的,先是Management node,然后是Data nodes,最后是SQL nodes。
首先在IP地址为192.168.0.208的主机上打开命令窗口,切换到C:\mysql\bin目录下面,输入:
C:\Documents and Settings\Administrator>cd c:\mysql\bin
C:\mysql\bin>ndb_mgmd -f config.ini --configdir=c:\mysql\mysql-cluster步骤6: 启动数据节点
在IP地址为192.168.0.206的主机中打开一个新的命令行窗口,切换到目录D:/Program Files/mysqlcluster/datanode/mysql/bin,输入如下命令:
D:\Program Files\mysqlcluster\datanode\mysql\bin>ndbd -c 192.168.0.208
下面在IP地址为192.168.0.208的主机上使用ndb_mgm命令测试发现没有成功连接上数,如下:
C:\mysql\bin>ndb_mgm
ndb_mgm> all status步骤7: 启动SQL节点
在IP地址为192.168.0.206的主机中打开一个新的命令行窗口,切换到目录D:/Program Files/mysqlcluster/sqlnode/mysql/bin,输入如下命令:
D:\Program Files\mysqlcluster\sqlnode\mysql\bin>mysqld --console接下来,可以在管理节点192.168.0.208这台计算机上,在命令窗口切换到c:/mysql/bin目录下输入以下命令来检测数据节点和SQL节点是否成功连接,如下所示:
C:\mysql\bin>ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show步骤8: 下面进行简单的SQL节点数据同步测试
首先,在IP地址为192.168.0.102机器上面登录MySQL Server,然后创建数据引擎为ndb的测试表t,并添加一条记录,如下所示。
D:\Program Files\mysqlcluster\sqlnode\mysql\bin>mysql
mysql> use test;
mysql> show tables;
mysql> create table t(->   id integer,->   data varchar(20)-> )engine=ndb;
mysql> insert into t values(1,'a');
mysql> commit;
mysql>接下来,登录IP地址为192.168.0.206的计算机,查看节点数据是否同步,如下所示。
D:\Program Files\mysqlcluster\sqlnode\mysql\bin>mysql
mysql> use test;
mysql> show tables;
mysql> show tables;
mysql> select * from t;

2022年7月4日
青海·西宁

基于《MySQL5.7从入门到精通》学习记录(20220608_持续更新)相关推荐

  1. Android 学习记录(持续更新)

    Android 学习记录(持续更新) 1.AndroidManifest.xml 详解: http://www.jb51.net/article/73731.htm (AndroidManifest. ...

  2. C#程序设计--入门到精通 学习记录(一) C# 与 .net平台

    之前在学校的时候学习了C语言,这段时间想学一下C# 在学习之前需要先弄明白 C/C++/C# 他们三个直接的区别和联系: 1.C是完全面向过程的语言,用于开发规模较小的程序效率很高,但是程序较大,就显 ...

  3. <极客时间:零基础入门Spark> 学习笔记(持续更新中...)

    看的是极客时间的课,讲得很不错 零基础入门 Spark (geekbang.org) 基础知识 01 Spark:从"大数据的Hello World"开始 准备工作 IDEA安装S ...

  4. Django 入门(个人学习笔记,持续更新)

    导语:这些笔记都是结合自己的学习和查找网上的资料笔记或者回答上整理,可能有很多内容类似,目的是为了让自己以后忘了知识点可以看自己写的笔记,第一次写技术笔记,多多包涵. MVC 大部分开发语言中都有MV ...

  5. Android Performance Patterns 系列视频学习记录(持续更新中)

    系列文章旨在记录YouTube上谷歌发布的Android Performance Patterns系列视频,一共79个视频,每个视频也就几分钟.当然对于大部分安卓开发者来说,这些都是基础,可能你会说, ...

  6. FORTRAN学习记录(持续更新)

    FORTRAN: .f的后缀,表示固定格式: .f90的后缀,表示自由格式. 固定格式用'C'开头(必须在行首)表示注释+C后面用tab缩进,否则编译错误. 自由格式用'!'开头表示注释,!后面不用缩 ...

  7. Uuntu16 学习记录(持续更新中......)

    Top Chunk: 概念:当一个chunk处于一个arena的最顶部(即最高内存地址处)的时候,就称之为top chunk. 作用:该chunk并不属于任何bin,而是在系统当前的所有free ch ...

  8. Revit二次开发从入门到精通学习之路, (含Revit二次开发教程下载)

    Revit二次开发从入门到精通学习之路 Autodesk Joe Ye叶雄进 2. 18 2014    yexiongjin@hotmail.com Revit在国内的应用越来越广泛, Revit ...

  9. 第1课 EOS开发从入门到精通学习导航

    第1课 EOS开发从入门到精通学习导航 柚子(EOS)可以理解为Enterprise Operation System,即为商用分布式应用设计的一款区块链操作系统.EOS是EOS软件引入的一种新的区块 ...

  10. python web开发入门_python大佬整理的python web开发从入门到精通学习笔记

    原标题:python大佬整理的python web开发从入门到精通学习笔记 Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象.直译式电脑编程语言,也是一种功能强大的通 ...

最新文章

  1. python 分布式锁_python分布式锁
  2. php100并发cpu告警,多线程并发导致CPU100%的一种原因和解决办法
  3. java not a jpeg file_javax.imageio.IIOException: Not a JPEG file: starts with 0x47 0x49
  4. PHP SESSION生存时间设置
  5. vue中先加载数据后加载页面
  6. 简述:bs和cs的区别
  7. 获取设备的sn号,mac地址以及IP地址
  8. 市场调查报告写作的基本要求
  9. 为什么visio输出图片俩边有留白_Microsoft Office Visio导出图片添加边界的操作教程...
  10. openfoam一些报错的原因(持续更新)
  11. 如何用循环执行玩转自定义企业微信机器人?
  12. UFS详细介绍---终章
  13. 计算机未检测到任何网络硬件,电脑提示windows没有检测到任何网络硬件怎么办...
  14. 3.1.hole_behind_comprehensive_teaching_complex 综教楼后的那个坑
  15. [MdSQL]表的增删查改(进阶)
  16. {0}:{1:.4f}“.format(是什么意思 Python字符串格式化 (%占位操作符)
  17. format转换方法
  18. css文本框圆角不兼容,CSS教程之重置默认样式与IE兼容圆角的解决方法
  19. RFID智能仓储管理解决方案,智能化仓储管理-新导智能
  20. ngss for oracle,学习笔记:Oracle bbed工具在Windows平台上兼容9i 10g 11g 12c运

热门文章

  1. SEO_关键词研究工具
  2. 金蝶记账王和易记账哪个好_金蝶易记账和记账王的区别是什么?金蝶易记账的具体操作如下...
  3. vs2017 html安装,解决vs2017无法安装问题
  4. 上海行政区划经纬度地图_全国行政区划2017省市区完整版附经纬度及拼音
  5. mysql ---- 全文索引:中文语义分词检索
  6. 项目管理-项目启动会
  7. html生成一维码,一维码条形码生成工具
  8. linux 小巧的浏览器,Linux奇技淫巧:一款特别轻量级的网页浏览器
  9. 万字长文,解密秒杀架构!(建议收藏)
  10. 办公技巧分享:如何编辑PDF文件内容