SQL,英文全称Structured Query Language,中文意思是结构化查询语言。它是一种对关系数据库中的数据进行定义和操作的语言方法,是大多数关系数据库管理系统所支持的工业标准。
SQL分类:
DDL:数据定义语言,CREATE,ALTER,DROP。管理基础数据 <--运维熟练
DCL:数据控制语言,GRANT,REVOKE,COMMIT,ROLLBACK,用户授权,权限回收,数据提交回滚 <--运维要熟悉
DML:数据操作语言,SELECT,INSERT,DELETE,UPDATE,针对数据库里的表里的数据进行操作 <--开发熟练,运维了解
-
二、数据库基础管理
-
1、登录MySQL方法
(1)单实例MySQL登录的方法 mysql #无密码登录方式 mysql -u root #指定用户无密码登录 mysql -uroot -p #标准dba命令行登录 mysql -uroot -p123456 #非脚本一般不这样使用,密码明文,容易泄露 (2)多实例防止密码泄露登录的方法 设置变量:HISTCONTROL=ignorespace mysql -uroot -p123456 -S /data/3306/mysql.sock (3)远程链接登录 mysql -uroot -p -h 192.168.56.11 -P3306 -h 指定ip地址,-P指定端口号
-
2、MySQL数据库安全策略介绍
(1)为root设置比较复杂的密码 (2)删除无用的mysql库内的用户账号,只留root@localhost (3)删除默认的test数据库 (4)删除用户的时候,授权的权限尽量最小,允许访问的主机范围最小化 (4)针对mysql数据库的用户处理,还有更严格的做法,例如删除root用户,添加新的管理员用户
-
3、命令讲解
-
(1)创建数据库
(1) 语法:create database 库名; (2)查看建表语句:show create database 库名; (3)创建指定字符集的数据库:create database 库名 default character set 字符 collate 校对方式; (4)查看字符集:show character set; (5)示例:create database test1; show create database test1; create database test3 default character set utf8 collate utf8_general_ci; #创建utf8格式 #如果编译的时候指定了特定的字符集,则以后创建对应字符集的数据库就不需要指定字符集 -DDEFAULT_CHARSET=utf8 \ -DDEFAULT_COLLATION=utf8_general_ci \ -DEXTRA_CHARSETS=gbk,gb2312,utf8,ascii \ #提示:二进制软件包,安装的数据库字符集默认latinl
-
(2)切换数据库
(1)语法:use <dbname> (2)示例:use test1;
-
(3)查看数据库
(1)语法:select database(); #相当于pwd select user(); #查看当前用户 select version(); #查看当前版本 select now(); #查看当前时间
-
(4)删除数据库
(1)语法 drop database <dbname> (2)示例 drop database test1;
-
(5)删除数据库中指定用户
(1)语法:drop user "user"@"主机域" (2)要求:可以是单引号,也可以是双引号。但是不能不加。如果主机名中有大写字母的则 drop 删除不了,可以用 delete 语句来删除 mysql.user 表中的用户。 delete from mysql.user where user=’root’ and host=’oldboy’; flush privileges; (3)示例: drop user 'root'@'localhost'; drop user 'system'@"localhost"; drop user ''@"localhost";
-
(6)创建用户和授权
(1) 查看 GRANT 命令帮助获取创建用户并授权的例子: MariaDB [test1]> help grant; CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; GRANT ALL ON db1.* TO 'jeffrey'@'localhost'; GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost'; GRANT USAGE ON *.* TO 'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 90; (2)普通授权方法:先 Create 后 grant a、语法 CREATE USER 'username'@'主机域' IDENTIFIED BY 'mypass'; GRANT ALL ON dbname.* to 'username'@'localhost' b、示例 create user 'user1'@'localhost' identified by '123456'; grant all on test1.* to 'user1'@'localhost'; (3)运维人员常用创建用户方法:使用 grant 命令在创建用户的同时进行授权
a、语法 GRANT ALL PRIVILEGES ON dbname.* to 'username'@'主机域' identified by 'password'; b、说明 GRANT ALL PRIVILEGES ON dbname.* to 'username'@'主机域' identified by 'password' 授权命令 对应权限 目标:库和表 用户名和客户端主机 用户密码 说明:上述命令是授权localhost主机上通过用户username管理dbname数据库的所有权限,密码为passwd,其中username,dbname,passwd可根据业务的情况修改 对于web连接用户授权尽量采用最小化原则,很多开源软件都是web界面安装,因此在安装期间除了select,insert,update,delete 4个权限外,还需要create,drop等比较危险的权限。 grant select,insert,update,create,drop on blog.* to blog@localhost identified by ‘123’ 常规情况下授权select,insert,update,delete 4个权限即可,有的源软件,例如discuz,bbs还需要create,drop等比较危险的权限。生成数据库表后,要收回create,drop授权 (4)远程主机授权连接数据库 grant 命令的语法中主机域部分为授权访问数据库的客户端主机,可以用域名、 IP 或 IP 段来表示。远程主机 的授权方法有 2 种,具体如下: a、方法一:百分号匹配法 grant all on *.* to test@'192.168.0.%' identified by '123456'; flush privileges; b、方法二:子网掩码匹配法 grant all on *.* to test@'192.168.1.0/24' identified by '123456'; grant all on *.* to test@'192.168.1.0/255.255.255.0' identified by '123456'; flush privileges; #如果是web连接数据库,尽量不要授权all,而是select,insert,update,delete (5)查看权限 MariaDB [test1]> grant all on test1.* to test@'192.168.56.0/24' identified by '123456'; Query OK, 0 rows affected (0.00 sec) MariaDB [test1]> show grants for test@'192.168.56.0/24'; +-------------------------------------------------------------------------------------------------------------------+ | Grants for test@192.168.56.0/24 | +-------------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'test'@'192.168.56.0/24' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | | GRANT ALL PRIVILEGES ON `test1`.* TO 'test'@'192.168.56.0/24' | +-------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) 查看权限可以看出授权是分为 2 步: 第一步是授权可登陆 GRANT USAGE ON *.*。 USAGE 表示只有登陆权限。 第二步是授权可访问 ON `test1`.* TO 'test'@'192.168.56.0/24' (6)权限回收 MariaDB [test1]> revoke insert on test1.* from test@'192.168.56.0/24'; Query OK, 0 rows affected (0.01 sec) MariaDB [test1]> show grants for test@'192.168.56.0/24'; +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for test@192.168.56.0/24 | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'test'@'192.168.56.0/24' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | | GRANT SELECT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `test1`.* TO 'test'@'192.168.56.0/24' | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) #MySQL 权限列表如下 SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY, TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER MySQL包含关系 :数据库服务器>数据库(多个实例)>多个库>多个表>多个字段行列(数据) -
(7)创建表
(1)语法:create table <表名>( <字段名1><类型n>); 提示:其中create table是关键字,不能更改,但是大小写可以变化 (2)下面是人工写法设计的建表语句例子,表名student create table student( id int(4) not null, name char(20) not null, age tinyint(2) NOT NULL default '0', dept varchar(16) default NULL ); (3)查看创建表的语句 mysql> show create table student; create table student( #create table表示创建表的固定关键字,student为表名 id int(4) not null, #学号列,数字类型,长度为4,不能为空值 name char(20) not null, #名字列,定长字符类型,长度20,不能为空 age tinyint(2) NOT NULL default '0', #年龄列,很小的数字类型,长度为2,不能为空,默认为0值 dept varchar(16) default NULL #性别列,变长字符类型,长度16,默认为空。 ENGINE=lnnoDB DEFAULT CHARSET=latinl #引擎和字符集,引擎默认为InnoDB,字符集,继承库的latinl ); #需要注意的事:MySQL5.1和MySQL5.5 环境的默认建表语句中的引擎的不同,如果希望控制引擎,就要在建表语句里显示的指定引擎建表;MySQL5.1以及默认引擎为MyISAM,MySQL5.5,以后默认引擎为InnoDB。
-
(8)生产场景案例
某sns产品生产正式建表语句
use sns; set names gbk; CREATE TABLE `subject_comment_manager` ( `subject_comment_manager_id` bigint(12) NOT NULL auto_increment COMMENT '主键', `subject_type` tinyint(2) NOT NULL COMMENT '素材类型', `subject_primary_key` varchar(255) NOT NULL COMMENT '素材的主键', `subject_title` varchar(255) NOT NULL COMMENT '素材的名称', `edit_user_nick` varchar(64) default NULL COMMENT '修改人', `edit_user_time` timestamp NULL default NULL COMMENT '修改时间', `edit_comment` varchar(255) default NULL COMMENT '修改的理由', `state` tinyint(1) NOT NULL default '1' COMMENT '0代表关闭,1代表正常', PRIMARY KEY (`subject_comment_manager_id`), KEY `IDX_PRIMARYKEY` (`subject_primary_key`(32)), #<==括号内的32表示对前32个字符做前缀索引。 KEY `IDX_SUBJECT_TITLE` (`subject_title`(32)) KEY `index_nick_type` (`edit_user_nick`(32),`subject_type`)#<==联合索引,此行为新加的,用于给大家讲解的。实际表语句内没有此行。 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -
4、索引
-
(1)为表的字段创建索引
索引就象书的目录一样,如果在字段上建立了索引,那么以索引为查询条件时可以加快查询数据的速度. 创建主键索引 查询数据库,按主键查询是最快的,每个表只有一个主键列,但是可以用多个普通索引列。主键列要求列的所有内容必须唯一,而普通索引不要求内容必须唯一 主键就类似我们在学校学习时的学号一样,班级内是唯一的,整个表的每一条记录的主键值在表内都是唯一的,用来唯一标识一条记录。 (1)建立主键索引的方法: drop table student; create table student( id int(4) not null AUTO_INCREMENT, name char(20) not null, age tinyint(2) NOT NULL default '0', dept varchar(16) default NULL, primary key(id), KEY index_name(name) ); #提示: # primary key(id)<==主键 # KEY index_name(name)<==name字段普通索引 (2)mysql> desc student; 查看刚刚创建的表结构。 +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | name | char(20) | NO | MUL | NULL | | | age | tinyint(2) | NO || 0 | | | dept | varchar(16) | YES | | NULL| | +-------+-------------+------+-----+---------+----------------+ #PRL为主键的标示,MUL为普通索引的表示 ,auto_increnment 代表数据自增 (3)利用alter命令修改id列为自增主键值 alter table student change id id int primary key auto_increment; 创建的表的时候,可以指定 mysql> create table student( id int(4) not null AUTO_INCREMENT, name char(20) not null, age tinyint(2) NOT NULL default '0', dept varchar(16) default NULL, primary key(id), KEY index_name(name) ); 提示: KEY index_name(name) <==name字段普通索引 优化:在唯一值多的列上建索引查询效率高 还可以自定义自增的长度 EBGUBE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; (4)查看索引【前提都需要进入库】 show index from student; 查看索引\G 可以查看的更详细:show index from student\G
-
(2)查看表结构
(1)语法:desc 表名 (2)示例:desc student;
-
(3)建表后利用alter增加普通索引,删除建表时创建的index_name索引
(1)语法:alter table 表名 add|drop index 索引名称 alter table student add index index_name; alter table student drop index index_name;
(2)示例: create index index_name on student(name); #创建索引 show index from student; #查看索引 create index index_age on student(name(8)); #创建指定n个字符索引 show index from student\G #查看索引
-
(4)为表的多个字段创建联合索引
如果查询数据的条件是多列时,我们可以为多个查询的列创建联合索引,甚至,可以为多个列的前n个字符创建联合索引,演示如下:
创建联合索引,和单个索引不冲突
create index ind_name_dept on student(name,dept); #在student表创建联合索引 联合索引作用,查询更快 show index from student\G 创建联合索引,并指定值大小: create index ind_name_dept on student(name(8),dept(10)); #name 前8个字符,dept 前10个字符 #提示:尽量在唯一值多的大表上建立索引。
什么时候创建联合索引?
只有程序用这两个条件查询,采用联合索引,这个主要是看开发。
提示:按条件列查询数据时,联合索引是由前缀生效特性的
-
(5) 创建唯一索引(非主键)
create unique index uni_ind_name on student(name);
-
(6)索引小结:
创建主键索引: alter table student chage id id int primary key auto_increment;
删除主键索引(主键列不能自增): alter table student drop primary key;
添加普通索引: alter table student add index index_dept(dept);
根据的前n个字符创建索引: create index index_dept on student(dept(8));
根据多个列创建联合索引: create index index_name_dept on student(name,dept);
创建唯一索引: create unique index uni_ind_name on student(name);
删除普通索引与唯一索引: alter table student drop index index_dept; drop index index_dept on student;
-
(7)索引列的创建及生效条件
Q1:既然索引可以加快查询速度,那么就给所有的列加索引吧? A1:因为索引不但占用系统空间,而且更新数据时还需要维护索引数据的,因此索引是一把双刃剑,并不是越多越好,例如:数十到几百行的小表上无需建立索引,插入更新频繁,读取比较少的需要少建立索引. Q2:需要在哪些列上创建索引才能加快查询速度呢? select user,host from mysql.user where password=…..,索引一定要创建在where后的条件列上,而不是select后的选择数据的列上。另外,我们要尽量选择在唯一值多的大表上的列建立索引,例如,男女生性别列唯一值少,不适合建立索引。
-
(8)查看唯一值数量
select count(distinct user) from mysql.user; 唯一值就是相同的数量,例如查询user那么相同的user就是唯一值
-
(9)创建索引的基本知识小结:
■ 索引类似书籍的目录,会加快查询数据的速度
■ 要在表的列(字段)上创建索引
■ 索引会加快查询速度,但是也会影响更新的速度,因为更新要在维护索引数据
■ 索引列并不是越多越好,要在频繁查询的表语句where后的条件列上创建索引
■ 小表或重复值很多的列上可以不建索引,要在大表以及重复值少的条件上创建索引
■ 多个列联合索引有前缀生效特性
■ 当字段内容前N个字符已经接近唯一时,可以对字段的前N个字符创建索引
■ 索引从工作方式区别,有主键,唯一,普通索引
■ 索引类型有BTREE(默认)和hash(适合做缓存(内存数据库))等。
-
(10)主键索引和唯一索引的区别
(1)对于主键/unique constraint oracle/sql server/mysql等都会自动建立唯一索引; (2)主键不一定只包含一个字段,所以如果你在主键的其中一个字段建唯一索引还是必要的; (3)主健可作外健,唯一索引不可; (4)主健不可为空,唯一索引可; (5)主健也可是多个字段的组合; (6)主键与唯一索引不同的是: a.有not null属性; b.每个表只能有一个。
-
5、往表中插入数据
(1)命令语法:insert into <表名>[(<字段名1>[..<字段名n>])]values(值1)[,(值n)] (2)建立测试表: CREATE TABLE `test1` ( `id` int(4) NOT NULL, `name` char(16) NOT NULL, `age` int(2) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 (3)插入值 insert into test1(id,name,age) values(1,'gaoyuliang',60); insert into test1 values(2,"xiaoqiang",12); (4)查询 select * from test1; +----+------------+------+ | id | name | age | +----+------------+------+ | 1 | gaoyuliang | 60 | | 2 | xiaoqiang | 12 | +----+------------+------+ (5)批量插入 insert into test1 values(3,'xiaohong',20),(4,'xiaogang',23); MariaDB [oldboy]> select * from test1; +----+------------+------+ | id | name | age | +----+------------+------+ | 1 | gaoyuliang | 60 | | 2 | xiaoqiang | 12 | | 3 | xiaohong | 20 | | 4 | xiaogang | 23 | +----+------------+------+ (6)清空表中所有值 MariaDB [oldboy]> truncate table test1; Query OK, 0 rows affected (0.00 sec) MariaDB [oldboy]> select * from test1; Empty set (0.00 sec) (7)一条命令创建 MariaDB [oldboy]> insert into test1 values (1,'oldboy',40),(2,'oldgirl',60),(3,'inca',20),(4,'zuma',30),(5,'kaka',33); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 MariaDB [oldboy]> select * from test1; +----+---------+------+ | id | name | age | +----+---------+------+ | 1 | oldboy | 40 | | 2 | oldgirl | 60 | | 3 | inca | 20 | | 4 | zuma | 30 | | 5 | kaka | 33 | +----+---------+------+ 5 rows in set (0.00 sec)