一、数据库基本概念

1、数据库设计的步骤

    六个阶段:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库实施、数据库运行与维护

二、MySQL编程语言

1、MySQL函数

    1.1、聚合函数
        count():计数(对于除“*”以外的任何参数,返回所选集合中非null值的数目)
        sun():求和
        avg():求平均数
        max():求最大值
        min():求最小值
    1.2、数学函数
        abs():求绝对值
        floor():返回小于或等于参数的最大整数
        rand():返回0~1之间的随机数
        truncate(x,y):返回x保留到小数点后y为的值
        sort(): 求参数的平方根
    1.3、字符串函数
        upper()和ucase():把字符串所有字母变成大写字母
        left(s,n):返回字符串s的前n个字符
        substring(s,n,len):从字符串s的第n个位置开始获取长度为len的字符串
    1.4、日期和时间函数
        curdate()和current_date():返回当前日期
        curtime()和current_time():获取当前时间
        now():获取当前日期和时间,current_timestamp()、localtime()、sysdate()、localtimestamp()同样可以获取当前日期和时间
    1.5、其他函数
        if(expr,v1,v2):条件判断函数,如果表达式expr成立,则执行v1,否则执行v2
        ifnull(v1,v2):条件判断函数,如果表达式v1不为空,则显示v1的值,否则显示v2的值
        version():获取数据库的版本号

三、数据定义

