1. 程式人生 > >《資料庫系統概念》第三章:SQL

《資料庫系統概念》第三章:SQL

SQL資料定義

  • 基本型別

char(n) 固定長度的字串,使用者指定長度n
varchar(n) 可變長度的字串,使用者指定最大長度n
int 整數型別(和機器相關的整數的有限子集)
smallint 小整數型別(和機器相關的整數型別的子集)
numeric(p,d) 定點數,精度由使用者指定。這個數有p位數字(加上一個符號位),其中d位數字在小數點的右邊。
real,doubleprecision 浮點數與雙精度浮點數,精度與機器相關。
float(n) 精度至少為n位的浮點數
  • 基本模式定義

--建立一個instructor關係
create table instructor
    (ID varchar(5),
    name varchar(20) not null
    debt_name varchar(20),
    salary numeric(8,2),
    primary key(ID),
    foreign key(dept_name)references department);

--create table命令的通用形式:
create table r
    (A1 D1,
    A2 D2,
    ……,
    An,Dn,
    <完整性約束>
    ……,
    <完整性約束>); 

SQL查詢的基本操作

--一個典型的SQL查詢具有如下形式
select A1,A2,……,An
from r1,r2,……rn
where P;
select distinct dept_name--強行刪除重複
select all dept_name--指明不去除重複

--返回一個與instructor一樣的關係,只是屬性salary的值是原來的1.1倍
select ID,name,dept_name,salary*1.1
from instructor
  • 多關係查詢

笛卡爾積(Cartesian product):從兩個輸入關係中輸出所有的元組對(無論它們在共同屬性上的取值是否相同)。

自然連線(natural join):作用於兩個關係,併產生一個關係作為結果。且自然連線只考慮那些在兩個關係中都出現的屬性上取值相同的元組對。

select A1,A2,……,An
from r1 natural join r2 join r3
where P;
--r1與r2先做自然連線,然後與r3做笛卡爾積。

select A1,A2,……,An
from r1 join r2 using(A1,A2)
where P;
--r1與r2做r1.A1=r2.A1並且r1.A2=r2.A2的合併

基本運算

  • 更名運算:

--使用as語句進行更名運算
--可放入selct子句和from子句。
old-name as new-name

--需要比較同一個關係中的元組的情況,如:
--查詢:“找出所有工資至少比Biology系某一個教師的工資要高的教師的姓名。”
select distinct T.name
from instructor as T,instructor as S
where T.salary > S.salary and S.dept_name = 'Biology';

在上述查詢中,T和S這樣被用來重新命名關係的識別符號在SQL標準中被稱作相關名稱(correlation name),但通常也被稱作表別名(table alias),或者相關變數(correlation variable),或者遠元組變數(tuple variable)

  • 字串運算

SQL中使用各一對單引號來標識字串。如果單引號是字串的組成部分,那就用兩個單引號字元來表示。

在字串上可以使用like操作符來實現模式匹配。我們使用一些特殊字元來描述模式:

  1. 百分號(%):匹配任意子串。
  2. 下劃線(_):匹配任意一個字元。
  3. 反斜線(\):作為轉義字元。
--查詢:“找出所在建築名稱中包含子串'Watson'的所有系名”
select dept_name
from department
where building like '%Watson%';
  • selct字句中屬性說明

形如select *表示from子句結果關係的所有屬性都被選中。

select instructor.*
from instructor,teaches
where instructor.ID = teaches.ID;
  • 排列元組的顯示次序

order by可以讓查詢結果中元組按預設的升序順序顯示。

desc表示降序,asc表示升序。

--按salary的降序排列。如果salary相同,按名字的升序排列。
select *
from instructor
order by salary desc,name asc;
  • where子句謂詞

所有的謂詞前面都可以加上not表示範圍取反。

--between比較運算子:
select name
from instructor
where salary between 90000 and 100000;

--用記號(v1,v2,……vn)表示一個n維元組
select name,course_id
from instructor teaches
where (instructor.ID,dept_name)=(teaches.ID,'Biology');

集合運算

並運算union,交運算intersect,差運算except,相當於數學集合論中的 \cup ,\cap , - 。

這三個運算都會自動去除重複元素,如果要保留可在後面加上all,比如用union all代替union

  • 並運算結果的重複元組數是c1和c2中出現的重複元次數之和。
  • 交運算結果中的重複元組數等於在c1和c2中出現的重複元次數裡最少的那個。
  • 差運算結果中的重複元組數等於在c1中出現的重複元組數減去在c2中出現的重複元組數(前提是此差為正)。
(select course_id
from section
where semester = 'Fall' and year = 2009)
union
(select course_id
from section
where semester = 'Spring' and year = 2010)

空值

  • 如果算術表示式的任一輸入為空,則該算術表示式結果為空。
  • 如果比較運算子涉及到空值,那麼結果為unknown。
and的真值表
true and unknown unknown
false and unknown unknown
unknown  and unknown unknown
or的真值表
true or unknown true
false or unknown unknown
unknown  or unknown unknown
not的真值表
not unknown unknown
select name
from instructor
where salary is null--找出所有值為空的
where salary is not null--找出所有值為非空的

如果元組在所有屬性上的取值相等,那麼它們就被當作相同元組,即使某些值為空。

聚焦函式

  • 平均值:avg
  • 最小值:min
  • 最大值:max
  • 總和:sum
  • 計數:count

sum和avg的輸入必須是數字集,但其他運算子還可作用在非數字資料型別的集合上,如字串。

--計算平均值需要保留重複元素,否則結果可能會出錯。
select avg (salary) as avg_salary
from instructor

--如果需要刪除在聚焦函式前重複元素,利用distinct。
select count(distinct ID)
from teaches

--利用count計算一個關係的元組的個數
select count(*)
from course

分組聚焦group by:

  • group by子句中的所有屬性上取值相同的元組將被分在一個元組中,並在結果中出現。
  • group by子句中的屬性要麼出現在其他聚集函式中,要麼在select子句中。否則查詢是錯誤的。

having:

  • having子句是針對group by分組後的元組限定條件。
  • having子句中的屬性要麼出現在其他聚集函式中,要麼在group by子句中。否則查詢是錯誤的。
select dept_name,avg(salary) as avg_salary
from instructor
group by dept_name
having avg (salary) > 42000;

如果輸入是空值,count運算值為0,其他聚集函式返回一個空值。

如果輸入包含空值,除count以外的聚集函式會自動忽略空值。

巢狀子查詢

select id
from A
where id in(select id  from B);

select id
from A
where id exists(select id  from B);、

select id
from A
where score > all(select score from B);、

select id
from A
where not unique(select name from B)
--查詢所有系中工資總額最大的系
select max(tot_salary)
from(select dept_name,sum(salary))
     from instructor
     group by dept_name) as dept_total(dept_name,tot_salary);
--標量子查詢返回單個值,能夠出現在select、where和having子句中
--查詢所有的系和它們擁有的教師數
select dept_name,
      (select count(*)
       from instructor
       where department.dept_name = instructor.dept_name)
       as num_instructors
from departments;

資料庫的修改

insert into instructor values(10211,'Smith','Biology',6000);--插入元組
insert into A select id from B; --在查詢的基礎上插入元組

delete from r where P--刪除元組
drop table r;--刪除關係

alter table r add A D;--增加屬性
alter table r drop A--去掉屬性

update r
set salary = salary*1.05--更新元組
where P

update r
set salary = case --利用case結構提供多種更新
               when pred1 then result1
               when pred2 then result2
               ……
               when predn then resultn
               else result.
             end;

[參考資料]:《資料庫系統概念》 機械工業出版社