學號、姓名、年齡、住址、成績、學科、學科(語文、數學、英語)
咱們應該怎麼去設計儲存這些數據呢?python
這裏面學科包含了三個學科,因此學科拆分爲:語文學科、數學學科、英語學科,一樣的成績也要拆分爲語文成績、數學成績、英語成績。這樣既知足了第一範式,各列能夠設計爲:mysql
學號、姓名、年齡、住址、語文學科、數學學科、英語學科、語文成績、數學成績、英語成績
也就是說在1NF的基礎上,非Key屬性必須徹底依賴於主鍵,第二範式(2NF)要求數據庫表中的每一個實例或記錄必須能夠被惟一地區分。選取一個能區分每一個實體的屬性或屬性組,做爲實體的惟一標識。即肯定主鍵,咱們能夠選取學號爲主鍵sql
不難發如今這麼多列中,年齡、住址和成績、學科沒有直接關係,也就是說我考多少分,和年齡及住址都無關,他們都是學生的信息,但都是不相關的信息,因此根據第三範式,咱們須要將這些數據根據其相關性拆分爲多個表。數據庫
若是咱們要想找到張三的語文成績,那麼咱們就必須去成績表中查找,由於成績表中保存的全部人的全部學科成績。可是在成績表中查找的時候,須要從省標中查到張三的學號(stu_id)和從學科表中查到語文學科(sub_id)的編號,這個時候這三張表就發生了關係,這也就是關係型數據庫的精髓,而根據這種表與表之間的關係也會衍生出不少的查詢的高級操做函數
外鍵約束:用於限制主表與從表數據完整性。ui
alter table scores add constraint 'stu_score_fk' foreign key(stu_id) references students(stu_id);
語法:spa
foreign key (外鍵字段) references 主表名 (關聯字段)
例如:
create table scores( id int primary key auto_increment, stu_id int, sub_id int, score decimal(5,2), foreign key(stuid) references students(id), foreign key(subid) references subjects(id) );
[主表記錄刪除時的動做] [主表記錄更新時的動做],此時須要檢測一個從表的外鍵須要約束爲主表的已存在的值。外鍵在沒有關聯的狀況下,能夠設置爲null.前提是該外鍵列,沒有not null。
設計
alter table scores add constraint stu_sco foreign key(stu_id) references students(stu_id) on delete cascade;
除了on delete還有on update都要注意級聯操做版本控制
級聯操做的類型包括:rest
在講解第一個問題關係的時候,咱們提到了,若是要查找張三的語文成績,須要用到三個表,當咱們查詢結果來源於多張表的時候就須要使用鏈接查詢
連接查詢關鍵:找到表間的關係,當前的關係是
select students.stu_name,subjects.sub_name,scores.score from scores inner join students on scores.stu_id=students.stu_id inner join subjects on scores.sub_id=subjects.sub_id where students.stu_name='張三' and subjects.sub_name='語文';
+----------+----------+-------+
| stu_name | sub_name | score |
+----------+----------+-------+
| 張三 | 語文 | 80 |
+----------+----------+-------+
視圖就像咱們python裏面的函數同樣,對SQL語言代碼塊的封裝
create view stuscore as select students.stu_name,subjects.sub_name,scores.score from scores inner join students on scores.stu_id=students.stu_id inner join subjects on scores.sub_id=subjects.sub_id;
這句話的意思就是用stuscore就至關於後面紅色很長的一段SQL語句:
mysql> select *from stuscore; +----------+----------+-------+ | stu_name | sub_name | score | +----------+----------+-------+ | 張三 | 語文 | 80 | | 張三 | 數學 | 85 | | 張三 | 英語 | 88 | | 李四 | 語文 | 83 | | 李四 | 數學 | 84 | | 李四 | 英語 | 87 | | 王五 | 語文 | 81 | | 王五 | 數學 | 85 | | 王五 | 英語 | 85 | | 趙六 | 語文 | 88 | | 趙六 | 數學 | 88 | | 趙六 | 英語 | 87 | | 侯七 | 語文 | 84 | | 侯七 | 數學 | 83 | | 侯七 | 英語 | 82 | +----------+----------+-------+
有時在信息查詢時須要進行對自身鏈接(自鏈接)自鏈接是單邊操做,因此咱們須要爲表定義別名。舉例說明,下面是一個新的學生成績表,在下表中咱們要找到比張三成績高的。
+--------+----------+-----------+ | stu_id | stu_name | stu_score | +--------+----------+-----------+ | 1 | 張三 | 90 | | 2 | 李四 | 85 | | 3 | 王五 | 80 | | 4 | 趙六 | 95 | | 5 | 侯七 | 100 | +--------+----------+-----------+
通常狀況咱們看到這張表咱們第一時間用語句進行操做:
select * from Score where stu_score>90;
可想而知,這是有多麼簡單,假設你並不知道數據庫中張三的成績是90或者數據量至關龐大呢?做爲一個數據庫管理員,咱們就要用別的方式迅速找出所須要的數據。
方式一:分步查找:最簡單的一種方式,也是最容易想到的操做「
select stu_score from Score where stu_name='張三';//得出張三的成績 select *from Score where stu_score>90;
與採用自鏈接的方式相比,這種方法須要對中間結果進行人工干預,顯然不利於程序中的自動處理操做。
方式二:自鏈接方式:
select * from Score as a,Score as b where a.stu_name='張三' and a.stu_score<b.stu_score;
+--------+----------+-----------+--------+----------+-----------+ | stu_id | stu_name | stu_score | stu_id | stu_name | stu_score | +--------+----------+-----------+--------+----------+-----------+ | 1 | 張三 | 90 | 4 | 趙六 | 95 | | 1 | 張三 | 90 | 5 | 侯七 | 100 | +--------+----------+-----------+--------+----------+-----------+
若是不想把張三的信息打印出來咱們能夠調整SQL語句爲:
select b.* from Stu_score as a,Stu_score as b where a.stu_name='張三' and a.stu_score<b.stu_score;
+--------+----------+-----------+ | stu_id | stu_name | stu_score | +--------+----------+-----------+ | 4 | 趙六 | 95 | | 5 | 侯七 | 100 | +--------+----------+-----------+
注意:別名 a,b雖然名稱不一樣,可是同一個表,定義別名的目的是更方便在自身進行刪選。
執行select經過(中間表)所獲得的b.*,,就是最終結果。
子查詢也是經常使用的一種方式,就是在select裏嵌套select。仍是上面的例子,咱們用子查詢實現以下:
select * from Stu_score where stu_score>(select stu_score from Stu_score where stu_name='張三');
+--------+----------+-----------+ | stu_id | stu_name | stu_score | +--------+----------+-----------+ | 4 | 趙六 | 95 | | 5 | 侯七 | 100 | +--------+----------+-----------+
一、查看字符的ascii碼值ascii(str),str是空串時返回0
mysql> select ascii('a'); +------------+ | ascii('a') | +------------+ | 97 | +------------+
二、查看ascii碼值對應的字符char(數字)
mysql> select char(97); +----------+ | char(97) | +----------+ | a | +----------+
三、拼接字符串concat(str1,str2...)
select concat(12,34,'ab'); +--------------------+ | concat(12,34,'ab') | +--------------------+ | 1234ab | +--------------------+
四、包含字符個數length(str)
mysql> select length('abc'); +---------------+ | length('abc') | +---------------+ | 3 | +---------------+
五、截取字符串
mysql> select substring('abc123',2,3); +-------------------------+ | substring('abc123',2,3) | +-------------------------+ | bc1 | +-------------------------+
六、去除空格
mysql> select trim(' bar '); +------------------+ | trim(' bar ') | +------------------+ | bar | +------------------+
mysql> select trim(leading 'x' FROM 'xxxbarxxx'); +------------------------------------+ | trim(leading 'x' FROM 'xxxbarxxx') | +------------------------------------+ | barxxx | +------------------------------------+
mysql> select trim(trailing 'x' FROM 'xxxbarxxx'); +-------------------------------------+ | trim(trailing 'x' FROM 'xxxbarxxx') | +-------------------------------------+ | xxxbar | +-------------------------------------+
mysql> select trim(both 'x' FROM 'xxxbarxxx'); +---------------------------------+ | trim(both 'x' FROM 'xxxbarxxx') | +---------------------------------+ | bar | +---------------------------------+
七、替換字符串replace(str,from_str,to_str)
mysql> select replace('abc123','123','def'); +-------------------------------+ | replace('abc123','123','def') | +-------------------------------+ | abcdef | +-------------------------------+
八、大小寫轉換,函數以下
mysql> select lower('aBcD'); +---------------+ | lower('aBcD') | +---------------+ | abcd | +---------------+
一、求絕對值abs(n)
mysql> select abs(-32); +----------+ | abs(-32) | +----------+ | 32 | +----------+
二、求m除以n的餘數mod(m,n),同運算符%
mysql> select mod(10,3); +-----------+ | mod(10,3) | +-----------+ | 1 | +-----------+ mysql> select 10%3; +------+ | 10%3 | +------+ | 1 | +------+
三、floor(n),表示不大於n的最大整數
mysql> select floor(2.3); +------------+ | floor(2.3) | +------------+ | 2 | +------------+
四、ceiling(n),表示不小於n的最大整數
mysql> select ceiling(2.3); +--------------+ | ceiling(2.3) | +--------------+ | 3 | +--------------+
五、求四捨五入值round(n,d),n表示原數,d表示小數位置,默認爲0
mysql> select round(1.6); +------------+ | round(1.6) | +------------+ | 2 | +------------+
六、求x的y次冪pow(x,y)
mysql> select pow(2,3); +----------+ | pow(2,3) | +----------+ | 8 | +----------+
七、隨機數rand(),值爲0-1.0的浮點數
mysql> select rand(); +--------------------+ | rand() | +--------------------+ | 0.0713081630610937 | +--------------------+
mysql> select year('2019-7-11'); +-------------------+ | year('2019-7-11') | +-------------------+ | 2019 | +-------------------+
mysql> select '2019-7-11'+interval 1 day; +----------------------------+ | '2019-7-11'+interval 1 day | +----------------------------+ | 2019-07-12 | +----------------------------+
日期格式化date_format(date,format),format參數可用的值以下
獲取年%Y,返回4位的整數
* 獲取年%y,返回2位的整數
* 獲取月%m,值爲1-12的整數
獲取日%d,返回整數
* 獲取時%H,值爲0-23的整數
* 獲取時%h,值爲1-12的整數
* 獲取分%i,值爲0-59的整數
* 獲取秒%s,值爲0-59的整數
show create table Stu_score;
alter table Stu_score engine=innodb;
開啓begin;
提交commit;
回滾rollback;
在begin;後面寫咱們要操做的SQL語句組合也就是咱們所謂的要執行的事物,可是這個時候寫好的SQL語句就算咱們回車以後,也不會執行,知道commit;執行以後纔會被執行到數據庫中,rollback回滾是咱們begin;以後發現咱們寫錯了,或者不想執行了,均可以在commit;以前回滾到上一次commit;的狀態,很像版本控制器SVN和GIT同樣