MySQL数据库SQL语句基本操作

一、用户管理:

创建用户:

create user '用户名'@'IP地址' identified by '密码';

删除用户:

drop user '用户名'@'IP地址';

修改用户:

rename user '用户名'@'IP地址'; to '新用户名'@'IP地址';

修改密码:

set password for '用户名'@'IP地址' = Password('新密码')

 

二、库相关操作

查看所有数据库: 

1 SHOW DATABASES;

创建数据库 :

CREATE DATABASE cnblog(数据库名称,下同) CHARSET=UTF8; 

删除数据库 :

DROP DATABASE cnblog;

切换数据库 :

USE cnblog;

查看当前数据库 :

SELECT DATABASE();

 

图例:

 

 

三、表相关操作

查看数据库中的所有表:SHOW TABLES;

创建表:

格式(中括号中可以不填):CREATE TABLE 表名(列名 数据类型 是否可以为空)[ ENGINE= INNODB DEFAULT CHARSET=UTF8 ]

1.数字
     int[unsigned]  可以保存2的32次方大小的数,若有正负号,表示正负2的31次方
    bigint可以表示很大的数
2.字符串
    char(10)定长 若数据没有10长度会用空格补缺
    varchar(10)变长  数据是多少就是多少
    两者都只能表示255字节长度的字符串,
3.时间
    一般用DATATIME 显示XXXX-MM-DD H-i-s
4.枚举
    enum 插入数据时只能从Enum选项中选取
 CREATE TABLE shirts (
                    name VARCHAR(40),
                    size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
                );
INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small')
    set    插入值只能是set选项中的组合
CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
5.文件
如果文件过长,或者是图片,存取的是文件的url位置
基本数据类型
            NOT NULL    -不能为空
            NULL           -可为空
是否可为空
    CREATE TABLE 表名(
         num INT NOT NULL DEFAULT 6,
        ) ;     
     # 插入的这个数默认为6
默认值
1. 自增列为主键的情况    
CREATE TABLE 表名(
           id  INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        )    
2. 自增列为索引
CREATE TABLE 表名(
           id  INT NOT NULL AUTO_INCREMENT,
           index(id)      
        )     
自增
1.主键可以为单个字段
CREATE TABLE 表名(
           id  INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        ) 

2.主键可以为组合
CREATE TABLE 表名(
           firstname  VARCHAR(20) NOT NULL,
           lastname  VARCHAR(20) NOT NULL,
           PRIMARY KEY (firstname,lastname)
        ) 
主键
creat table color(
                nid int not null primary key,
                name char(16) not null
            )

create table fruit(
                nid int not null primary key,
                smt char(32) null ,
                color_id int not null,
                constraint fk_cc foreign key (color_id) references color(nid)
            )
外键
SHOW CREATE TABLE 表名
查看建表语句
DESC 表名
查看建表字段

 

 

修改表:

添加列:ALTER TABLE 表名 ADD 列名 类型
删除列:ALTER TABLE 表名 DROP COLUMN 列名
修改列:ALTER TABLE 表名 MODIFY COLUMN 列名 类型;  -- 类型
修改外键:ALTER TABLE 从表 ADD CONSTRAINT 外键名称(形如:FK_从表_主表)FOREIGN KEY 从表(外键字段) REFERENCES 主表(主键字段);
删除外键:ALTER TABLE 表名 DROP FOREIGN KEY 外键名称

 

 INSERT INTO 表名(列名,列名) VALUES (值,值);
eg: INSERT INTO student(name,tel) VALUES(‘小明’,‘13111311313’);
DELETE FROM 表名 WHERE 条件;
eg:DELETE FROM STUDENT WHERE sid=‘1001’ AND class=‘二班’
UPDATE 表名 SET 列=值 WHERE 条件
eg:UPDATE student SET points = 80 WHERE class=‘三班’
SELECT * FROM 表名
eg:SELECT * FROM STUDENT WHERE id>1
      SELECT id,gender FROM student WHERE points>80
ALTER TABLE 表名 AUTO_INCREMENT=10
表示主键的值从10开始递增
修改主键的值

 添加一个条件语句(语法case when ...then.... else .... end)

select max(num),min(num) case when min(num)<60 then 不及格 else min(num) end from score

最低分低于60分的会显示不及格,如果高于60分会显示最低是多少。

