本文主要介绍了关于mysql数据库的部分基础知识,仅供初学者参考,很小一部分内容摘自网上前辈,已添加原链接供大家浏览。文章较长,都是个人学习总结,由于时间仓促,部分内容略显空洞,但还是希望给屏幕前的你带来帮助(^_−)☆。
数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、截取、更新、删除等操作。
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。
本文主要介绍MySQL数据库的一些基本知识。
mysql -uroot -p密码
net start mysql
net stop mysql
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
通过SQL语言可以操作所有的关系型数据库,但是每种数据库之间都会有一定的差异,我们称之为“方言”。
DDL(Data Definition Language):数据定义语言
用来定义数据库对象:库、表、列等
DML(Data Manipulation Language):数据操作语言
用来定义数据库记录(增删改)
DCL(Data Control Language):数据控制语言
用来定义访问权限和安全级别
DQL(Data Query Language):数据查询语言
用来查询记录(数据)
返回顶部
注意SQL语言标签不区分大小写,但是数据库对象名最好前后保持一致。
操作数据库
CREATE DATABASE 数据库名;
DROP DATABASE 数据库名;
ALTER DATABASE 数据库名 CHARACTER SET 要修改的字符集名称;
SHOW DATABASES;
SHOW CREATE DATABASE 数据库名称;
操作表
先来看一些常见的列类型:
列类型 | 中文解释 |
---|---|
int | 整型 |
double | 浮点型 |
char | 固定长度字符串类型 |
varchar | 可变长度字符串类型 |
text | 字符串类型 |
bolb | 字节类型 |
date | 日期类型 yyyy-MM-dd |
datetime | 日期时间类型 yyyy-MM-dd hh:mm:ss |
time | 时间类型 |
timestamp | 时间戳类型 默认为系统当前时间 |
有时我们会在列类型字段后面加上括号使其完整,比如double(5,2)表示最多5位,其中必须有2位小数,即最大值为999.99;char(2)表示限定两个字符。
在创建数据库之前,你应该想清楚数据库结构:你需要什么数据库表,各数据库表中有什么样的列。
下面我们来举例说明怎样建立一个表,比如我们要用一张表存储所有的学生信息:
CREATE TABLE students(
sid int,
sname varchar(20),
sage int,
ssex char(1)
);
这样就创建了一个简单的学生表,每个学生都有id,姓名,年龄,性别。
varchar 类型是可变长度的字符串类型,很适合于name列,因为列值是变长的。这些列的长度不必都相同,而且不必是20。你可以挑选从1到65535的任何长度,从中选择一个最合理的值。如果后面你觉得长度不够用,还可以通过SQL语句ALTER TABLE
来修改。
删除表 DROP TABLE 表名;
修改表
添加列
比如我们要给上面的students增加一个 班级 列:
ALTER TABLE students ADD (class varchar(10));
修改列类型
修改学生表中的性别列为char(2):
ALTER TABLE students MODIFY ssex CHAR(2);
修改列名
修改ssex 为sex
`ALTER TABLE students CHANGE ssex sex CHAR(2);`
删除列
ALTER TABLE students DROP sid;
查询表
SHOW TABLES;
查询该数据库下的所有表名称;
DESC 表名;
查询表结构。
注意,以上的操作都是基于选择一个数据库使用之上USE 数据库名;
即可。
返回顶部
我们先创建一个学生表:
CREATE TABLE students(
sid int,
sname varchar(20),
sage int,
ssex char(1)
);
给表中添加数据:
INSERT INTO students (sid,sname,sage,ssex) VALUES(1,'张三',19,'男');
列名要和后面的值匹配上,写几个列名,就要赋几个值。
注意,字符类型和日期类型赋值时要用引号括起来,单引号还是双引号没有要求。
简写形式:
INSERT INTO students VALUES(1,'张三',19,'男');
这么写必须给所有的列都赋上值,不想赋值的就写null,否则会报错。
删除表中数据:
删除表中所有数据
DELETE FROM 表名;
删除部分数据
DELETE FROM 表名 WHERE 条件;
TRUNCATE 删除数据
TRUNCATE TABLE 表名;
这么做会删除所有记录,先删除表,再创建表。
修改表中数据
UPDATE 表名 SET 列名1=值1,列名2=值2…… WHERE 条件;
比如我们要修改张三的数据:
UPDATE students SET sid=0,sage=20 WHERE sname='张三';
返回顶部
SELECT
selection_list /*要查询的列名称*/
FROM
table_list /*要查询的表名称*/
WHERE
condition /*行条件*/
GROUP BY
grouping_columns /*对结果分组*/
HAVING
condition /*分组后的行条件*/
ORDER BY
sorting_columns /*对结果排序*/
LIMIT
offset_start, row_count /*结果限定*/
_ :匹配单个任意字符
%:匹配多个任意字符
-- 建表
CREATE TABLE emp(
empno INT, -- 编号
ename VARCHAR(50), -- 姓名
job VARCHAR(50), -- 职位
mgr INT, -- 领导编号
hiredate DATE, -- 入职日期
sal DECIMAL(7,2), -- 薪水
comm decimal(7,2), -- 奖金
deptno INT -- 部门编号
) ;
插入数据:
INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
利用模糊查询来操作:
-- 比如我现在想匹配员工表中名字首个字母是S开头的
SELECT name FROM emp WHERE name LIKE 'S%';
-- 匹配名字第二个字母是a的
SELECT name FROM emp WHERE name LIKE '_a%';
返回顶部
-- 比如我现在想给empno这个列名其别名id
SELECT empno AS id FROM emp;
-- 给运算字段起别名
select empno,ename,(sal+comm) as 总收入 from emp;
-- 给表起别名
SELECT empno,ename FROM emp AS 员工表;
这里看不出起别名的用处,它更多的用在子查询(大量的代码嵌套)中,我们可以通过起别名来简化代码。
-- ifnull的作用演示
SELECT empno,ename,sal+IFNULL(comm,0) FROM emp;
返回顶部
SECECT sal FROM emp ORDER BY sal;
-- 比如我现在想查询工资的分布情况
sal
---------
800.00
950.00
1100.00
1250.00
1250.00
1300.00
1500.00
1600.00
2450.00
2850.00
2975.00
3000.00
3000.00
5000.00
-- 我们会得到重复的值,这显然是不合理的,需要去重
SELECT DISTINCT sal FROM emp ORDER BY sal;
sal
---------
800.00
950.00
1100.00
1250.00
1300.00
1500.00
1600.00
2450.00
2850.00
2975.00
3000.00
5000.00
-- 排序默认为ASC升序排列,你也可以降序排列DESC
SELECT DISTINCT sal FROM emp ORDER BY sal DESC;
-- 不去重的情况下,比如我们要按工资大小排序来查看所有人的信息
SELECT * FROM emp ORDER BY sal DESC; -- *表示所有列
empno ename job mgr hiredate sal comm deptno
------ ------ --------- ------ ---------- ------- ------- --------
7839 KING PRESIDENT (NULL) 1981-11-17 5000.00 (NULL) 10
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 (NULL) 20
7902 FORD ANALYST 7566 1981-12-03 3000.00 (NULL) 20
7566 JONES MANAGER 7839 1981-04-02 2975.00 (NULL) 20
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 (NULL) 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 (NULL) 10
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
7934 MILLER CLERK 7782 1982-01-23 1300.00 (NULL) 10
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7876 ADAMS CLERK 7788 1987-05-23 1100.00 (NULL) 20
7900 JAMES CLERK 7698 1981-12-03 950.00 (NULL) 30
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
-- 我们发现工资会有重复的情况,那么可以指定第二排序条件
SELECT * FROM emp ORDER BY sal DESC, ename ASC;
empno ename job mgr hiredate sal comm deptno
------ ------ --------- ------ ---------- ------- ------- --------
7839 KING PRESIDENT (NULL) 1981-11-17 5000.00 (NULL) 10
7902 FORD ANALYST 7566 1981-12-03 3000.00 (NULL) 20
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 (NULL) 20
7566 JONES MANAGER 7839 1981-04-02 2975.00 (NULL) 20
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 (NULL) 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 (NULL) 10
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
7934 MILLER CLERK 7782 1982-01-23 1300.00 (NULL) 10
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7876 ADAMS CLERK 7788 1987-05-23 1100.00 (NULL) 20
7900 JAMES CLERK 7698 1981-12-03 950.00 (NULL) 30
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
返回顶部
聚合函数就是用来做纵向运算的函数,常见的有以下几种:
聚合函数 | 解释 |
---|---|
COUNT() | 统计指定列不为NULL的记录行数 |
MAX() | 计算指定列的最大值,如果指定列是字符串类型那么使用字符串排序运算 |
MIN() | 计算指定列的最小值,如果指定列是字符串类型那么使用字符串排序运算 |
SUM() | 计算指定列的数值和,如果指定列的类型不是数值类型,那么计算结果为0 |
AVG() | 计算指定列的平均值,如果指定列的类型不是数值类型,那么计算结果为0 |
顺便介绍分组查询:GROUP BY()
GROUP BY()和聚合函数相互结合,可以查出很有意义的数据:
-- 查询各部门的平均工资
SELECT deptno,AVG(sal)FROM emp GROUP BY deptno;
deptno AVG(sal)
------ -------------
10 2916.666667
20 2175.000000
30 1566.666667
-- 查询每个部门工资大于1500的人数
SELECT deptno,COUNT(sal) FROM emp WHERE sal>1500 GROUP BY deptno;
-- where 是对分组前的条件限定 也就是说不满足条件的 不参与分组
deptno count(sal)
------ ------------
10 2
20 3
30 2
返回顶部
-- 查询平均工资大于2000的部门
SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno HAVING avgsal>2000;
deptno avgsal
------ -------------
10 2916.666667
20 2175.000000
-- 查询各个部门员工工资大于1500的平均工资,并且平均工资大于2000的部门
-- 思路:首先查询各个部门,那肯定要按部门编号分组,分组的条件限定是 员工工资大于1500的材参与分组 计算出平均工资 然后再对结果进行筛选 筛选出平均工资大于2000的部门
SELECT deptno,AVG(sal) FROM emp WHERE sal>1500 GROUP BY deptno HAVING AVG(sal)>2000;
deptno avg(sal)
------ -------------
10 3725.000000
20 2991.666667
30 2225.000000
返回顶部
-- 语法:
LIMIT 开始的记录索引,每一页显示的条数
-- 索引从0开始,开始的记录索引 = (页码-1) * 每一页显示的条数。
SELECT * FROM emp LIMIT 0,5;
empno ename job mgr hiredate sal comm deptno
------ ------ -------- ------ ---------- ------- ------- --------
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-04-02 2975.00 (NULL) 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
SELECT * FROM emp LIMIT 5,5;
empno ename job mgr hiredate sal comm deptno
------ ------ --------- ------ ---------- ------- ------ --------
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 (NULL) 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 (NULL) 10
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 (NULL) 20
7839 KING PRESIDENT (NULL) 1981-11-17 5000.00 (NULL) 10
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
SELECT * FROM emp LIMIT 10,5;
empno ename job mgr hiredate sal comm deptno
------ ------ ------- ------ ---------- ------- ------ --------
7876 ADAMS CLERK 7788 1987-05-23 1100.00 (NULL) 20
7900 JAMES CLERK 7698 1981-12-03 950.00 (NULL) 30
7902 FORD ANALYST 7566 1981-12-03 3000.00 (NULL) 20
7934 MILLER CLERK 7782 1982-01-23 1300.00 (NULL) 10
返回顶部
约束是对插入数据的一种限制,保证数据的有效性和完整性。
主要分为以下几种:
特点:非空且唯一,而且一张表中只能有一个主键
来看看主键的添加语法:
CREATE TABLE test(
userid INT,
username VARCHAR(32) PRIMARY KEY,
age INT
);
CREATE TABLE test_1(
userid INT,
username VARCHAR(32),
age INT,
PRIMARY KEY(username)
);
CREATE TABLE test_2(
userid INT,
username VARCHAR(32),
age INT
);
ALTER TABLE test_2 add PRIMARY KEY(username);
加上了主键约束的字段在插入数据时就不能写null,而且不能有重复值:
INSERT INTO test1 VALUES(01,'张三',19); -- 插入成功
INSERT INTO test1 VALUES(02,'张三',20); -- 插入失败
-- 提示Duplicate entry '张三' for key 'PRIMARY'
INSERT INTO test1 VALUES(02,null,20);
-- 提示Column 'username' cannot be null
下面学习如何删除主键约束,分两种情况:
CREATE TABLE test(
userid INT ,
username VARCHAR(32) PRIMARY KEY,
age INT
);
ALTER TABLE test DROP PRIMARY KEY;
-- 这么做只删除了唯一约束,但是没有删除非空约束
-- 删除非空约束可以通过修改字段来实现,在原来的字段声明后加上NULL即可
ALTER TABLE test MODIFY username VARCHAR(32) NULL;
-- 这样就解除了主键约束
CREATE TABLE test2(
userid INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(32) ,
age INT
);
-- 有自增长约束的字段一定是INT型,我们第一步先删除自增长约束
ALTER TABLE test2 CHANGE userid userid INT;
-- 然后再删除主键约束
ALTER TABLE test2 DROP PRIMARY KEY;
ALTER TABLE test2 MODIFY userid INT NULL;
返回顶部
被修饰的字段在插入数据时要求唯一(不限制null):
语法与上面的类似:
CREATE TABLE test(
userid INT UNIQUE,
username VARCHAR(32) UNIQUE,
age INT
);
CREATE TABLE test(
userid INT,
username VARCHAR(32),
age INT,
UNIQUE(userid),
UNIQUE(username)
);
CREATE TABLE test(
userid INT,
username VARCHAR(32),
age INT,
);
ALTER TABLE test ADD UNIQUE(userid);
ALTER TABLE test ADD UNIQUE(username);
返回顶部
值得注意的是:
ALTER TABLE test ADD UNIQUE(userid);
ALTER TABLE test ADD UNIQUE(username);
这种添加方式是给每个字段单独添加唯一约束,此时:
INSERT INTO test values(01,'james',36); -- 插入数据成功
INSERT INTO test values(02,'james',25); -- 插入数据失败
INSERT INTO test values(01,'curry',30); -- 插入数据失败
-- userid和username都单独设置了唯一约束,插入数据时,任意一个重复就会报错
这显然不是我们想要的结果,我们的重复数据应该是全部一样才报错,此时就要使用到联合约束。
ALTER TABLE test ADD UNIQUE(userid,username);
现在就可以插入部分重复的数据了:
INSERT INTO test values(01,'james',36); -- 插入数据成功
INSERT INTO test values(02,'james',25); -- 插入数据成功
INSERT INTO test values(01,'curry',30); -- 插入数据成功
INSERT INTO test values(01,'james',36); -- 插入数据失败
如果使用主键约束两个字段那就是加粗样式联合主键,这个主键的唯一性并不冲突。
返回顶部
特点:被修饰的字段不能为null
CREATE TABLE test(
userid INT NOT NULL,
username VARCHAR(32) NOT NULL,
age INT NOT NULL,
);
这里非空约束见名知意,不再赘述。
返回顶部
特点:
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
age INT,
username VARCHAR(32)
);
这样的话我们在插入数据时就可以直接给userid赋NULL值,数据库会自动帮助我们设置增长的数字来赋给userid:
INSERT INTO test VALUES(NULL,20,"张三");
INSERT INTO test VALUES(NULL,26,"李四");
INSERT INTO test VALUES(NULL,22,"王五");
id age username
------ ------ ----------
1 20 张三
2 26 李四
3 22 王五
当然你也可以指定id的值,那么后面插入的数据的id值就会从你指定的这个数开始增长:
INSERT INTO test VALUES(10,23,"赵六");
INSERT INTO test VALUES(NULL,56,"鬼脚七");
id age username
------ ------ -----------
1 20 张三
2 21 李四
3 26 王五
10 23 赵六
11 56 鬼脚七
注意:你可以把这个自增长约束理解为只能前进不能后退的指针,当你把这张表中以有的数据删除之后,指针并没有后退,下次插入数据时,会从删除前的数字开始增长:
DELETE FROM test ;
INSERT INTO test VALUES(NULL,20,"张三");
id age username
------ ------ ----------
12 20 张三
如果想要更换增长的数字,就摧毁这张表,重新建立:
TRUNCATE test;
-- 摧毁这张表,重新建立一张新表
有了自增长约束,每一行数据都有一个独有的值,那么我们的增删改查工作就可以以id为条件来限制数据,非常方便,自增长约束通常和主键约束配合使用。
返回顶部
我们已经知道了主键具有约束数据非空且唯一的作用,但是主键只能设置一个,那么如果其他列也想要这种效果该怎么办呢?我们可以把非空约束和唯一约束来配合使用:
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
username varchar(20) UNIQUE NOT NULL,
age INT UNIQUE NOT NULL
);
这样就给所有字段设置了非空且唯一的约束,任何字段的重复都是不允许的。
返回顶部
这里简单介绍一下枚举限制数据:
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
username varchar(20) ,
age INT ,
sex ENUM('男','女')
);
sex列就被限制只能是 男 或者 女 中的一个。
返回顶部
ER图就是实体联系图。
ER图的实体(entity)即数据模型中的数据对象,用长方体来表示,每个实体都有自己的实体成员(entity member)或者说实体对象(entity instance),实体成员(entity member)/实体实例(entity instance) 不需要出现在ER图中。
ER图的属性(attribute)即数据对象所具有的属性,用椭圆形表示,属性分为唯一属性( unique attribute)和非唯一属性,唯一属性指的是唯一可用来标识该实体实例或者成员的属性,用下划线表示,一般来讲实体都至少有一个唯一属性。
ER图的关系(relationship)用来表现数据对象与数据对象之间的联系,关系用菱形来表示。
ER图中关联关系有三种:
1对1(1:1) :1对1关系是指对于实体集A与实体集B,A中的每一个实体至多与B中一个实体有关系;反之,在实体集B中的每个实体至多与实体集A中一个实体有关系。
1对多(1:N) :1对多关系是指实体集A与实体集B中至少有N(N>0)个实体有关系;并且实体集B中每一个实体至多与实体集A中一个实体有关系。
多对多(M:N) :多对多关系是指实体集A中的每一个实体与实体集B中至少有M(M>0)个实体有关系,并且实体集B中的每一个实体与实体集A中的至少N(N>0)个实体有关系。
我们可以使用ER图来设计表,比如说我们现在要设计一个网络商城,那么必有的表就有:商品表,用户表,订单表。
这三张表之间是有一定联系的,比如一个用户可以有很多个订单,每个订单会有很多商品。
商品和订单之间就是多对多的关系,为了处理多对多的关系,我们一般会引入一张中间表,存放这两张表的主键,这样就可以将多对多的关系拆分为两个一对多的关系,为了保证数据的有效性和完整性,需要在中间表上添加两个外键约束即可。用户和订单是一对多的关系,订单和商品又是一对多的关系,在这里,订单表就是所谓的中间表。
开发中处理一对多的关系,我们会在多表中添加一个外键,名称一般为主表的名称_id,字段类型一般和主表的主键的类型保持一致。
比如在这里,我们往订单表orders里面添加外键user_id。
外键约束就是用来保证数据的有效性和完整性,多表一方叫从表,一表一方叫主表,我们通常还会在从表添加外键约束中去管理主表的主键。
alter table 多表名称 add foreign key(外键名称) references 一表名称(主键);
alter table orders add foreign key(user_id) references user(id);
添加了外键约束之后 两张表之间就有了联系,有如下特点:
那么如果我们想要删除主表中的数据怎么办呢?
ALTER TABLE orders ADD FOREIGN KET(user_id) REFERENCE user(id) ON DELETE CASCADE;
ALTER TABLE orders ADD FOREIGN KET(user_id) REFERENCE user(id) ON DELETE CASCADE ON UPDATE CASCADE;
在开发过程中,我们并不推荐使用外键约束,因为在后期测试工作量会很大。
我们现在来新建用户表和订单表来说明问题:
-- 主表
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT, -- 主表主键
username VARCHAR(20)
);
-- 从表
CREATE TABLE orders(
id INT PRIMARY KEY AUTO_INCREMENT, -- 从表主键
totalprice DOUBLE,
user_id INT
);
-- 给从表添加外键约束
ALTER TABLE orders ADD FOREIGN KEY(user_id) REFERENCES users(id);
-- 插入数据
INSERT INTO users VALUES (3,"张三");
INSERT INTO users VALUES (NULL,"李四");
INSERT INTO users VALUES (NULL,"王五");
INSERT INTO orders VALUES (NULL,1000,3);
INSERT INTO orders VALUES (NULL,1200,4);
INSERT INTO orders VALUES (NULL,3000,5);
INSERT INTO orders VALUES (NULL,5000,3);
INSERT INTO orders VALUES (NULL,1600,4);
-- 表结构
id username
------ ----------
3 张三
4 李四
5 王五
6 赵六
-- 表结构
id price user_id
------ ------ ---------
1 1314 3
2 1314 3
3 15 4
4 315 5
5 1014 (NULL)
返回顶部
在数学中,两个集合X和Y的笛卡儿积(Cartesian product),又称直积,表示为X × Y,是其第一个对象是X的成员而第二个对象是Y的一个成员的所有可能的有序对。
假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。
在数据库中,无条件的联合查询是没有实际意义的,它会返回这两张表的笛卡尔积,我们用上面的用户表和订单表来演示一下:
-- 拼接两个表
SELECT * FROM USER,orders;
-- 用户表
id username
------ ----------
3 张三
4 李四
5 王五
6 赵六
-- 订单表表
id price user_id
------ ------ ---------
1 1314 3
2 1314 3
3 15 4
4 315 5
5 1014 (NULL)
-- 笛卡尔积
id username id price user_id
------ -------- ------ ------ ---------
3 张三 1 1314 3
4 李四 1 1314 3
5 王五 1 1314 3
6 赵六 1 1314 3
3 张三 2 1314 3
4 李四 2 1314 3
5 王五 2 1314 3
6 赵六 2 1314 3
3 张三 3 15 4
4 李四 3 15 4
5 王五 3 15 4
6 赵六 3 15 4
3 张三 4 315 5
4 李四 4 315 5
5 王五 4 315 5
6 赵六 4 315 5
3 张三 5 1014 (NULL)
4 李四 5 1014 (NULL)
5 王五 5 1014 (NULL)
6 赵六 5 1014 (NULL)
简单来讲笛卡尔积就是把两张表的列相加,行相乘,即A表中的每一行都会和B表中的每一行数据拼接,那么自然地,B表中的每一行数据就会和A表中的每一行数据拼接。
这样就完成了没有条件的多表联合查询,我们给它加上条件,就会得到具有实际意义的数据。
返回顶部
select a.*,b.* from a,b inner join b on ab的连接条件
inner join on 不符合条件的数据不展示,形成的中间表为两个表经过ON条件过滤后的笛卡尔积
select a.*,b.* from a,b where 连接条件
从左表中取出每一条记录,去右表中与所有的记录进行匹配;匹配必须是某个条件是左表中与右表中相同,才会保留结果,否则不保留;
-- 查询所有用户的订单详情,没有订单显示null
-- 左连接
SELECT user.*,orders.* FROM USER LEFT OUTER JOIN orders ON user.`id`=orders.`user_id`;
-- 右连接
SELECT user.*,orders.* FROM orders RIGHT OUTER JOIN USER ON user.`id`=orders.`user_id`;
id username id price user_id
------ -------- ------ ------ ---------
3 张三 1 1314 3
3 张三 2 1314 3
4 李四 3 15 4
5 王五 4 315 5
6 赵六 (NULL) (NULL) (NULL)
返回顶部
SELECT a.*,b.* FROM a left outer join b on 连接条件;
SELECT a.*,b.* FROM a right outer join b on 连接条件;
-- 查询所有用户的订单详情,没有订单显示null
-- 左外连接
SELECT user.*,orders.* FROM USER LEFT OUTER JOIN orders ON user.`id`=orders.`user_id`;
-- 右外连接
SELECT user.*,orders.* FROM orders RIGHT OUTER JOIN USER ON user.`id`=orders.`user_id`;
id username id price user_id
------ -------- ------ ------ ---------
3 张三 1 1314 3
3 张三 2 1314 3
4 李四 3 15 4
5 王五 4 315 5
6 赵六 (NULL) (NULL) (NULL)
-- 查询所有订单的用户详情
-- 右连接
SELECT orders.*,user.* FROM USER RIGHT OUTER JOIN orders ON user.`id`=orders.`user_id`;
-- 左连接
SELECT orders.*,user.* FROM orders LEFT OUTER JOIN USER ON user.`id`=orders.`user_id`;
id price user_id id username
------ ------ ------- ------ ----------
1 1314 3 3 张三
2 1314 3 3 张三
3 15 4 4 李四
4 315 5 5 王五
5 1014 (NULL) (NULL) (NULL)
返回顶部
有两种基本类型的的连接,inner和outer连接。两种类型的主要区别在于,即使是在连接条件不满足的情况下,外部连接也会在结果集内返回行,而内部连接不会在结果集类返回行 。
当外部连接不满足连接条件时,通常返回一个表中的列,但是第二个表中没有返回值就返回null。
返回顶部
一个主查询的条件要依赖于另外一个子查询的结果。
-- 一. 查询出订单的价格大于300的所有用户信息。
-- 分步查询
-- 先找出价格大于300的订单的用户ID 3 5
SELECT orders.`user_id` FROM orders WHERE orders.`price`>300;
-- 再通过id找出用户信息
SELECT user.* FROM USER WHERE user.id IN (3,5,NULL);
-- 合并-子查询
SELECT user.* FROM USER WHERE user.id IN (SELECT orders.`user_id` FROM orders WHERE orders.`price`>300);
id username
------ ----------
3 张三
5 王五
-- 二.查询订单价格大于300的订单信息及相关用户的信息。
-- 内连接
SELECT user.*,orders.* FROM USER,orders WHERE user.id=orders.`user_id` AND orders.`price`>300;
-- 子查询
-- 找出所有订单价格大于三百的订单信息作为临时表
SELECT user.*,tmp.* FROM USER,(SELECT * FROM orders WHERE price>300) AS tmp WHERE user.`id`=tmp.user_id;
id username id price user_id
------ -------- ------ ------ ---------
3 张三 1 1314 3
3 张三 2 1314 3
5 王五 4 315 5
返回顶部
有时候我们需要在一张表中查询出有实际意义的数据,那就需要把它适时地看作两张表:
我们先来新建一张员工表:
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno INT
) ;
-- 插入数据
INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
-- 员工表
empno ename job mgr hiredate sal comm deptno
------ ------ --------- ------ ---------- ------- ------- --------
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-04-02 2975.00 (NULL) 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 (NULL) 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 (NULL) 10
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 (NULL) 20
7839 KING PRESIDENT (NULL) 1981-11-17 5000.00 (NULL) 10
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-05-23 1100.00 (NULL) 20
7900 JAMES CLERK 7698 1981-12-03 950.00 (NULL) 30
7902 FORD ANALYST 7566 1981-12-03 3000.00 (NULL) 20
7934 MILLER CLERK 7782 1982-01-23 1300.00 (NULL) 10
查询emp表中所有员工的上司的姓名:
我们假设有两张表,一张员工表,一张上司表,如果员工表的mgr=上司表中的empno,就说明这个empno对应的人名就是他的上司。
-- 查询
SELECT a.empno AS 员工编号,a.ename AS 员工,b.empno AS 上司编号,b.ename AS 上司
FROM emp AS a,emp AS b WHERE a.mgr = b.empno ORDER BY a.`empno`;
-- 返回
员工编号 员工 上司编号 上司
------------ ------ ------------ --------
7369 SMITH 7902 FORD
7499 ALLEN 7698 BLAKE
7521 WARD 7698 BLAKE
7566 JONES 7839 KING
7654 MARTIN 7698 BLAKE
7698 BLAKE 7839 KING
7782 CLARK 7839 KING
7788 SCOTT 7566 JONES
7844 TURNER 7698 BLAKE
7876 ADAMS 7788 SCOTT
7900 JAMES 7698 BLAKE
7902 FORD 7566 JONES
7934 MILLER 7782 CLARK
返回顶部
开发中我们会经常用到旧表中的结构或者数据,学会怎样复制表会很方便:
-- 举例来说比如我们要复制上面的那张员工表
CREATE TABLE myEmp AS SELECT * FROM emp;
-- 或者
CREATE TABLE myEmp AS SELECT * FROM emp WHERE TRUE;
-- 或者
CREATE TABLE myEmp AS SELECT * FROM emp WHERE 1=1;
-- 结论:只要在WHERE后面跟上TRUE或者结果为TRUE的判断式
-- 当然,WHERE也可以省略,默认复制列名和数据
CREATE TABLE myEmp2 AS SELECT * FROM emp WHERE FALSE;
-- 或者
CREATE TABLE myEmp2 AS SELECT * FROM emp WHERE 1=2;
-- 结论:只要在WHERE后面跟上TRUE或者结果为FALSE的判断式
CREATE TABLE myEmp3 AS SELECT emp.id,emp.name FROM emp WHERE FALSE;
CREATE TABLE myEmp4 AS (语句);
返回顶部
-- 查询10号和20号部门的员工信息
-- 方法一:
SELECT * FROM emp WHERE deptno = 10 OR deptno = 20;
-- 方法二:
SELECT * FROM emp WHERE deptno = 10
UNION
SELECT * FROM emp WHERE deptno = 20;
empno ename job mgr hiredate sal comm deptno
------ ------ --------- ------ ---------- ------- ------ --------
7782 CLARK MANAGER 7839 1981-06-09 2450.00 (NULL) 10
7839 KING PRESIDENT (NULL) 1981-11-17 5000.00 (NULL) 10
7934 MILLER CLERK 7782 1982-01-23 1300.00 (NULL) 10
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
7566 JONES MANAGER 7839 1981-04-02 2975.00 (NULL) 20
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 (NULL) 20
7876 ADAMS CLERK 7788 1987-05-23 1100.00 (NULL) 20
7902 FORD ANALYST 7566 1981-12-03 3000.00 (NULL) 20
返回顶部
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
返回顶部
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
PROCEDURE `库名`.`存储过程名`()
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN
方法体
END$$
DELIMITER ;
CALL 存储过程名();
DROP PROCEDURE 存储过程名();
show procedure status\G; -- 查看所有的存储过程状态
show create procedure 存储过程名\G; -- 查看创建存储过程的语句
返回顶部
delimiter是mysql中用来定义结束标记的,mysql客户端中结束标记默认是分号’;’。如果一次输入的语句较多,并且语句中间有分号,这时需要新指定一个特殊的结束符。delimiter $ 表示mysql用$表示mysql语句结束,过程结束后肯定会有一句delimiter ;恢复成默认的。
返回顶部
https://blog.csdn.net/jq_ak47/article/details/52087484
- 全局变量:MYSQL内置变量,存在任何一个会话当中,会话是你跟数据库建立的一次连接,全局变量影响服务器整体操作。当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。要想更改全局变量,必须具有SUPER权限。全局变量作用于server的整个生命周期,但是不能跨重启。即重启后所有设置的全局变量均失效。要想让全局变量重启后继续生效,需要更改相应的配置文件。
- 用户变量:在客户端链接到数据库实例整个过程中用户变量都是有效的。mysql中用户变量不用事前申明,在用的时候直接用“@变量名”使用就可以了,select语句一般用来输出用户变量,比如select
@变量名,用于输出数据源不是表格的数据。- 会话变量:服务器为每个连接的客户端维护一系列会话变量。在客户端连接数据库实例时,使用相应全局变量的当前值对客户端的会话变量进行初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。会话变量的作用域与用户变量一样,仅限于当前连接。当当前连接断开后,其设置的所有会话变量均失效。
- 局部变量:定义在存储过程中或者函数中的变量,局部变量只在当前begin/end代码块中有效
返回顶部
来看几个实例:
-- 存储过程中可以存放一些简单的逻辑
-- 这个存储过程用来根据传进来的员工编号返回员工的所有信息
DELIMITER $$
CREATE
PROCEDURE `mydemo`.`mypro1`(IN num INT) -- 输入参数的定义
BEGIN
SELECT * FROM emp WHERE empno=num;
END$$
DELIMITER;
-- 查询编号为7369的员工信息
CALL mypro1(7369);
-- 返回
empno ename job mgr hiredate sal comm deptno
------ ------ ------ ------ ---------- ------ ------ --------
7369 SMITH CLERK 7902 1980-12-17 800.00 (NULL) 20
DELIMITER $$
CREATE
PROCEDURE `mydemo`.`mypro2`(OUT mytext VARCHAR(20)) -- 输出参数的定义
BEGIN
SET mytext = 'helloworld';
END$$
DELIMITER;
-- 我们需要定义一个用户变量去接收程序返回的值
SET @s; --定义
CALL mypro2(@s); -- 调用程序
SELECT @s; -- 查询
-- 返回
@s
------------
helloworld
DELIMITER $$
CREATE
PROCEDURE mypro3(INOUT num INT) -- 形参的定义
BEGIN
DELETE FROM emp WHERE empno = num;
SELECT COUNT(*) FORM emp INTO num;
END$$
DELIMITER;
SET @num=7369;
CALL mypro3(@num);
SELECT @num;
返回顶部
案例:输入数字返回星期
DELIMITER $$
CREATE
PROCEDURE proIf(IN num INT,OUT result VARCHAR(10)) -- 形参的定义
BEGIN
IF num=1 THEN
SET result = '星期1';
ELSEIF num=2 THEN
SET result = '星期2';
ELSEIF num=3 THEN
SET result = '星期3';
ELSEIF num=4 THEN
SET result = '星期4';
ELSEIF num=5 THEN
SET result = '星期5';
ELSEIF num=6 THEN
SET result = '星期6';
ELSEIF num=7 THEN
SET result = '星期7';
ELSE
SET result = 'undefined'
END IF;-- 结束条件语句
END$$
DELIMITER;
返回顶部
案例:求1~100的和
DELIMITER $$
CREATE
PROCEDURE sum1(IN num INT,OUT result INT) -- 形参的定义
BEGIN
DECLARE i INT DEFAULT 1; -- 定义一个局部变量默认值为1
DECLARE sum INT DEFAULT 0; -- 定义一个局部变量默认值为0
WHILE(i<=num) DO
SET sum = sum + i;
SET i = i+1;
END WHILE; -- 记得结束循环
SET result = num;
END$$
DELIMITER;
CALL myproWhile(100,@r);
SELECT @r;
返回顶部
-- 第二种 loop 循环
/*loop 循环语法:
loop_name:loop
if 条件 THEN -- 满足条件时离开循环
leave loop_name; -- 和 break 差不多都是结束训话
end if;
end loop;
*/
-- 实例:
DELIMITER $$
CREATE PROCEDURE sum2(a INT)
BEGIN
DECLARE SUM INT DEFAULT 0;
DECLARE i INT DEFAULT 1;
loop_name:LOOP -- 循环开始
IF i>a THEN
LEAVE loop_name; -- 判断条件成立则结束循环 好比java中的 boeak
END IF;
SET SUM=SUM+i;
SET i=i+1;
END LOOP; -- 循环结束
SELECT SUM; -- 输出结果
END $$
DELIMITER;
-- 执行存储过程
CALL sum2(100);
-- 删除存储过程
DROP PROCEDURE IF EXISTS sum2;
-- 第三种 repeat 循环
/*repeat 循环语法
repeat
循环体
until 条件 end repeat;
*/
-- 实例;
DELIMITER $$
CREATE PROCEDURE sum3(a INT)
BEGIN
DECLARE SUM INT DEFAULT 0;
DECLARE i INT DEFAULT 1;
REPEAT -- 循环开始
SET SUM=SUM+i;
SET i=i+1;
UNTIL i>a END REPEAT; -- 循环结束
SELECT SUM; -- 输出结果
END$$
DELIMITER;
-- 执行存储过程
CALL sum3(100);
返回顶部
leave 相当于 break
iterate相当于continue
返回顶部
触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。
触发器尽量少的使用,因为不管如何,它还是很消耗资源,如果使用的话要谨慎的使用,确定它是非常高效的:触发器是针对每一行的;对增删改非常频繁的表上切记不要使用触发器,因为它会非常消耗资源。
触发器是数据库中的一个对象,相当于JS中的监听器,触发器可以监听增删改 三个动作比如说我想监听一张表,只要我增删改了这张表中的数据,我就可以触发这个触发器,去往另外一张表中记录一下日志。
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
TRIGGER `库名`.`触发器名` BEFORE/AFTER INSERT/UPDATE/DELETE --可选择的事件名
ON `目标表`.`<Table Name>`
FOR EACH ROW BEGIN -- 针对每一行
-- 具体实现
END$$
DELIMITER ;
-- BEFORE 行为发生之前就触发
-- AFTER 行为发生之后触发
比如少我们现在有一张学生表student,和一张日志表logger:
-- 新建学生表
CREATE TABLE student(sname VARCHAR(10),sage INT);
-- 插入数据
INSERT INTO student VALUES("张三",20);
INSERT INTO student VALUES("李四",30);
INSERT INTO student VALUES("王五",40);
-- 表
sname sage
------ --------
张三 20
李四 30
王五 40
-- 新建logger表来写日志
CREATE TABLE logger(sname VARCHAR(10),sage INT,text varchar(100),time timestamp);
返回顶部
现在要求当我学生表中新插入数据时,就往日志表中写一条记录:
-- 新建触发器
DELIMITER$$
CREATE
TRIGGER tri AFTER INSERT
ON student
FOR EACH ROW
BEGIN
INSERT INTO logger VALUES(new.sname,new.sage,"插入了一行数据",NULL);
END$$
DELIMITER;
-- 现在往学生表中插入一条数据
INSERT INTO student VALUES("赵六",24);
-- 学生表
sname sage
------ --------
张三 20
李四 30
王五 40
赵六 24
-- 日志
sname sage text time
------ ------ --------------------- ---------------------
赵六 24 插入了一行数据 2019-03-14 19:09:36
返回顶部
当学生表中数据发生改变,往日志表中写一条记录:
DELIMITER$$
CREATE
TRIGGER tri2 AFTER UPDATE
ON student
FOR EACH ROW
BEGIN
INSERT INTO logger VALUES(old.sname,old.sage,"此行数据更新",NULL);
INSERT INTO logger VALUES(new.sname,new.sage,"更新后的数据",NULL);
END$$
DELIMITER;
-- 更新数据
UPDATE student SET sname="张三三",sage=19 WHERE sname = "张三";
-- 学生表
sname sage
------ --------
张三三 19
李四 30
王五 40
赵六 24
-- 日志
sname sage text time
--------- ------ --------------------- ---------------------
赵六 24 插入了一行数据 2019-03-14 19:09:36
张三 20 此行数据更新 2019-03-14 19:26:48
张三三 19 更新后的数据 2019-03-14 19:26:48
返回顶部
当学生表中的数据被删除,往日志表中写一条记录:
DELIMITER$$
CREATE
TRIGGER tri3 AFTER DELETE
ON student
FOR EACH ROW
BEGIN
INSERT INTO logger VALUES(old.sname,old.sage,"此行数据删除",NULL);
END$$
DELIMITER;
-- 删除
DELETE FROM student WHERE sname='张三三';
-- 学生表
sname sage
--------- --------
李四 30
王五 40
赵六 24
-- 日志
sname sage text time
--------- ------ --------------------- ---------------------
赵六 24 插入了一行数据 2019-03-14 19:09:36
张三 20 此行数据更新 2019-03-14 19:26:48
张三三 19 更新后的数据 2019-03-14 19:26:48
张三三 19 此行数据删除 2019-03-14 19:44:45
返回顶部
DROP TRIGGER tri;
DROP TRIGGER tri2;
DROP TRIGGER tri3;
这两种都是mysql的数据库的存储引擎的类型,一个支持事物等数据库的高级功能,一个不支持。两个各有用处,各有优劣。
另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。简而言之:
MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。 MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持,外键等高级数据库功能。
任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势.
下面来看一些常见的关于引擎的操作:
查看表信息,里面包括使用的引擎类型,字符编码,表结构等mysql> show create table 表名;
可以执行以下命令来切换非事务表到事务(数据不会丢失),innodb表比myisam表更安全:
alter table 表名 type=innodb;
innodb表不能用repair table
命令和myisamchk -r table_name
但可以用check table 表名
,以及mysqlcheck [OPTIONS] database [tables]
启动mysql数据库的命令行中添加了以下参数可以使新发布的mysql数据表都默认为使用事务(
只影响到create语句。)
default-table-type=InnoDB
临时改变默认表类型可以用:
set table_type=InnoDB;
返回顶部
索引在MySQL中也叫做“键”,即’key’,是存储引擎用于快速查找记录的一种数据结构。当表中的数据越来越多时,索引对于性能的影响愈发重要。索引优化是对查询性能优化最有效的手段,它能够轻易将查询性能提高好几个数量级。通俗来讲,它就相当于新华字典的音序表,能够帮助你快速的找到你想要的数据。
返回顶部
语法:
create table 表名(
字段名 数据类型 [约束],
字段名2 数据类型2 [约束],
[unique|fulltext|spatial] index|key
[索引名](字段名[(长度)] [ASC|DESC]) -- 注意中括号里面的是可选项
);
CREATE TABLE t1(
sid INT,
sname VARCHAR(32),
INDEX(sname) -- 给name 字段建立普通索引 注意字段不要带引号
);
-- 查询建表语句
SHOW CREATE TABLE t1;
-- 返回
Table Create Table
------ --------------------------------------
t1 CREATE TABLE `t1` (
`sid` int(11) DEFAULT NULL,
`sname` varchar(32) DEFAULT NULL,
KEY `sname` (`sname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE t2(
tid INT,
tname VARCHAR(32),
UNIQUE INDEX(tname) -- 创建唯一索引,这列的值不能重复
);
CREATE TABLE t3(
tid INT,
tname VARCHAR(32),
tlog TEXT,
FULLTEXT INDEX myIndex (tlog) -- 这个myIndex是你起的索引名,一般省略不写
);
CREATE TABLE t4(
tid INT,
tname VARCHAR(32),
tlog VARCHAR(100),
INDEX my_Index (tname,tlog) -- 给 tname 和 tlog 两个列都建立索引
);
语法:
create [unique|fulltext|spatial] index 索引名 on 表名 (字段名[(长度)] [ASC|DESC]);
演示: student表已经存在,给里面的字段添加索引
-- 创建普通索引例子
CREATE INDEX myIndex ON student (sname);
-- 创建唯一索引例子
CREATE UNIQUE INDEX myIndex ON student (sname);
-- 创建全文索引例子
CREATE FULLTEXT INDEX myIndex ON t3 (tlog);
-- 创建多列索引例子
CREATE INDEX myIndex ON student (sname,slog);
语法:
alter table 表名 add [unique|fulltext|spatial] index 索引名 on 表名 (字段名[(长度)] [ASC|DESC]);
演示:
-- 创建普通索引的例子
ALTER TABLE student ADD INDEX MyIndex(sname);
-- 创建唯一索引的例子
ALTER TABLE student ADD UNIQUE INDEX MyIndex(sname);
-- 创建多列索引
ALTER TABLE student ADD INDEX MyIndex(sname,slog);
返回顶部
show create table 表名\G;
drop index 索引名 on 表名;
返回顶部
写一个存储过程往表中存20000条数据。
DELIMITER$$
CREATE
PROCEDURE myinsert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE (i<=20000) DO
INSERT INTO test VALUES(i,"这是个测试");
SET i = i+1;
END WHILE;
END$$
DELIMITER;
CALL myinsert();
-- 没添加索引查询
SELECT * FROM test WHERE id=20000;
-- 执行耗时 : 0.061 sec
-- 传送时间 : 0.003 sec
-- 总耗时 : 0.065 sec
EXPLAIN SELECT * FROM test WHERE id=20000;
id select_type TABLE TYPE possible_keys KEY key_len ref ROWS Extra
------ ----------- ------ ------ ------------- ------ ------- ------ ------ -------------
1 SIMPLE test ALL (NULL) (NULL) (NULL) (NULL) 20375 USING WHERE
-- 添加索引后查询
CREATE INDEX index1 ON test(id);
SELECT * FROM test WHERE id=20000;
-- 执行耗时 : 0.007 sec
-- 传送时间 : 0.015 sec
-- 总耗时 : 0.023 sec
EXPLAIN SELECT * FROM test WHERE id=20000;
id select_type TABLE TYPE possible_keys KEY key_len ref ROWS Extra
------ ----------- ------ ------ ------------- ------ ------- ------ ------ -------------
1 SIMPLE test ref index1 index1 5 const 1 USING WHERE
-- 可以看出,效率大大提升
返回顶部
视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义。 同真实的表一样,视图包含一系列带有名称的列和行数据。 但是,视图并不在数据库中以存储的数据值集形式存在。 行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
返回顶部
create view 视图名称 as 查询语句;
-- 比如创建单表视图
CREATE VIEW my_view1 AS SELECT * FROM emp;
-- 创建多表视图 注意不要查询两张表中的同名字段,不然报错
CREATE VIEW my_view2 AS SELECT a.字段名,b.字段名 FROM a,b WHERE a.id=b.id;
-- 注意mysql中视图不支持封装子查询查出的数据
注意mysql中视图不支持封装子查询查出的数据。、
视图一旦创建,系统会在视图对应的数据库文件夹下,创建一个对应的结构文件:frm文件
show tables;
desc my_view1;
show create view my_view1;
drop view my_view1;
alter view 视图名 as 新的select语句;
返回顶部
返回顶部
视图是可以进行数据操作的,但是有很多限制:
with check option
create view my_v1 as select * from student where age>30 with check option;
返回顶部