1. 程式人生 > >SQL入門,就這麼簡單

SQL入門,就這麼簡單

   隨著時代的發展,人類活動產生的資訊越來越多,大家常說,現在這個時代是大資料時代。在這樣一個前提下,資料的儲存成為我們必須要認真對待和研究的問題了。SQL(Structured Query Language)結構化查詢語言,是當今三大主流關係型資料庫(MsSQL,MySQL,Oracle)的通用操作語言,今天就給大家分享一下我對資料庫和 SQL 的一些認識,希望對大家有用。

  一  資料庫簡介

 

    1,什麼是資料庫

    在理解什麼是資料庫之前,我們首先要明白另一個問題,即什麼是資料?

    一個人的身高、體重、年齡;一輛車的品牌、顏色,尺寸;一個運動員在完成比賽期間所用的時間,速度,心率;即使你計算機上的圖片、視訊等都是資料。我的結論就是:用於描述事物或事件的屬性,並且能被人們識別的符號就是資料。

    明白了什麼是資料,不難推測出:資料庫就是資料儲存的倉庫,各種資料的集合。當然資料庫中的資料都是有序的,有組織的,這是為了能讓管理資料更方便。

    

    2,什麼是資料庫管理系統

    你可能常常聽到人們常說:MsSQL 資料庫、MySQL 資料庫、Oracle 資料庫等等,其實他們多數指的是不同的資料庫管理系統。SQL server 是微軟旗下的資料庫管理系統,MySQL 和 Oracle 目前都屬於甲骨文公司。

    資料庫管理系統本質上是一套軟體,專門用於幫助使用者管理資料庫中的資料。

    

    3,什麼是關係型資料庫

    根據資料庫組織和儲存資料的方式,資料庫通常分為四類:層次式資料庫、網路式資料庫、關係型資料庫、非關係型資料庫。

    前兩種基本已經成為了歷史,現在主流的是後兩種,但佔市場絕對優勢的仍然是關係型資料庫(Relational Database Management System:RDBMS)。顧名思義,關係型資料庫是依照資料與資料之間的關係來組織儲存資料的。

    為了方便後面的書寫,這裡進行一個申明:從此之後,文中提到的所有資料庫均指關係型資料庫。

    

    4,資料庫和 SQL 有什麼聯絡

    SQL,指結構化查詢語言,全稱是 Structured Query Language。

    SQL 是用於訪問和處理資料庫的標準的計算機語言。

    SQL 是一種 ANSI(American National Standards Institute 美國國家標準化組織)標準的計算機語言。

    SQL 是一種命令式語言。

    當今三大資料庫管理系統均支援標準 SQL。

  

  二  如何儲存

    現在,我們已經知道什麼是資料庫、資料庫管理系統和 SQL 了。那麼,既然資料庫是用來儲存資料的,那麼資料庫具體是通過什麼方式來進行儲存的呢?它又是怎樣保證資料的有效性、合法性呢?既然說現今社會主流的仍然是關係型資料庫(RDBMS),那麼資料庫又是怎麼在資料與資料之間確定關係的呢?

    

    1,資料的儲存方式

    開門見山的說:資料庫是通過“表”來儲存資料,根據不同的資料庫管理系統,以不同的檔案格式最終被儲存到物理磁碟上(多是硬碟)。

    這裡的表類似 Excel 表格,表中的資料由不同的行和列組成,每一列在資料庫中我們稱為一個欄位,每一行資料稱為一條記錄或元組,它算是資料在資料庫中的基本單元。

    如果用一張表來記錄一類事物,那麼每一條記錄可以看成這類事物單獨的個體,而不同的列則是用來記錄事物的每個具體的特性。例如一個Person 表,用來記錄人員資訊,每個人員都可以擁有自己的姓名,年齡,性別,身高等資訊,那麼這個表應該具有姓名,年齡,性別等這些列。