按条件查询(关键词where):
SELECT * FROM students WHERE age>10;
SELECT * FROM students WHERE id in (1,3,5);
SELECT * FROM students WHERE id BETWEEN 5 AND 16;(这是个闭区间)
SELECT * FROM students WHERE age=30 AND firstname=‘张'
SELECT * FROM students WHERE id in (SELECT id FROM male_students)(先从第二张表取id,再用此id查第一张表数据)
通配符查询(关键词like):
SELECT * FROM students WHERE name  like '%平’;(查找名字以平结尾的)
SELECT * FROM students WHERE name  like '_平’;(查找名字以平结尾的,只能为两个字)
SELECT * FROM students WHERE name  like '%平%’;(查找名字中含有平的)
分页查找(关键字limit):
SELECT * FROM students limit 10;      取10条数据查看
SELECT * FROM students limit 20,10    从第20条开始向后取10条
SELECT * FROM students limit 5 offset 7     从第7条开始向后取5条
排序 (关键词 ORDER BY)
SELECT * FROM students ORDER BY id DESC;降序排列
SELECT * FROM students ORDER BY id ASC;升序排列
分组(关键字group by 和 having):
SELECT count(id) as mount, class_id FROM students GROUP BY cl
ass_id HAVING count(id) > 20;(注意:where语句不能接聚合函数的,如果要对分组后的结果进行二次筛选要用having)
连表操作(关键词LEFT JOIN ...ON):
SELECT student.name FROM student LEFT JOIN class ON student.cid = class.id 

多张表相连:
SELECT student.name,teacher.id FROM student 
LEFT JOIN class ON student.cid = class.id 
LEFT JOIN teacher on class.teacher = teacher.id

LEFT JOIN 与 RIGHT JOIN区别:会以LEFT或RIGHT关联的表作为主显示表,从表没有数据会显示NULL

INNER JOIN 则会隐藏NULL的字段

注意:多张表关联时要引用字段,字段所在的表必须是关联好的不能凭空引入一个字段

 

索引:帮助我们快速的找到数据

索引文件存储的某种格式:

1.hash, 单值取值快, 但取多项数据时速度较慢

2.btree,单值没有hash速度快,但单次取数据查询次数少,对于多项数据速度较快

常见索引:
普通索引:加速查找
唯一索引:加速查找 + 不能重复
主键索引:加速查找 + 不能为空 + 不能重复
联合索引:
        - 联合主键索引
        - 联合唯一索引
        - 联合普通索引

普通索引:

生成表时即创建普通索引
CREATE TABLE index_1(
    nid int not null auto_increment primary key,
    name char(32) not null,
    email char(32) not null,
    extra text,
    index ix_name(name)
)

SQL语句创建索引
CREATE INDEX 索引名 on 表名(字段)

删除索引
DROP 索引名 on 表名;

查看索引
show index from 表名;

索引的缺点:
1.需要保存额外的索引文件
2.更新修改新建速度慢
3.要命中索引
    - SELECT * FROM student WHERE name='一休', 命中
    - SELECT * FROM student WHERE name LIKE '一休', 未命中

唯一索引:
创建表生成唯一索引
CREATE TABLE index_2(
        nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    unique ix_name (name)  -- 将name字段设置为唯一索引
)


创建唯一索引
CREATE unique INDEX 索引名 on 表名(字段);

删除唯一索引
DROP unique INDEX 索引名 on 表名

主键索引
create table index_3(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    index ix_name (name)
)

OR

create table index_4(
    nid int not null auto_increment,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text,
    primary key(ni1),
    index ix_name (name)
)


创建主键
ALTER TABLE 表名 add PRIMARY KEY(列名)

删除主键
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;


联合索引:
创建联合索引

create table index_5(
    nid int not null auto_increment primary key,
    name varchar(32) not null,
    email varchar(64) not null,
    extra text
)
create index ix_name_email on in3(name,email);


删除联合索引
- drop unique index 索引名称 on 表名
常见索引
在索引文件中直接获得数据
SELECT name FROM tb WHERE name='zhang'
覆盖索引
把多个单列索引合并使用
SELECT * FROM tb WHERE name=‘xxx’ AND id=3
索引合并
在组合索引中,遵循最左前缀原则,比如索引为(name,class,tel)
查询条件为name时走索引,(name,class),(name,tel)都会走索引
但是如果是class或tel开头不走索引
1.like
select * from tb1 where name like '%cn';

