-
一、SQL結構化查詢語言
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)
-
6、查詢數據
(1)語法:select <字段1,字段2,…> from <表名> where <表達式> #其中,select,from,where是不能隨便改的,是關鍵字,支持大小寫 (2)不進入庫查詢 MariaDB [(none)]> select * from oldboy.test1 where name="oldboy"; +----+--------+------+ | id | name | age | +----+--------+------+ | 1 | oldboy | 40 | +----+--------+------+ 1 row in set (0.01 sec) (3)只查詢前2行 MariaDB [oldboy]> select * from test1 limit 2; +----+---------+------+ | id | name | age | +----+---------+------+ | 1 | oldboy | 40 | | 2 | oldgirl | 60 | +----+---------+------+ 2 rows in set (0.00 sec) (4)從第二條開始查,查找2個 MariaDB [oldboy]> select * from test1 limit 1,2; +----+---------+------+ | id | name | age | +----+---------+------+ | 2 | oldgirl | 60 | | 3 | inca | 20 | +----+---------+------+ 2 rows in set (0.00 sec) (5)按照條件查詢 MariaDB [(none)]> select * from oldboy.test1 where name="oldboy"; +----+--------+------+ | id | name | age | +----+--------+------+ | 1 | oldboy | 40 | +----+--------+------+ #提示:查找字符串類型的條件的值要帶單引號,數字值不帶引號。 (6)查詢多個條件 MariaDB [oldboy]> select * from test1 where name='oldgirl' and id=2; +----+---------+------+ | id | name | age | +----+---------+------+ | 2 | oldgirl | 60 | +----+---------+------+ 1 row in set (0.00 sec) (7)范圍查詢 MariaDB [oldboy]> select * from test1 where id>2; +----+------+------+ | id | name | age | +----+------+------+ | 3 | inca | 20 | | 4 | zuma | 30 | | 5 | kaka | 33 | +----+------+------+ 3 rows in set (0.00 sec) (8)示例: 創建學生表 drop table student; create table student( Sno int(10) NOT NULL COMMENT '學號', Sname varchar(16) NOT NULL COMMENT '姓名', Ssex char(2) NOT NULL COMMENT '性別', Sage tinyint(2) NOT NULL default '0' COMMENT '學生年齡', Sdept varchar(16) default NULL COMMENT '學生所在系別', PRIMARY KEY (Sno) , key index_Sname (Sname) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 插入內容 create table course( Cno int(10) NOT NULL COMMENT '課程號', Cname varchar(64) NOT NULL COMMENT '課程名', Ccredit tinyint(2) NOT NULL COMMENT '學分', PRIMARY KEY (Cno) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 插入內容 CREATE TABLE `SC` ( SCid int(12) NOT NULL auto_increment COMMENT '主鍵', `Cno` int(10) NOT NULL COMMENT '課程號', `Sno` int(10) NOT NULL COMMENT '學號', `Grade` tinyint(2) NOT NULL COMMENT '學生成績', PRIMARY KEY (`SCid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 插入內容 INSERT INTO course values(1001,'Linux中高級運維',3); INSERT INTO course values(1002,'Linux高級架構師',5); INSERT INTO course values(1003,'MySQL高級Dba',4); INSERT INTO course values(1004,'Python運維開發',4); INSERT INTO course values(1005,'Java web開發',3); 插入內容 INSERT INTO SC(Sno,Cno,Grade) values(0001,1001,4); INSERT INTO SC(Sno,Cno,Grade) values(0001,1002,3); INSERT INTO SC(Sno,Cno,Grade) values(0001,1003,1); INSERT INTO SC(Sno,Cno,Grade) values(0001,1004,6); INSERT INTO SC(Sno,Cno,Grade) values(0002,1001,3); INSERT INTO SC(Sno,Cno,Grade) values(0002,1002,2); INSERT INTO SC(Sno,Cno,Grade) values(0002,1003,2); INSERT INTO SC(Sno,Cno,Grade) values(0002,1004,8); INSERT INTO SC(Sno,Cno,Grade) values(0003,1001,4); INSERT INTO SC(Sno,Cno,Grade) values(0003,1002,4); INSERT INTO SC(Sno,Cno,Grade) values(0003,1003,2); INSERT INTO SC(Sno,Cno,Grade) values(0003,1004,8); INSERT INTO SC(Sno,Cno,Grade) values(0004,1001,1); INSERT INTO SC(Sno,Cno,Grade) values(0004,1002,1); INSERT INTO SC(Sno,Cno,Grade) values(0004,1003,2); INSERT INTO SC(Sno,Cno,Grade) values(0004,1004,3); INSERT INTO SC(Sno,Cno,Grade) values(0005,1001,5); INSERT INTO SC(Sno,Cno,Grade) values(0005,1002,3); INSERT INTO SC(Sno,Cno,Grade) values(0005,1003,2); INSERT INTO SC(Sno,Cno,Grade) values(0005,1004,9); 檢查,查看表格式或者表內容 MariaDB [oldboy]> desc SC; or select * from SC; +-------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------+------+-----+---------+----------------+ | SCid | int(12) | NO | PRI | NULL | auto_increment | | Cno | int(10) | NO | | NULL | | | Sno | int(10) | NO | | NULL | | | Grade | tinyint(2) | NO | | NULL | | +-------+------------+------+-----+---------+----------------+
