SQL 結構化查詢語言
導讀
MySql是我們常用的資料庫,javaEE常用幾款(Oracle,PostgreSQL,DB2或IBM),SQLite是用於嵌入式裝置裡的小型資料庫,例如Android或IOS,而掌握SQL語句,就相當於掌握了所有的常見關係化資料庫,需要同學們重點掌握以及經常複習
MySQL資料庫伺服器、資料庫和表的關係
- 一般一個專案建一個數據庫,資料庫中又有一張張的table,table中的一條資料庫語句,相當於java中的實體bean類
- 一個java類 對應資料庫中一張資料表,一個java物件 對應資料表中一條資料記錄
SQL語言
Structured Query Language(SQL語言),結構化查詢語言
非過程性語言為加強SQL的語言能力,各廠商增強了過程性語言的特徵
- 如Oracle的PL/SQL 過程性處理能力
- SQL Server、Sybase的T-SQL
SQL是用來存取關係資料庫的語言,具有查詢、操縱、定義和控制關係型資料庫的四方面功能
SQL分類
DDL (資料定義語言)
- 資料定義語言 - Data Definition Language
- 用來定義資料庫的物件,如資料表、檢視、索引等
- 即操作資料庫或表結構的
- 所有資料庫相關操作語句,資料庫表結構操作語句都屬於DDL
DML (資料操縱語言)
- 資料處理語言 - Data Manipulation Language
- 在資料庫表中更新,增加和刪除記錄
- 如 update, insert, delete
DCL (資料控制語言)
- 資料控制語言 – Data Control Language
- 指用於設定使用者許可權和控制事務語句
- 如grant,revoke,if…else,while,begin transaction
DQL (資料查詢語言)
- 資料查詢語言 – Data Query Language
- select
SQL語句(重點)
掌握SQL語句,相當於掌握了所有的常見關係化資料庫,需要重點掌握以及經常複習
資料庫操作建議先在.txt檔案,寫好再把游標移動語句最後,shift+home複製整句過去
編寫sql語句沒有大小寫之分,注意不要拼錯單詞
MySQL5中文參考手冊 -> 部分不知道的欄位可以通過這個文件查詢
資料庫操作:
一 . 建立資料庫
- 語法 : create database 資料庫名稱; (建立資料庫採用資料庫伺服器預設字符集)
- 複雜寫法 : create database 資料庫名稱 character set 字符集 collate 比較規則;
練習:
1. 建立一個名稱為mydb1的資料庫。 create database mydb1;
2. 建立一個使用utf8字符集的mydb2資料庫。 create database mydb2 character set utf8;
3. 建立一個使用utf8字符集,並帶校對規則的mydb3資料庫。create database mydb3 character set utf8 collate utf8_bin;
==**補充: 每次建立一個數據庫在 資料存放目錄中生成一個資料夾 , 每個資料夾中存在 db.opt 存放預設字符集和校對規則
datadir=”C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/”**==
二 . 查詢資料庫
- 語法 : show databases; —– 檢視所有資料庫,沒有資料庫則返回沒資料null
- 語法 : show create database 資料庫名; —— 檢視資料編碼集
練習:
1. 檢視當前資料庫伺服器中的所有資料庫 show databases;
2. 檢視前面建立的mydb2資料庫的定義資訊 show create database mydb2;
三 . 刪除資料庫
- 語法 : drop database 資料庫名稱;
練習:
1. 刪除前面建立的mydb1資料庫 drop database mydb1;
四 . 修改資料庫
- 語法 : alter database 資料庫名稱 character set 字符集 collate 比較規則;
練習:
1. 修改mydb2字符集為gbk; alter database mydb2 character set gbk;
==補充:==
1. 切換資料庫 use db_name; -> 當有多個數據庫的情況,需要use db_name; 先切換到要操作的資料庫
2. 檢視當前正在使用資料庫: select database();
資料表操作:
一 . 建立資料表
- 語法 : create table 表名(列名 型別(長度),列名 型別(長度)… );
格式 :
create table 表名(
列名稱1 列名稱1值型別,
列名稱2 列名稱2值型別,
列名稱3 列名稱3值型別,
列名稱4 列名稱4值型別
);
列名稱1值型別 是 mysql 中執行的值的型別
注意最後一句沒有 ,
- MySQL 常用資料型別:
型別 | 說明 |
---|---|
字串型—String | Varchar(可變值)、char(固定值) ->若兩者最大值都為30,varchar如果資料只有20,最後就為20;char如果資料只有20,會自動補齊,char比varchar效率高點 |
大資料型別—位元組流,字元流 | BLOB、TEXT |
數值型–數值型別 (bit,byte,short,int,long,float,double) | TINYINT 、SMALLINT、INT、BIGINT、FLOAT、DOUBLE |
邏輯型 | BIT 存放以為數值 0 或者 1 |
日期型 | DATE(只有日期)、TIME(只有時間)、DATETIME(日期和時間)、TIMESTAMP時間可以自動跟新(當前時間) |
練習 :
建立一個員工表employee ---- 查看錶結構: desc 表名;
欄位 屬性
id 整形 int
name 字元型 varchar(30)
gender 字元型 varchar(10)
birthday 日期型 date
entry_date 日期型 date
job 字元型 varchar(50)
salary 小數型 double
resume 大文字型 varchar(255)
create table employee(
id int,
name varchar(30),
gender varchar(10),
birthday date,
entry_date date,
job varchar(50),
salary double,
resume varchar(255)
);
==補充:==
1. 建立表時沒有指定字符集,將採用資料庫預設字符集
2. 建立表之前 必須使用use db_name 語法指定操作資料庫
3. 查看錶結構: desc 表名
4. 建立資料表時,只有字串型別必須寫長度,而其他型別都有預設長度
5. 一個java類 對應資料庫中一張資料表,一個java物件 對應資料表中一條資料記錄
二 . 定義單表字段的約束
約束用來保證資料有效性和完整性
- 有效性: 類似日常生活防止姓名一樣,給個身份證號以保證身份的唯一性
- 完整性: 類似生活中一個人不告訴我們姓名就不讓他存資料,保證資料的完整性
定義主鍵約束(唯一,並且非空):
primay key -> 資訊記錄某個欄位可以唯一區分其他資訊記錄,這個欄位就可以是主鍵
如果列的型別為數值型(int bigint),並且宣告為主鍵,那麼通常會加上auto_increment,表示自動增長
唯一約束(不能重複,可以為空):
unique -> 一張表中可以有很多個唯一約束,只能有一個(兩個)作為主鍵約束
非空約束(可以重複,不能為空):
not null
練習:
create table employee2(
id int primary key auto_increment,
name varchar(30) not null,
gender varchar(10) not null,
birthday date,
entry_date date,
job varchar(50),
salary double not null,
resume varchar(255) unique
);
三 . 修改資料表結構
- 增加列 語法: alter table 表名 add 列名 型別(長度) 約束;
- 修改現有列型別、長度和約束 語法:alter table 表名 modify 列名 型別(長度) 約束;
- 修改現有列名稱 語法:alter table 表名 change 舊列名 新列名 型別(長度) 約束;
- 刪除現有列 語法:alter table 表名 drop 列名;
- 修改表名 rename table 舊錶名 to 新表名;
練習:
1. 修改表的字符集:—-alter table student character set utf8;
2. 在上面員工表的基本上增加一個image列: —-alter table employee add image varchar(100);
3. 修改job列,使其長度為60。 —-alter table employee modify job varchar(60) not null;
4. 刪除gender列。 —-alter table employee drop gender ;
5. 表名改為user。 —-rename table employee to user;
6. 修改表的字符集為utf8 —- alter table user character set utf8;
7. 列名name修改為username —– alter table user change name username varchar(20) unique not null;
==補充:==
1. 檢視當前資料庫內所有表:show tables;
2. 檢視當前資料表字符集 : show create table user;
3. 查看錶結構 : desc 表名;
四 . 刪除資料表
- 語法:drop table 表名;
練習:
1. 刪除employee2表:drop table employee2;
資料表中資料記錄的增刪改查操作:
一 . 插入資料:
語法一(全寫) :insert into 表名(列名,列名,列名…) values(值,值,值…);
- 如:insert into employee2(id,name,gender,birthday,entry_date,job,salary,resume) values(1,’zs’,’female’,’1995-09-09’,’2015-12-09’,’developer’,15000,’a good developer’);
語法二(只寫部分,欄位值屬性為空的可以不寫,不為空的值要寫)
- 如:insert into employee2 (id,name,gender,salary,resume) values(null,’haojie’,’male’,17000,’a hansome boy’);
語法三(不寫欄位名稱,只寫欄位值,但是所有的欄位值都要寫)
- 如:insert into employee2 values(null,’linpeng’,’male’,’1994-09-09’,’2015-12-22’,’programmer’,16000,’a lady killer’);
==補充:==
1. 插入值 型別必須和 列型別匹配
2. 值長度不能超過 列定義長度
3. 值的順序和 列順序對應
4. 字串和日期型值 必須寫 單引號
5. 插入空值 可以寫 null
6. 插入記錄後,使用select * from 表名; 查看錶資訊
可能出現的bug:
插入一條中文記錄
insert into employee(id,name,job,salary) values(4,'小明','清潔員',1500);
出錯了:
ERROR 1366 (HY000): Incorrect string value: '\xC3\xF7' for column 'name' at row 1 ;
錯誤原因:mysql client 採用預設字符集編碼 gbk
檢視系統所有字符集 : show variables like 'character%';
解決:修改客戶端字符集為gbk
MYSQL中共有6個地方字符集 :client connetion result 和客戶端相關 、database server system 和伺服器端相關
第一種:
當前視窗臨時修改 set names gbk ;
* 只對當前視窗有效,關閉後就會失效
第二種:
配置mysql/my.ini 檔案
[mysql] 客戶端配置
[mysqld] 伺服器端配置
修改客戶端字符集 [mysql] 後字符集 default-character-set=gbk
使用mysql -u root -p 密碼連入資料庫後,如果進行資料庫操作,直接操作,如果要進行資料表結構和資料記錄操作,必須先切換到操作的資料庫 use db;
二 . 資料記錄更改操作:
- 語法: update 表名 set 列名=值,列名=值…. where條件語句;
- 如果沒有where條件語句,預設修改所有行資料
練習:
1. 將所有員工薪水修改為5000元。 —– update employee set salary = 5000;
2. 將姓名為’zhangsan’的員工薪水修改為3000元。 ——- update employee set salary = 3000 where name=’zhangsan’;
3. 將所有員工薪水修改為5000元。 ——- update employee set salary=4000, job=’ccc’ where name=’lisi’;
4. 將wangwu的薪水在原有基礎上增加1000元。 ———— update employee set salary = salary+1000 where name =’wangwu’;
三 . 資料記錄的刪除操作:
語法:delete from 表名 where條件語句;
- 如果沒有where語句,將刪除表中 所有記錄
語法: truncate table 表名;
練習:
1. 刪除表中名稱為’zs’的記錄。—-delete from employee2 where name=’zs’;
2. 刪除表中所有記錄(DML語句)。—-delete from employee2;
3. 使用truncate刪除表中記錄。(先將表摧毀,然後再建立, 屬於DDL語句)—-truncate table employee2;
==補充:==
truncate 與 delete區別
1. truncate 刪除資料,過程先將整個表刪除,再重新建立
2. delete 刪除資料,逐行刪除記錄
3. truncate 屬於DDL,delete屬於DML——-事務管理只能對DML有效,被事務管理SQL語句可以回滾到SQL執行前狀態
4. truncate 效率要好於 delete
四 . 資料表記錄的查詢(DQL語句):
- 語法一 : select [distinct] * | 列名,列名… from 表名;
- select * from 表名; 查詢該表中所有列資訊
- select 列名,列名… from 表名; 查詢表中指定列的資訊
- distinct 用於去重
練習:
create table exam(
id int primary key auto_increment,
name varchar(20) not null,
chinese double,
math double,
english double
);
insert into exam values(null,'關羽',85,76,70);
insert into exam values(null,'張飛',70,75,70);
insert into exam values(null,'趙雲',90,65,95);
查詢表中所有學生的資訊。 --------- select * from exam;
查詢表中所有學生的姓名和對應的英語成績。 ----- select name,english from exam;
過濾表中重複資料 (查詢英語成績,排除完全相同重複資料) ---- select distinct english from exam;
- 語法二 : select 列名 as 別名 from 表名;
練習:
1. 在所有學生分數上加10分特長分。 —- select name,chinese+10,math+10,english+10 from exam;
2. 統計每個學生的總分。——- select name,chinese+math+english from exam;
3. 使用別名表示學生分數。—– select name,chinese+math+english as 總分 from exam;
4. 在對列起別名時,as可以省略 select name,chinese+math+english as 總分 from exam; —— select name,chinese+math+english 總分 from exam;
5. select name,math from exam; 查詢name和math兩列的值
6. select name math from exam; 查詢name列值,起別名math
- 語法三 : select 列名 from 表名 where條件語句
練習:
1. 查詢姓名為關羽的學生成績 ——-select * from exam where name=’關羽’;
2. 查詢英語成績大於90分的同學 —– select * from exam where english > 90;
3. 查詢總分大於200分的所有同學 —– select * from exam where chinese+math+english > 200;
- 語法四 : select * from 表名 order by 列名 asc|desc; —- asc升序 desc降序
練習:
1. 對數學成績排序後輸出。———– select * from exam order by math; 預設asc升序
2. 對總分排序按從高到低(降序)的順序輸出 ———— select * from exam order by math+chinese+english desc;
3. 對學生成績按照英語進行降序排序,英語相同學員按照數學降序 ————- select * from exam order by english desc,math desc;
- 語法五:select 分組函式 from exam group by 列名; 按照某列進行分組統計 分組操作,就是具有相同資料記錄分到一組中,便於統計
練習:
create table orders(
id int,
product varchar(20),
price float
);
insert into orders(id,product,price) values(1,'電視',900);
insert into orders(id,product,price) values(2,'洗衣機',100);
insert into orders(id,product,price) values(3,'洗衣粉',90);
insert into orders(id,product,price) values(4,'桔子',9);
insert into orders(id,product,price) values(5,'洗衣粉',90);
對訂單表中商品歸類後,顯示每一類商品的總價 ---- 需要按照商品名稱進行分組
select product,sum(price) from orders group by product;
在group by 語句後面 新增having 條件語句 ---- 對分組查詢結果進行過濾
查詢購買了幾類商品,並且每類總價大於100的商品
select product,sum(price) from orders group by product having sum(price) > 100;
運算子:
相等= 不等 <>
between …and… 在兩者之間取值 between 70 and 80 等價於 >=70 <=80 —– 注意前面那個數要比後面那個數要小
in(值,值,值) 在指定值中任取一個 in(70,80,90) 值可以是70、80或者90
**like ‘模糊查詢pattern’ 進行模糊查詢 ,表示式有兩個佔位符 % 任意字串 _ 任意單個字元 例如: name like ‘張%’ 所有姓張學員
name like ‘張_’ 所有姓張名字為兩個字學員**is null 判斷該列值為空
and 邏輯與 or 邏輯或 not 邏輯非
練習:
查詢英語分數在 90-100之間的同學。 -------- select * from exam where english>=90 and english <= 100; select * from exam where english between 90 and 100;
查詢數學分數為65,75,85的同學。 ---- select * from exam where math in(65,75,85);
查詢所有姓趙的學生成績。---- select * from exam where name like '趙%';
查詢英語分>80,語文分>80的同學。 ---- select * from exam where english > 80 and chinese > 80;
insert into exam values(null,'劉備',null,55,38);
查詢語文沒有成績學員 select * from exam where chinese is null;
查詢語文有成績學員 select * from exam where chinese is not null;
聚集函式 指SQL語句中內建函式 ———- 分組函式(用於統計):
- count 統計查詢結果記錄條數 select count(*)|count(列名) from 表名;
練習:
1. 統計一個班級共有多少學生?———— select count( * ) from exam;
2. 統計英語成績大於90的學生有多少個? ——- select count( * ) from exam where english > 90;
3. 統計總分大於220的人數有多少? ——–select count( * ) from exam where chinese+math+english > 220;
- sum 統計某一列資料的和 select sum(列名) from 表名;
練習:
1. 統計一個班級數學總成績? —– select sum(math) from exam;
2. 統計一個班級語文、英語、數學各科的總成績 —- select sum(chinese),sum(math),sum(english) from exam;
3. 統計一個班級語文、英語、數學的成績總和 select sum(chinese+math+english) from exam; select sum(chinese)+sum(math)+sum(english) from exam;
4. **劉備語文null ,null進行所有運算 結果都是null
select sum(chinese)+sum(math)+sum(english) from exam; 含有劉備英語和數學成績
select sum(chinese+math+english) from exam; 不含劉備英語和數學成績**
5. **使用ifnull函式處理 null情況
select sum(ifnull(chinese,0)+ifnull(math,0)+ifnull(english,0)) from exam; 含有劉備英語和數學成績**
6. 統計一個班級語文成績平均分 —— select sum(chinese)/count( * ) from exam;
- avg 統計某一列平均值 select avg(列名) from 表名;
練習:
1. 求一個班級數學平均分? —- select avg(math) from exam;
2. 求一個班級總分平均分?—- select avg(ifnull(chinese,0)+ifnull(math,0)+ifnull(english,0)) from exam;
- max 統計一列最大值 min 統計一列最小值
練習:
1. 求班級最高分和最低分(數值範圍在統計中特別有用)select max(chinese+math+english) ,min(ifnull(chinese,0)+ifnull(math,0)+ifnull(english,0)) from exam;
==補充:==
where 和 having 條件語句的區別?
1. where 是在分組前進行條件過濾,having 是在分組後進行條件過濾 2. 使用where地方都可以用 having替換,但是having可以使用分組函式,而where後不可以用分組函式
小結select語句:
**S-F-W-G-H-O 組合 select … from … where … group by… having… order by … ;
順序不能改變**解析順序 : from - where - group by - having - select - order by
多表設計:
多表設計(外來鍵約束):
create table emp (
id int primary key auto_increment,
name varchar(20),
job varchar(20),
salary double
);
insert into emp values(null,'小麗','人力資源',4500);
insert into emp values(null,'小張','Java工程師',5000);
insert into emp values(null,'老李','財務經理',8000);
insert into emp values(null,'小劉','專案經理',10000);
create table dept(
id int primary key auto_increment,
name varchar(20)
);
insert into dept values(null,'人力資源部');
insert into dept values(null,'財務部');
insert into dept values(null,'技術研發部');
讓員工表和部門表發生關係,知道員工屬於哪個部門 ,在員工表新增部門id欄位
alter table emp add dept_id int ;
update emp set dept_id = 1 where name = '小麗';
update emp set dept_id = 2 where name = '老李';
update emp set dept_id = 3 where name = '小劉';
update emp set dept_id = 3 where name = '小張';
假設公司因為財政問題,解散技術研發部 delete from dept where name ='技術研發部'; ----- 小張和小劉 失去了組織
emp表 中dept_id欄位 引用 dept表 id 欄位 ------- 新增外來鍵約束 (保證資料有效和完整性)
將emp表中dept_id 設定為外來鍵約束 alter table emp add foreign key(dept_id) references dept(id) ;
無法刪除技術研發部,因為小劉和小張資訊 依賴技術研發部 記錄 !!!!!
多表設計原則(瞭解):
- 多對多關係 : 僱員和專案關係
- 一個僱員可以參與多個專案 , 一個專案可以由多個僱員參與
- 建表原則:必須建立第三張關係表,在關係表中引用兩個實體主鍵 作為外來鍵
- 關係表中每條記錄,代表一個僱員參與了一個專案
- 一對多關係: 使用者和部落格關係
- 一個使用者可以發表多篇部落格 , 一個部落格只能由一個作者
- 建表原則:不需要建立第三方關係表,只需要在多方新增 一方主鍵作為 外來鍵
- 一對一關係 : 這種關係很少見到 負責人和工作室
- 一個負責人 管理一個工作室 , 一個工作室 只有一個負責人
- 建表規則:在任一方新增對方主鍵 作為外來鍵
笛卡爾積的學習:
多表查詢——笛卡爾積
將A表中每條記錄 與 B表中每條記錄進行 匹配 獲得笛卡爾積
select * from emp;
select * from dept;
select * from emp,dept; 顯示結果就是笛卡爾積
笛卡爾積結果 就是 兩個表記錄乘積 例如A 表3條 B表4條 ---- 笛卡爾積 12條
笛卡爾積結果是無效的,必須從笛卡爾積中選取有效的資料結果 !!!
多表查詢 連線查詢 內連線查詢
從A表中選擇一條記錄,去B表中找對應記錄 ----- 內連線
必須A表和B表存在對應記錄才會顯示
create table A(A_ID int primary key auto_increment,A_NAME varchar(20) not null);
insert into A values(1,'Apple');
insert into A values(2,'Orange');
insert into A values(3,'Peach');
create table B(A_ID int primary key auto_increment,B_PRICE double);
insert into B values(1,2.30);
insert into B values(2,3.50);
insert into B values(4,null);
使用內連線 select * from a,b where a.a_id = b.a_id; 從笛卡爾積中篩選出有效的資料
* 內連線查詢結果條數 一定小於 兩個表記錄較多哪個表 ----- 例如 A表3條 B表5條 ---- 內連線結果條數 <= 5
select * from emp,dept where emp.dept_id = dept.id ; 將emp 表和dept 表進行內連線
在內連線查詢時 新增條件,
查詢人力資源部有哪些 員工 ??
select * from emp,dept where emp.dept_id = dept.id and dept.name ='人力資源部';
查詢工資大於7000員工來自哪個部門?
select * from emp,dept where emp.dept_id = dept.id and emp.salary > 7000;
select * from emp,dept where emp.dept_id = dept.id ; 寫法一
select * from emp inner join dept on emp.dept_id = dept.id ; 寫法二
擴充套件內容
MySQL 資料庫的備份和恢復
- 備份命令 mysql/bin/mysqldump 將資料庫SQL語句匯出
- 語法:mysqldump -u 使用者名稱 -p 資料庫名 > 磁碟SQL檔案路徑
例: 備份day12資料庫 — c:\day10.sql
cmd > mysqldump -u root -p day10 > c:\day10.sql 回車輸入密碼**
- 恢復命令 mysql/bin/mysql 將sql檔案匯入到資料庫
- 語法: mysql -u 使用者名稱 -p 資料庫名 < 磁碟SQL檔案路徑
注意:匯入SQL 必須手動建立資料庫,SQL不會建立資料庫
例: 將c:\day10.sql 匯入 day10資料庫
cmd > mysql -u root -p day10 < c:\day10.sql 回車密碼
==補充知識==: 恢復SQL也可以在資料庫內部執行 source c:\day10.sql