name age sex height birthday
張三 20 180 2000-01-01
李四 18 170 2002-01-01
王五 25 165 1995-01-01

    在這個表中,每一行就是一條記錄,代表一個具體的人,每一列都是用來描述人的不同特徵的,從表中可以看出,每個人都擁有不同的特性。

    

    2,確保資料的有效性

    上面的表格有一個問題:不能確保資料的有效性、合法性。為什麼這麼說呢?

    試想一下,這個世界上人那麼多,總會有其他人也叫張三,並且年齡正好也是20,正好也是個身高180的大漢,那麼在表中豈不是有兩條一模一樣的記錄?那我們怎麼來區分到底誰是誰呢?還有,在不加任何限制的情況下,我可以隨意錄入人員的年齡,比如我錯把王五的年齡記錄成了250,這世上還沒有能活250歲的人吧,顯然這樣的資料是不合常理的。

    那麼資料庫是怎麼解決這個問題的呢?答案是:約束。約束作用域每一列,約束用於規定表中的資料儲存規則。如果我們在錄入資料時,不符合約束的規定,那麼你將不能把該記錄錄入資料庫中。

    

    3,約束

    資料庫中主要的約束有以下幾種:

      NOT NULL - 指示某列不能儲存 NULL 值,即空,什麼都沒有。

      UNIQUE - 保證每行的某一列必須具有唯一的值,不能重複。

      PRIMARY KEY - NOT NULL 和 UNIQUE 的結合。確保某列(或兩個列多個列的結合,即聯合主鍵)有唯一標識,有助於更容易更快速地找到表中的一個特定的記錄。

      FOREIGN KEY - 保證表中某一列的資料來自另一個表中的某一列,能使用外來鍵約束的列,在另一個表中必須是主鍵。資料庫正是通過外來鍵來建立表與表之間的聯絡。

      CHECK - 保證列中的值符合指定的條件,確保資料的合理性。

      DEFAULT - 規定沒有給列賦值時的預設值。

    本章主要講解資料庫如何儲存資料和如何確保資料的有效性,下一章將詳細介紹如何建立表,如何為表的欄位新增約束,以及如何向表中插入和刪除資料等。

  

  三  如何操作

 

    1,基礎語法

    前面提到,SQL 是命令是語言,所以它的語法其實非常簡單,每一條命令就是一條語句,每條語句以“;”結束。並且 SQL 語句對大小寫不敏感,不過為了方便閱讀和維護程式碼,請儘量統一命令的大小寫。

    SQL 中的命令總共分為四大類:

      A:DDL(Data Definition Language)資料定義語言

      主要命令包括:create(建立)、alter(修改)、drop(刪除)

      B:DQL(Data Query Language)資料查詢語言

      主要命令包括:select

      C:DML(Data Manipulation Language)資料操縱語言

      主要命令包括:insert(插入)、update(修改),delete(刪除)

      D:DCL(data Control Language)資料控制語言

      主要命令包括:grant(授權)、revoke(回收)、commit(提交)、rollback(回滾)等

      資料控制語言主要是針對資料庫安全性方面的操作,可以簡單理解為許可權管理,這部分命令 DBA 經常使用,一般資料開發人員用的較少。

    

    2,使用方式

    DDL:

 1 create database "my_db";--建立一個庫
 2 use "my_db";--選擇剛剛穿件的庫
 3 create table "my_tb"
 4 (
 5     --欄位名1 資料型別 約束,
 6     --欄位名2 資料型別 約束,
 7     --......
 8 );--在“my_db”中建立表“my_tb”
 9 
10 alter table "my_tb"
11 add 欄位名 資料型別;--修改表,並向其新增一列
12 alter table "my_tb"
13 alter 欄位名 資料型別;--修改表中某一列的資料型別
14 
15 drop table "my_tb";--刪除表
16 drop database "my_db";--刪除庫
17 truncate table 表名;--清空表中的資料

    DQL:資料查詢語言是 SQL 的重中之重,將在下一頁單獨講解,這裡僅給出 select 命令的基礎用法。

1 /*以上面的 Person 表為例*/
2 select name ,age from Person;--查詢Person表中所有人員的姓名及年齡
3 select * from Person;--查詢Person表中的所有資料,*是萬用字元

    DML:

1 /*以 Person 表為例*/
2 insert into Person (name,age,sex,height)
3 values('小明',12,'男',150);
4 --向表中插入一條資料
5 update Person set sex='女' where name='小明';
6 --修改小明的性別為女
7 delete from Person where name='小明';
8 --刪除姓名為小明的記錄

    

    3,建立約束

    建立約束有兩種方式,其一:在建立表時同時建立約束,其二:同過 alter 命令向已建立的表新增約束。

 1 /*建立表時即新增約束*/
 2 create table tablename
 3 (
 4     id int identity(1,1) primary key,
 5     name varchar(50) not null,
 6     idcard char(18) unique,
 7     city varchar(50) foreign key(city) references City(id),--city列的值通過外來鍵繫結City表的id列
 8     age int check (age>0 and age<150),
 9     email varchar(50) not null
10 )

    