2.使用函数
SELECT * FROM tb WHERE  reverse(name) = 'zhang'

3.or
SELECT * FROM tb WHERE nid=1 or email='nn@qq.com'
注意:当or条件未建立索引才会失效或者后面接and条件是索引,也会忽略or

4.类型不一致
SELECT * FROM tb WHERE sid='999';(int类型却用字符串查找)

5.!=
SELECT * FROM tb WHERE sid != 99;
注意:如果条件是主键依然走索引

6.>
SELECT * FROM tb WHERE sid>99;
注意:如果条件是主键或整数类型会走索引

7.order by
SELECT name FROM tb order by sid;
注意:如果sid是索引 name非索引 则不走索引
如果order by接主键依然走索引

8.最左前缀匹配
不能命中索引的几种情况
1.避免使用SELECT *
2.创建表时尽量用char代替varchar
3.建表时固定长度的字段往前排
4.索引散列(重复少)不适合建索引(性别)
5.尽量使用短索引(text字段类型格式:text18)以前18个字符建索引)
6.连表操作是条件类型需一直
索引应注意事项
作用:不执行sql语句,MySQL预估SQL语句执行时间
 id
        查询顺序标识
            如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
            |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
        特别的:如果使用union连接气值可能为null


    select_type
        查询类型
            SIMPLE          简单查询
            PRIMARY         最外层查询
            SUBQUERY        映射为子查询
            DERIVED         子查询
            UNION           联合
            UNION RESULT    使用联合的结果
            ...
    table
        正在访问的表名


    type
        查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
            ALL             全表扫描,对于数据表从头到尾找一遍
                            select * from tb1;
                            特别的:如果有limit限制,则找到之后就不在继续向下扫描
                                   select * from tb1 where email = 'seven@live.com'
                                   select * from tb1 where email = 'seven@live.com' limit 1;
                                   虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。

            INDEX           全索引扫描,对索引从头到尾找一遍
                            select nid from tb1;

            RANGE          对索引列进行范围查找
                            select *  from tb1 where name < 'alex';
                            PS:
                                between and
                                in
                                >   >=  <   <=  操作
                                注意:!=> 符号


            INDEX_MERGE     合并索引,使用多个单列索引搜索
                            select *  from tb1 where name = 'alex' or nid in (11,22,33);

            REF             根据索引查找一个或多个值
                            select *  from tb1 where name = 'seven';

            EQ_REF          连接时使用primary key 或 unique类型
                            select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;



            CONST           常量
                            表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
                            select nid from tb1 where nid = 2 ;

            SYSTEM          系统
                            表仅有一行(=系统表)。这是const联接类型的一个特例。
                            select * from (select nid from tb1 where nid = 1) as A;
    possible_keys
        可能使用的索引

    key
        真实使用的

    key_len
        MySQL中使用索引字节长度

    rows
        mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值

    extra
        该列包含MySQL解决查询的详细信息
        “Using index”
            此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
        “Using where”
            这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
        “Using temporary”
            这意味着mysql在对查询结果排序时会使用一个临时表。
        “Using filesort”
            这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
        “Range checked for each record(index map: N)”
            这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
执行计划
分页:
最常见的分页基于 SELECT * FROM text_tb limit 0,10
这样的分页当数据量很大时(例如千万级别的数据量),很耗费时间,解决方法有以下几点:
1. 只给浏览用户展示固定页数,比如200页,300页,减轻mysql检索压力
2. 用索引表(覆盖索引)
    SELECT * FROM text_tb WHERE id in(SELECT id FROM text_tb LIMIT 1000000,10)
3.记录当前页最小id(比如150000)和最大id(150010)
    下一页: SELECT * FROM text_tb WHERE id > max_id LIMIT 10;
    上一页:SELECT * FROM text_tb WHERE id < min_id ORDER BY id DESC LIMIT 10;
4.给URL上的页数信息加密,无法直接访问到较大页数

注意:
1.id 不一定是连续的,所以不能用id bewteen xx and xx 来进行检索
2.中间页数的思路,根据前页的id 计算要跳到的页数的id,取到为止,倒序排列,并取头10个作为limit
select * from userinfo where id in (
    select id from (select id from userinfo where id > max_id limit 30) as N order by N.id desc limit 10
)
分页相关

 

posted @ 2019-02-26 20:21  Jimmyhe  阅读(285)  评论(0编辑  收藏  举报