1、定义数据库

    1.1、创建数据库
        create {database | schema} [if not exists] db_name [[default] character set [=] charset_name [[default] collate [=] collation_name];
    1.2、选择和查看数据库
        use da_name;
        show {databases | schemas};
    1.3、修改数据库
        alter {database | schema} [db_name] [[default] character set [=] charset_name [[default] collate [=] collation_name];
        数据库名可省略,表示修改当前数据库
    1.4、删除数据库
        drop {database | schema} [if exists] db_name;

2、定义表

    2.1数据类型
        2.1.1、数值类型
            bit
            tinyint
            bool,boolean
            smallint
            mediumint
            int,integer
            bigint
            double
            decimal(m.d)
        2.1.2、日期和时间类型
            date:日期型,MySQL以“YYYY-MM-DD”格式显示date值
            datetime:日期和时间类型,MySQL以“YYYY-MM-DD HH:MM:SS”格式显示datetime值
            timestamp:时间戳
            time:时间型,MySQL以“HH:MM:SS”格式显示time值
            year两位或四位格式的年
        2.1.3、字符串类型
            char:定长字符串
            varchar:可变长字符串
            tinytext
            text
    2.2、创建表
        create table tbl_name (
                字段名1 数据类型 [列级完整性约束条件] [默认值]
                [,字段名2 数据类型 [列级完整性约束条件] [默认值]
                [,... ...]
                [,表级完整性约束条件]
                ) [engine=引擎类型];
    2.3、查看表
        2.3.1、查看表名称
            show tables [{from | in } db_name];
        2.3.2、查看数据表的基本结构
            show columns {from | in } tb_name [from | in } db_name];
            或
            desc tb_name;
        2.3.3、查看数据表的详细结构
            show create table tb_name;
    2.4、修改表
        2.4.1、添加字段
            alter table tb_name add [column] 新字段名 数据类型 [约束条件] [first | after 已有字段名];
        2.4.2、修改字段
            # 可改指定列的名称和数据类型,修改多个彼此用逗号分隔
            alter table tb_name change [column] 原字段名 新字段名 数据类型 [约束条件];
            # 修改或删除指定列的默认值
            alter table tb_name alter [column] 字段名 {set | drop} default;
            # 修改列的数据类型,而不改名
            alter table tb_name modify [column] 字段名 数据类型 [约束条件] [first | after 已有字段名];
        2.4.3、删除字段
            alter table tb_name drop [column] 字段名;

    2.5、重命名表
        alter table 原表名 rename [to] 新表名;
        或
        rename table 原表名1 to 新表名1 [,原表名2 to 新表名2]......;
    2.6、删除表
        drop table [if exists] tb_name1 [,tb_name2]......;

3、数据的完整性约束

    3.1、定义实体完整性
        3.1.1、主键约束
            一个表必须要有一个主键,且唯一不为空
        3.2.2、完整性约束的命名
            constraint <约束名> {primary key(主键字段列表) | unique(候选键字段列表) |foreign key(外键字段列表) references tb_被参照的关系(表) (主键字段列表) | check(约束条件表达式)};
    3.2、定义参照完整性
        外键需存在或为空
    3.3、用户定义完整性
        MySQL支持的几种用户定义完整性约束:非空约束,check约束和触发器
        check约束:
            check(expr);
    3.4、更新完整性约束
        3.4.1、删除约束
            alter table <表名> drop foreign key <外键约束名>;
            alter table <表名> drop primary key;
            alter table <表名> drop {约束名 | 候选键字段名};
        3.4.2、添加约束
            alter table <表名> add [constraint <约束名>] primary key(主键字段);
            alter table <表名> add [constraint <约束名>] foreign key(外键字段名) references 被参照表(主键字段名);
            alter table <表名> add [constraint <约束名>] unique key(字段名);

四、数据查询

1、select语句

    select [all | distinct | distinctrow] <目标表达式1>[,目标表达式2]...
    form <表名1 或 视图1>[,<表名2 或视图2]...
    [where <条件表达式>]
    [group by <列名1> [having <条件表达式>]]
    [order by <列名2> [asc | desc]]
    [limit[m,]n]

2、单表查询

    2.1、选择字段
        select 目标表达式1, 目标表达式2,...,目标表达式n from 表名;
        select * form 表名;
        # 定义字段的别名
        select 字段名 as 字段别名 from 表名;
    2.2、选择指定的字段
        select 目标表达式1, 目标表达式2, ... , 目标表达式n  from 表名 where 查询条件;
        # 带between ...and...
        select 目标表达式1, 目标表达式2, ... , 目标表达式n  from 表名 where expression [not] between expr1 and expr2;
        #带like关键字,换码字符也叫转义字符,如果字符串本身含有通配符_和%,就需要换码字符
        select 目标表达式1, 目标表达式2, ... , 目标表达式n  from 表名 where 字段名 [not] like '<匹配字符串>'[escape '<换码字符>'];
        #使用正则表达式查询
        select 目标表达式1, 目标表达式2, ... , 目标表达式n  from 表名 where 字段名 [not] [regexp | rlike] <正则表达式>;
        # 限制查询结果数目
        limit 行数 offset 位置偏移数;

3、分组聚合查询

    3.1、使用聚合函数
        group by 字段列表 having <条件表达式>;

4、连接查询

    4.1、交叉查询(笛卡尔积):用得极少
        select * from tb_name1 cross join tb_name2;
        或
        select * from tb_name1, tb_name2;
    4.2、内连接
        select 目标表达式1, 目标表达式2, ... , 目标表达式n from table1 [as] 别名1 [inner] join table2 [as] 别名2 on 连接条件 [where 过滤条件];
        select 目标表达式1, 目标表达式2, ... , 目标表达式n from table1, table2 where 连接条件 [and 过滤条件];
        4.2.1、等值于非等值连接
            [<table1>.]<字段名1> <比较运算符> [<table2>.]<字段名2>;
        4.2.2、自连接
            使用自连接时,需要指定多个不同的别名,查询字段都有别名来限定
        4.2.3、自然连接
            两张表中的字段名都相同才可以使用,否则放回笛卡尔积结果
            select 目标表达式1, 目标表达式2, ... , 目标表达式n from table1 [as] 别名1 natural join table2 [as] 别名2;
    4.3、外连接
        # 左外连接
        select 目标表达式1, 目标表达式2, ... , 目标表达式n from table1 [as] 别名1 left [outer] join table2 [as] 别名2 on 连接条件 [where 过滤条件];
        # 右外连接
        select 目标表达式1, 目标表达式2, ... , 目标表达式n from table1 [as] 别名1 right [outer] join table2 [as] 别名2 on 连接条件 [where 过滤条件];

5、子查询

    子查询关键字:in, any, all, [not]exists, 
    必要时为表名加上别名         

6、联合查询

    select -from-where
    union [all]
    select -from-where
    [...union [all]
    select -from-where]
    多个表查询联合起来,不使用all关键字,执行的时候去重,返回的行都是唯一的,使用all则不去重。

五、数据更新

1、插入数据

    1.1、插入一条或多条
    insert into table(字段名列表) values(值列表1), [,值列表2], ... ,[值列表n];
    replace into table(字段名列表) values(值列表1), [,值列表2], ... ,[值列表n];
    1.2、插入查询结果
    insert into table1(字段名列表) select (字段名列表) from table2 where(conditions);

2、修改数据记录

    update table set 字段名1=值1, 字段名2=值2, ... , 字段名n=值n [where <conditions>];

3、删除数据记录

    delete from table [where<conditions>];
    truncate [table] tb_name;

六、索引

1、什么时候需要创建索引

 a.主键自动建立唯一索引
 b.频繁作为查询条件的字段应该创建索引
 c.查询中排序的字段创建索引将大大提高排序的速度(索引就是排序加快速查找
 d.查询中统计或者分组的字段;


2、什么时候不需要创建索引

a.频繁更新的字段不适合创建索引,因为每次更新不单单是更新记录,还会更新索引,保存索引文件
b.where条件里用不到的字段,不创建索引;
c.表记录太少,不需要创建索引;
d.经常增删改的表;
e.数据重复且分布平均的字段,因此为经常查询的和经常排序的字段建立索引。注意某些数据包含大量重复数据,因此他建立索引就没有太大的效果,例如性别字段,只有男女,不适合建立索引。


3、索引的分类:

a.普通索引:最基本的索引,它没有任何限制
b.唯一索引:索引列的值必须唯一,且不能为空,如果是组合索引,则列值的组合必须唯一。
c.主键索引:特殊的索引,唯一的标识一条记录,不能为空,一般用primary key来约束。
d.联合索引:在多个字段上建立索引,能够加速查询到速度

1、查看数据表上的索引

    show {index | indexes | keys} {fron | in } tb_name [{from | in } db_name];

2、创建索引

    2.1、建表时创建
        create table(字段名, 字段类型...) [constrint index_name] [unique] [index | key] [index_name](字段列名[长度]) [asc | aesc];
    2.2、使用create index
        create [unique] index index_name on tb_name(字段名[(长度)] [asc | desc] , ...);
    2.3、使用alter table
        alter table tb_name add [unique | fulltext] [index|key] index_name(字段名[(长度)][asc|desc],...)

3、删除索引

    drop index index_name on tb_name;
    alter table tb_name drop index index_name;

七、视图

1、创建视图

    create [or replace] view view_name[(column_list)] as select_statement [with [cascaded | local] check option];

2、删除视图

    drop view [if exists] view_name[,view_name]...;

3、修改视图

    alter view view_name [(column_list)] as select_statement [with [cascaded | local] check option];

4、查看视图定义

    show create view view_name\G

八、触发器

1、创建触发器

    create trigger trigger_name trigger_time(before|after) trigger_event(insert|update|delete) on tb_name for each row trigger_body;
    # 查看已有的触发器
        show triggers [{from | in} db_name]; 

2、删除触发器

    drop trigger [if exists] [schema_name.]trigger_name;

3、使用触发器

    在insert触发器中可以引用名为new的虚拟表来访问被插入的行
    在delete触发器中可以引用名为old的虚拟表来访问被删除的行
    在delete触发器中可以引用名为new的虚拟表来访问更新后的值
    在delete触发器中可以引用名为old的虚拟表来访问更新前的值
    例子:
        create trigger tg1 after update on tb_name1 for each row set new.col1 = old.col2; 

九、事件(临时触发器)

1、创建事件

    create event [if not exists] event_name on schedule 时间调度 [enable|disable|disable on slave] do event_body;
    时间调度语法格式:
        at timestamp [+ interval interval]... 
        | every interval 
        [starts timestamp [+ interval interval]...]
        [ends timestamp [+ interval interval]...]    
    interval语法格式
        quantity {year | quarter | month | day | hour | minute | week | second | year_month | day_hour | day_minute| day_second | hour_minute | hour_second | minute_second}
    例子:
        每个月向表tb_1插入一条数据,该事件开始于下个月并且结束于2019年12月31日。
            首先改变结束符:delimiter 
                create event if not exists event_insert
                    on schedule every 1 month
                        starts curdate() + interval 1 month
                        ends  '2019-12-31'
                        do
                        begin
                            if year(curdate()) < 2013 then
                                insert into tb_1 values('aa','aa','b');
                            end if;
                        end       

2、修改事件

    alter event event_name 
        [on schedule 时间调度]
        [rename to new_name]
        [enable | disable | disable on slave]
        [do event_body];

3、删除事件

    drop event [if exists] event_name;    

十、存储过程和存储函数

1、存储过程

    1.1、创建存储过程
        create procedure sp_name ([proc_parameter[,...]]) [characteristic...]routine_body
        其中proc_parameter格式为
            [in | out | inout]param_name type
            分别对应输入、输出和输入/输出参数
        其中routine_body为存储过程主体:
            也称存储过程体,其中包含了在过程调用的时候必须执行的sql语句,这个部分以关键字begin开始,以关键字end结束。如存储过程体中只有一条sql语句,可以省略begin-end标志,另外begin-end可以嵌套。
    1.2、存储过程体
        1.2.1、局部变量
            声明:
                declare var_name [,...] type [defautl value]                
            ps:局部变量不同意用户变量,区别:局部变量声明时,在其前面没有使用“@”符号,并且它只能在声明它的begin-end语句块中使用,而用户变量前面使用“@”符号,存在整个会话中。
        1.2.2、赋值
            set var_name = expr[, var_name = expr]...
            或
            select 字段名 into var_name[,...] 查询源及条件;
        1.2.3、流程控制语句
            条件
                if search_condition then statement_list
                    [elseif search_condition then statement_list]...
                    [else statement_list]
                end if;
                或
                case case_vale
                    when when_value then statement_list
                    [when when_value then statement_list]
                    [else statement_list]
                end case;
                或
                case
                    when search_condition then statement_list
                    [when search_condition then statement_list]
                    [else statement_list]
                end case;
            循环
                [begin_label:]while search_condition do
                    statement_list
                end while[end_label];
                或
                [begin_label:]repeat
                    statement_list
                until search_condition
                end repeat[end_label];
                或
                [begin_label:]loop
                    statement_list
                end loop[end_label];
        1.2.4、游标
            # 声明游标
                declare cursor_name cursor for select_statement;
                # select_statement为一条select语句注意不能有into子句。
            # 打开游标
                open cursor_name;
            # 读取游标
                fetch cursor_name into var_name[,var_name]...;
            # 关闭游标
                close cursor_name;
            # 例子:统计行数
                delimiter {% math %}
                create procedure sp_sum(out rows int)
                    begin
                        declare sno char;
                        declare found boolean default true;
                        declare cur cursor for select studentNo from tb_students;
                        declare continue handler for not found
                            set found = false;
                        set rows = 0;
                        open cur;
                        fetch cur into sno;
                        while found do
                            set rows = rows +1;
                            fetch cur into sno;
                        end while;
                        close cur;
                    end{% endmath %}
    1.3、调用存储过程
        call sp_name([parameter[,...]]);
        call sp_name[()];
    1.4、删除存储过程
        drop procedure [if exists] sp_name;

2、存储函数

    2.1、与存储过程的区别
        # 存储函数不能有输出参数,因为存储函数本身就是输出参数,而存储过程可以有输出参数
        # 可以直接对存储函数进行调用,不需要使用call
        # 存储函数必须包含一条return语句,而这条语句不允许包含于存储过程中
    2.1、创建存储函数
        create function sp_name ([func_parameter[,...]]) 
            returns type
            routine_body
        # 例子:根据给定的学号返回学生性别,如果没有则返回“没有该学生”
            delimiter {% math %}
            create function fn_student(sno char(10))
                returns char(2)
                begin
                    declare ssex char(2);
                    select sex into ssex from student where studentNo = sno;
                    if ssex is null then
                        return (select "没有该学生");
                    else if ssex="女" then
                        return (select "女");
                        else return (select "男");
                    end if;
                end{% endmath %}
    2.2、调用存储函数
        select sp_name([func_parameter[,...]]);
    2.3、删除存储函数
        drop function [if exists] sp_name;                

十一、访问控制与安全管理

1、用户账号与管理

    1.1、创建用户账号
        create user user_specification [,user_specification]...;
        其中user_specification格式:
            user [indentified by [password] 'password' | identified with 指定认证的插件名称 [as 'auth_string']];
        # 例子:
            create user 'zhangsan@localhost' identified by '123','lisi@localhost' identified by password 'password(字符串)返回的散列值';
    1.2、删除用户
        drop user user_name [,user_name]...;
    1.3、修改用户账号
        rename user old_name to new_name [,old_name to new_name]...;
    1.4、修改用户密码
        set password [for user] = {password('new_password') | 'encryted password(表示已被password加密的口令值)' }
        # 如果不加for 则表示给当前用户改密码

2、账号权限管理

    2.1、权限的授予
        grant priv_type [(column_list)] [,priv_type[(column_list)]]... on [object_type] priv_level to user_specification [,user_specifition]...
            [require {none|ssl_option[[and]ssl_option]...}]
            [with with_option...]
        # priv_type
            如:select、update、delete
        # 其中object_type格式为:
            table | function | procedure
        # priv_level格式为:
            * | *.* | db_name.tb_name | tb_name | db_name.routine_name
        # user_specifition格式同上面
            说明该语句同样可以用来创建用户
        # with_option格式为:
            grant option 
            | max_queries_per_hour count    #每小时查询数据库的次数
            | max_updates_per_hour count    #每小时可以修改数据库的次数
            | max_connections_per_hour count    #每小时可以连接数据库的次数
            | max_user_connections count    #同时连接数据库的最大用户数
        例子:
            grant select(studentNo, studentName) on db_school.tb_student to 'lisi@localhost' identifie by '123';
            grant all on *.* to 'zhangsan@loclhost' identified by '123';
            grant create user on *.* to 'zhangsan@loclhost' identified by '123';
    2.2、权限的转移与限制
        2.2.1、转移
            with 子句指定为with grant option时,表示to 子句中所指定的所以用户都具有把自己所拥有的权限授予其他用户。
            例子:
                grant select, update on db_school.tb_student to 'lisi@localhost' identified by '123' with grant option;
        2.2.2、限制
            with子句后面跟关键字
            例子:
                grant delete on db_school.* to 'zhangsan@localhost' identified by '123' with MAX_QUERIES_PER_HOUR 1;
    2.3、权限的撤销
        # 回收某些特定的权限
        revoke priv_type [(column_list)] [,priv_type[(column_list)]]... on [object_type] priv_level form user [,user]...;
        或
        # 回收特定用户的所有权限
        revoke all privileges, grant option form user [,user]; 

十二、备份与恢复

1、使用sql语句备份和恢复表数据

    1.1、select into ... outfile语句导出备份
       select * into outfile 'file_name ' [character set charset_name ] export_options | into dumpfile 'file_name';
    # export_options格式:
        [fields
            [terminated by 'string']
            [[optionally] enclosed by 'char']
            [escaped by 'char']
        ]
        [lines terminated by 'string']
    1.2、load data ...infile语句导入恢复
        load data [low_priority | concurrent] [local] infile 'file_name.txt'
            [replace | ignore]
            into table tb_name
            [fields
                [terminated by 'string']
                [[optionally] enclosed by 'char']
                [escaped by 'char']
            ]   
            [lines 
                [starting by 'string']
                [terminated by 'string']
            ]     
            [IGNORE number LINES]
            [(col_name_or_user_var,...)]
            [set col_name = expr, ...]]
    例子:
        # 导出
            select * from db_school.tb_student into outfile 'C:\BACKUP\backupfiel.txt' fields terminated by ','optionally enclosed by '"' lines terminated by '?';
        # 导出
            load data infile 'C:\BACKUP\backupfiel.txt' into table db_school.tb_student_copy fields terminated by ',' optionally enclosed by '"' lines terminated by '?'

2、使用MySQL客服端实用程序备份和恢复数据

    2.1、备份表
        # 备份数据表
        mysqldump [option] database [tables] > filename;
        # 备份数据库    
        mysqldump [option] database --database [option] DB1 [DB2 DB3...] > filename;
        # 备份整个数据库系统
        msyqldump [option] --all-database [option] > fielname;
        # 例子:
            mysqldump -hlocalhost -uroot -p123 db_school.tb_table > c:\backup\file.sql;
            msyqldump -hlocalhost -uroot -p123 --database db_school > c:\backup\data.sql;
            msyqldump -uroot -p123 --all-database > c:\backup\alldata.sql;
    2.2、使用mysql命令恢复数据
        mysql -uroot -p123 tb_student < c:\backup\tb_student.sql;
    2.3、使用mysqlimport程序恢复数据
        mysqlimport [option] database textfile...;
        # option常用的有:
            -d、--delete:在导入文本文件之前清空所有的数据行
            -l、--lock-tables:在处理任何文本文件之前锁定所有的表,以保证所有的表在服务器上同步,但对于InnoDB类型的表则不必进行锁定
            --low-priority、--local、--replace、--ignore:分别对于load data ... infile 语句中的low_priority、local、replace和ignore关键字
        # 例子:
            mysqlimport -uroot -p123 --low-priority --replace db_school c:\backup\tb_student.txt;

3、二进制日志文件的使用

    3.1、查看二进制日志文件
        msyqlbinlog [option] log_file... [> c:\backup\bin_log000001.txt];
    3.2、使用二进制文件恢复数据
        msyqlbinlog [option] log_file... | msyql [option]        
        # 例子
            msyqlbinlog bin_log0001 | mysql -uroot -p123;
    3.3、删除二进制日志文件
        # 清除所有日志文件
        reset master;
        # 删除指定的日志文件
        purge {master | binary| logs to 'log_name':
        #删除某个时间之前的所有日志文件
        purge {master | binary| logs before 'date';

十三、MySQL数据库的应用编程

1、使用PHP进行MySQL数据库应用编程

    1.1、mysql连接
        # 非持久连接
        mysql_connect([servername[, username[,password]]]);
        # 持久连接
        mysql_pconnect([servername[, username[,password]]]);
        ps:如果msyql函数成功执行后连接成功,函数mysql_errno()和mysql_error会分别返回数值0和空字符串。
    1.2、选择数据库
        msyql_select_db(database[,connection])
    1.3、执行数据库操作
        msyql_query(query[,connection])
        ps:sql语句是以字符串的形式提交,且不以分号作为结束符。
    1.4、数据结果读取
        mysql_fetch_array(data[,array_type])
        # array_type有:
            MYSQL_NUM:表示数值数组,功能与mysql_fetch_row(data)一样
            MYSQL_ASSOC:表示关联数组,功能与mysql_fetch_assoc(data)一样
            MYSQL_BOTH:表示同时产生关联数组和数字数组
        mysql_fetch_row(data)
        msyql_fetch_assoc(data)
    1.5、读取结果数目
        mysql_num_rows(data)
    1.6、读取指定记录号的记录
        # 在结果集中随意移动记录的指针,也就是将记录指针直接指向某个记录,其中0指示结果集中的第一条记录。
        mysql_data_seek(data,row)
    1.7、关闭数据库
        msyql_close([content])
    # 例子:
        <? php
            $con = mysql_connect('localhost:3306','root','123')
            or die('数据库服务器连接失败!<br>’);
            mysql_select_db('db01',$con) or die('数据库选择失败!<br>‘);
            mysql_query("set names 'gbk'");
            $sql = "select studentname from tb_student";
            $sql = $sql."where studentNo = 200120";
            $result = mysql_query($sql, $con);
            if ($result){
                echo "学生查询成功!<br>"
                $array = mysql_fetch_array($result,MYSQL_NUM);
                if ($array){
                    echo "读取到学生信息!<br>";
                    echo "所查询的学生姓名为:".$array[0];
                }
                else echo "没有查询到学生信息!<br>";
            }
            else 
                echo "学生信息查询失败!<br>";
        ?>

results matching ""

    No results matching ""