1 /*通過 alter 命令新增約束*/
2 alter table tablename
3 add
4     constraint ck_email check (email like '%@%');
5 --通過 constraint 可以指定約束的名字,建立表時新增約束也可以使用,但它不是必須的

    

    4,資料型別

    不同資料庫支援的資料型別有較大差異,即使相同的資料庫不同的版本也存在一定差異,所以在使用時請儘量以管飯個文件為依據,這裡僅列出部分常用的通用的資料型別:

      bigint(整型)、varchar(n)(可變長度字串)、boolean(布林值)、float(浮點型)、date(日期)、time(時間),timestamp(日期+時間型)、xml(XML型)。

  

  四  如何查詢

    相較於其他命令,資料開發中用的最多的就是 select 了,沒有之一。

    

    1,普通查詢

    通過幾條簡單的查詢語句來說明:

1 insert into Person values('張五',30,男,175,'1990-01-01');
2 insert into Person (name,sex,height,birthday)
3     values('張六',男,175,'1990-01-01');
4 --先插入兩條新資料
5 select * from Person as P
6 where P.birthday between '1990-01-01' and '2010-01-01'
7     and P.name like '%張%'
8     and P.age is not null
9 --查詢生日在1990-2010間姓名包含張並且年齡不為空的所有人員資訊

    通過上面的例子,我要說明查詢語句的一切基本用法。

    首先是緊跟在 select 命令之後的資訊,它表明需要被查詢的欄位,* 星號表示萬用字元,意為查詢所有表中的欄位。

    其次是 from 關鍵字,它表示從哪個表中查詢資料,緊跟在其後的是表名。

    as 關鍵字的作用是給表起一個別名,主要是為了簡化程式碼,被查詢的欄位也可以使用 as 起一個更通俗易懂的別名。

    where 關鍵字用於指定過濾條件,通過 where 我們可以值查詢我們需要的資料。

    and 關鍵字用來連線不同的過濾條件。

    between...and... 是一個組合範圍關鍵字,如上例所示,它可以用來指定時間範圍,還可以用來指定數字的取值範圍等。

    like 用來指定模糊查詢,% 表示零個或多個任意字元,_ 表示任意單個字元,[] 表示指定字元中的一個,[^] 表示不在指定字元中的一個。

    一個特別的,判斷某列的值是否為空,應該使用 is 或 not is 關鍵字,而不是使用 = 等號或 != 不等號,而其他情況均可使用 = 或 != 。

    

    2,分組和排序

    SQL 中的分組使用 group by 實現,group by 通常和聚合函式一起使用,否則單獨使用 group by 分組沒有現實意義。

    SQL 中的聚合函式從列的計算中獲取值,一般返回一個單一的值。SQL 中除了聚合函式,還有另一類標量函式,它們基於輸入的值返回一個單一的值。

聚合函式 含義 標量函式 含義
AVG() 返回平均值 UCASE() 轉換為大寫
COUNT() 返回行數 LCASE() 轉換為小寫
FIRST() 返回第一個記錄 SUBSTRING() 擷取字串
LAST() 返回最後一個記錄 LEN() 返回欄位長度
MAX() 返回最大值 ROUND() 四捨五入
MIN() 返回最小值 NOW() 返回系統時間
SUM() 返回總和 FORMAT() 格式化字串

    不同資料庫對函式的實現有一定差異,但常用的標量函式使用方式都相同:如上黑體字列出的聚合函式。 

    單獨使用聚合函式: 

1 select avg(age) as "平均年齡" from Person;--計算所有人的平均年齡
2 select max(age) as "最大年齡",min(age) as "最小年齡" from Person;--計算最大年齡和最小年齡
3 select count(name) as "人數" from Person;--統計表中的人數
4 --count()通過指定列來統計個數,忽略 NULL 值 

    聚合函式 + group by:

1 select sex,sum(name) as "人數" from Person
2 group by sex
3 having sum(name)>2;--查詢性別人數之和大於的的性別和人數
4 --group by 後面為聚合(或者叫分組)的欄位,查詢中用來分組的欄位都必須出現在 group by 之後,having 用來對聚合後的資料再過濾

    如果有多個欄位需要被用來分組,那麼他們的分組順序是從左至右的,並且最右邊的欄位將被當做聚合函式計算的最小分組。

    使用 order by 排序:

1 select * from Person order by age desc;
2 --按年齡從大到小排序查詢所資訊,desc 表示倒序。預設是asc 表示升序,可以省略。group by 可以和 order by 一起使用,但 order by 永遠在查詢語句的最後

    

    3,連線查詢

    連線查詢分為三類:內連線,外連線,全連線。

    我們知道,現實世界中的事物都存在各種聯絡,通過事物之間的種種聯絡,你可以收集到更多在一類事物上不存在的資訊。正如著名的七人理論:你最多隻需要通過7個人就能和世上任何一個人認識。這也是一種典型的關係模型。

    我們的關係型資料庫正是通過各種各樣的外來鍵把不同表關聯起來的。只要根據他們的關係,我們就可以在不同的表中查詢我們想要的任何資料了。

    A:內連線

      內連線的用法如下:

1 select * from tableA,tableB;--方式一
2 select * from tableA A
3 join tableB B
4 on 1=1;--方式二(join 是inner join 的縮寫,on 用來指定組合產生新資料連線的條件) 

      內連線會使用兩個表產生一個笛卡爾積,簡單的說就是:資料庫把兩個表中的資料認為是多對多的關係,用表 A 的每一條資料去和表 B 中的每一條資料組合成新的資料,最終的結果是,總記錄的條數是兩個表記錄條數的乘積,欄位數是兩個表字段數的總和。

      很顯然,通常情況下,笛卡爾積並不是我們需要的資料。方式一可以通過 where 來設定過濾條件,而方式二則是通過 on 指定連線條件。比如如下sta和sal兩個表:

sta表 id name sal_grade sal表 sal_grade sal
1 張三 3 1 8000
2 李四 2 2 6000
3 王五 1 3 4000
1 select * from sta,sal;--會返回 9 條記錄,每條記錄有 5 個欄位
2 select * from sta,sal
3 where sta.sal_grade = sal.sal_grade;--只會返回9條記錄中sta.sal_grade = sal.sal_grade的資料,共3條
4 select * from sta join sal
5 on sta.sal_grade = sal.sal_grade;--也只返回 3 條記錄,但他們的原理是有差別的,where 是在產生笛卡爾積後過濾,而 join 方式是在確定連線關係時就開始過濾,最終不會產生笛卡爾積,除非 on 指定的條件為真
6 select sta.id,sta.name,sal.sal from sta join sal
7 on sta.sal_grande = sal.sal_grande;--只查詢需要的欄位,而不是兩個表中所有的欄位

    B:外連線

      外連線又分為左外連線和右外連線,左外連線會返回所有左表中的記錄,無論是否滿足連線條件,而右外連線剛好相反,會返回右表中所有的記錄,無論是否滿足連線條件。這裡的左和右是指 join 關鍵字的左和右。

      外連線最終的輸出結果表現為:總記錄數不能確定,因為可能存在一對多的關係。而欄位數仍為兩個表字段數之和。那些滿足連線條件的記錄,每個欄位都會有確定的值,而那些不滿足連線條件的記錄,則只有左表或右表的欄位有值,另一個表的欄位為 NULL(具體取決於是左外連線還是右外連線)。

1 insert into sta values(4,'張五',5);
2 select sta.id,sta.name,sal.sal from sta 
3 left join sal
4 on sta.sal_grande =  sal.sal_grande;--返回 4 條記錄,但張五的工資欄位為 NULL,因為 sal 表中並沒有 sal_grande 為 5 的記錄可以匹配

    C:全連線和交叉連線

    全連線使用 full join,結果集的數量不確定,欄位數是兩個表字段數的總和,但是,依然會返回左右表中不滿足連線條件的記錄,只是另一邊表的欄位則均為 NULL。

    交叉連線使用 cross join,產生的結果仍是笛卡爾積,等價於內連線。

insert into sal values(4,2000);
select * from sta
full join sal
on sta.sal_grande = sal.sal_grande;--返回 5 條記錄,但name為張五的記錄中sal表的欄位值均為 NULL,工資等級為 4 的記錄中 sta 表的欄位均值為 NULL

    

    4,聯合查詢

    連線查詢是把表的欄位橫向組合到一起,從而產生新的資料,而聯合查詢是把兩個表的記錄縱向組合到一起,聯合查詢的要求是:兩個表的欄位數量和對應欄位的資料型別必須相同。SQL 通過 union 聯合兩張表。

1 select col1,col2,col3 from tableA
2 union
3 select col1,col2,col3 from tableB

    請注意,union 聯合表後,預設只選取不同的記錄,如果你希望在聯合後的記錄中允許相同的資料存在,請使用 union all。

&n