例子表:學生信息表Student(Sno,Sname,Ssex,Sage,Sdept),主鍵Snohtml
課程信息表Course(Cno,Cname,Cpno,Ccredit),主鍵Cno程序員
選課表SC(Sno,Cno,Grade),主鍵(Sno,Cno) 算法
★範式基礎:數據庫
1.第一範式:屬性列不可再分,如屬性列「住址」值爲"XX市XX路XX號",該列能夠再分爲「市」、"街道";安全
2.第二範式:非主屬性徹底依賴於主碼,如成績表SC(學生Id,課程Id,成績,學生姓名),「學生姓名」部分函數依賴於主碼(學生Id,課程Id),因此SC不知足第二範式併發
3.第三範式:不存在傳遞依賴ide
建立數據庫:create database "test001"函數
1、基本表的操做字體
1.建立表:fetch
學生信息表:
//建立
create table Student(
Sno int primary key not null,
Sname nvarchar(10) UNIQUE,
Sage int,
Ssex nchar(2) CHECK(Ssex in ('男','女')),
Ssdept nvarchar(20)
);
//修改屬性
alter table Student alter column Ssdept nvarchar(50)
課程信息表:建立:
create table Course(
Cno int primary key identity(1,1),
Cname nvarchar(50),
Cpno int ,
Ccredit int ,
foreign key (Cpno) references Course(Cno)
)
選課表:建立:
create table SC(
Sno int ,
Cno int ,
Grade int ,
primary key (Sno,Cno),
foreign key (Sno) references Student(Sno),
foreign key (Cno) references Course(Cno)
)
小貼士:屬性列的類型char[n]、varchar[n]、nvarchar[n]區別:
①.帶var的是可變長度類型,如varchar、nvarchar,這種類型存數據時會根據數據的實際大小分配適合的存儲空間,而不可變長度的char類型,每次存儲數據時都會分配固定的長度n的存儲空間,實際長度小於n時會用空格補齊(全部讀取該類型的屬性列數據時多用Trim())
②.若是存儲中文最好用帶n的nvarchar類型(其中n表示Unicode常量,能夠解決多語言字符集之間的轉換問題
),nvarchar不管是對一個字母仍是對一箇中文,都是分配兩個字節(因此nvarchar類型最多存儲4000個字符,不管中文仍是字母),而varchar類型對一個字母是分配一個字節,對一箇中文是分配兩個字節(因此varchar類型最多存儲4000個漢字,8000個字母),varchar也能夠存儲中文字符,可是若是遇到操做系統是英文操做系統而且對中文字體的支持不全面時, 在SQL Server存儲中文字符爲varchar就會出現亂碼(顯示爲??)
2.錄入數據
insert into Student(Sname,Sage,Ssex,Ssdept) values('kine',15,'女','國際')
3.修改數據
update Student set Sage=20 where Sname='kine'
4.刪除數據
delete from Student where Sname='kine'
5.T-SQL中的循環操做
declare @n int --定義變量
select @n=1 --給變量賦初始值
while @n<=100 --循環條件
begin --開始執行循環體
delete from Table1
where num=@n
select @n=@n+1--變量自增
end --循環體結束
6.存儲過程當中使用T-SQL循環
create procedure add100
@a int ,@b int
as
declare @n int
select @n=@a
while @n<=@b
begin
insert Table1(num) values(@n)
select @n=@n+1
end
--執行該存儲過程
execute add100 1,100
2、修改表
alter table 表名
add 新列名 數據類型 數據約束
drop 完整性約束名
alter column 列名 數據類型
①.向Student表增長「入學時間」列,其值類型爲日期類型
alter table Student add S_entertime DateTime
②.將年齡的數據類型由字符型改成整型
alter table Student alter column Sage int
③.增長課程表名稱必須取惟一值的約束條件
alter table Course add UNIQUE(Cname)
3、數據庫完整性
1.實體完整性:主鍵
2.參照完整性:外鍵
3.用戶自定義完整性:列值不爲空、列值惟1、列值值域範圍、完整性約束
如:約束屬性列值惟一:
Alter table Studen t add constraint c1 unique(Sname)
4、數據查詢
1.範圍查詢:
①查詢年齡在20~23歲之間的學生姓名、系別、年齡
Select Sname,Sdept,Sage
From Student
Where between 20 and 23
②查詢計算機系(CS)、數學系(MA)、信息系(IS)學生的姓名和性別
Select Sname,Ssex from Student where Sdept in (‘CS’,’’MA,’IS’)
2.字符匹配:
[NOT] LIKE ‘匹配串’ ESCAPE ’換碼字符’
①.查詢學號爲20222的學生信息
Select * from Student where Sno like ’20222’
②.查詢全部姓劉的學生信息
Select * from Student where Sname like ‘劉%’
③.查詢姓」歐陽」且全名爲3個漢字的學生信息
Select * from Student where Sname like ‘歐陽_ _’
小貼士:數據庫字符集爲ASCII時一個漢字須要兩個_,當字符集爲GBK時只須要一個_
④若是查詢字符串自己包含通配符%或 _ ,這時就要用ESCAPE
如:select * from Course where Cname like ‘DB\_Design’ ESCAPE ‘\’
3.涉及空值查詢
如:select Sno from SC where Grade IS NULL
小貼士:這類的’IS’不能用(=)替換
4. 多重條件查詢
用 AND 和 OR可用來聯結多個查詢條件,AND優先級高於OR,但能夠用括號改變優先級
5.order by 屬性列 :按照一個或多個屬性列的升序(ASC,默認的) 或降序(DESC) 排列,缺省值爲升序,對於空值,排序時顯示次序依系統而定,多是升序時最後顯示,降序時最早顯示。
6.彙集函數:
Count(dstinct |all 屬性列) 統計該屬性列的值的個數
SUM(dstinct |all 屬性列) 計算一數值型列值的總和
AVG(dstinct |all 屬性列) 計算一數值型列值的平均值
MAX(dstinct |all 屬性列) 求一數值型列的最大值
MIN(dstinct |all 屬性列) 求一數值型列的最小值
小貼士:在彙集函數遇到空值時,除了COUNT(*),都跳過空值而只處理非空值,WHERE子句中是不能用匯集函數做爲條件表達式。
7.GROUP BY 分組查詢
查詢選修了3門以上課程的學生學號
Select Sno from SC group by Sno HAVING COUNT(*) >3
5、鏈接查詢
1.等值鏈接:
查詢每一個學生及其選修課的狀況
Select Student.* ,SC.*
From Student,SC
Where Student.Sno=SC.Sno
可能的執行過程:嵌套循環算法的思想:首先在表Student中找到第一個記錄,而後從頭開始掃描SC表,逐一查找與Student第一條記錄的Sno相等的SC記錄,找到後就將Student中第一條記錄與該記錄拼接起來行成結果表中一個元組,SC表查完後,再找Student中第二條記錄,而後再從頭開始掃描SC,重複上面的操做,知道Student中所有元組處理完畢。
若是在SC表Sno上創建了索引的話,就不用每次全表掃描SC表了,而是根據Sno值經過索引找到相應的SC元組,查找速度更快。
天然鏈接:(去掉重複列的等值鏈接)
2.自身鏈接
查詢每一門課的間接先行課
Select T1.Cno,T2.Cpno from Course T1,Course T2 Where T1.Cpno=T2.Cno
3.外鏈接查詢:若是把捨去的元組也保留關係中,而在其餘屬性列上填NULL,那麼這種鏈接就叫外鏈接
①.左外鏈接:只保留左邊關係表中要捨棄的元組保留。
查詢每一個學生及其選修課程的狀況:
select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
from Student
LEFT OUT JOIN SC ON (Student.Sno=SC.Sno)
②.右外鏈接:相似左外鏈接,只保留右邊關係表中要捨棄的元組保留。
6、視圖:視圖是從基本表導出的虛表,數據庫只存放視圖的定義,不存放視圖對應的數據,這些數據仍然存放在原來的基本表中。
1.創建視圖:
Create View 視圖名稱
as
select子查詢
2.例子:
create view is_Isstudent
as
select Sno,Sname,Sage
from Student
where Sdept='計算機'
3.視圖的更新、刪除、插入數據等操做
4.視圖的用處和優勢:
①.下降多表鏈接查詢的邏輯複雜性,簡化應用程序:好比兩張間接相連的表可能要涉及到第三張表的三表鏈接查詢,若是構造一張視圖封裝這種複雜關係,對於程序員來講就像在操做兩張直接相連的表同樣。
②.實現必定的權限控制:能夠根據須要,對錶中的一部份內容作一個視圖,以供必定的角色使用。
③.能夠對 UNION 後的記錄集排序
create view A_B
AS
select a.id from a
union
select b.id from b
建立好視圖A_B後,能夠對該視圖進行排序
select id from A_B order by id
參考http://zhanghao007008.blog.163.com/blog/static/44874122200932293642494/
7、索引:索引是對數據庫表中一列或多列的值進行排序的一種結構,是該列值的集合和相應的指向表中相關記錄的存儲地址的清單,查詢數據時,根據索引快速定位到目標記錄,而沒必要一條一條記錄進行檢索匹配。
分類:①惟一(Unique)索引:此索引的每個索引值只對應惟一的數據記錄
②聚簇(Cluster)索引:該索引項的順序與表中的記錄的物理順序一致
1.建立索引:Create Unique或Cluster Index 索引名 ON 表名 (列名 ASC或DESC)
2.數據庫索引的做用和優勢缺點,參考http://blog.csdn.net/pang040328/article/details/4164874
8、存儲過程:
存儲過程就是將經常使用的或很複雜的工做,預先用SQL語句寫好並用一個指定的名稱存儲起來,而且這樣的語句是放在數據庫中的,還能夠根據條件執行不一樣SQL語句, 那麼之後要叫數據庫提供與已定義好的存儲過程的功能相同的服務時,只需調用execute,便可自動完成命令。
1.存儲過程的建立:
create procedure 存儲過程名
[參數名稱 數據類型及精度 [輸入參數][輸出參數],參數名稱 數據類型及精度 [輸入參數][輸出參數]……]
as
SQL語句
2.存儲過程的執行:
execute 存儲過程名 參數1、參數2。。。。。。
3.例子:
小貼士: 存儲過程的3種傳回值:
1.以Return傳回整數;2.以output格式傳回參數;3.Recordset
傳回值的區別:output和return均可在批次程式中用變量接收,而recordset則傳回到執行批次的客戶端中。
①不帶參數的查詢功能的存儲過程
create procedure pr_stu
as
select * from Student
go
execute pr_stu
②帶輸入參數的查詢功能的存儲過程
create procedure prstu2
@stuname nvarchar(10)
as
select * from Student where Student.Sname=@stuname
execute prstu2 'lucy'--執行該存儲過程
③帶輸出參數的查詢功能的存儲過程
create procedure prstu3
@sex varchar(20),@stuSum int output
as
select @stuSum=COUNT(*) from Student
where Ssex='男'
執行該函數
declare @sexSum int
execute prstu3 '女',@sexSum output
print @sexSum
④帶輸入參數的插入功能的存儲過程
create procedure prstu4
@name varchar(10),@sex char(2),@age int,@sdept nvarchar(10)
as
insert into Student(Sname,Ssex,Sage,Ssdept)
values(@name,@sex,@age,@sdept)
執行該存儲過程
execute prstu4 'mike','女',16,'藝術'
4.存儲過程的優點:
①. 存儲過程只在創造時進行編譯便可,之後每次執行存儲過程都不需再從新編譯,而咱們一般使用的SQL語句每執行一次就編譯一次,因此使用存儲過程可提升數據庫執行速度。
②. 常常會遇到複雜的業務邏輯和對數據庫的操做,這個時候就會用SP來封裝數據庫操做。當對數據庫進行復雜操做時(如對多個表進行Update,Insert,Query,Delete時),可將此複雜操做用存儲過程封裝起來與數據庫提供的事務處理結合一塊兒使用。能夠極大的提升數據庫的使用效率,減小程序的執行時間,這一點在較大數據量的數據庫的操做中是很是重要的。在代碼上看,SQL語句和程序代碼語句的分離,能夠提升程序代碼的可讀性。
③.存儲過程能夠設置參數,能夠根據傳入參數的不一樣重複使用同一個存儲過程,從而高效的提升代碼的優化率和可讀性。
④. 安全性高,可設定只有某此用戶才具備對指定存儲過程的使用權
9、觸發器:觸發器是用戶定義在數據表上的一類由事件驅動的特殊過程,SQL裏面的事件處理,這裏的事件主要是指Insert、Update、Delete
1.觸發器是與表事件相關的特殊的存儲過程,但又不一樣於存儲過程:觸發器與存儲過程很是類似,觸發器也是SQL語句集,二者惟一的區別是觸發器不能用EXECUTE語句調用,而是在用戶執行Transact-SQL語句時自動觸發(激活)執行。
觸發器不一樣於存儲過程,觸發器主要是經過事件執行觸發而被執行的,而存儲過程能夠經過存儲過程名稱名字而直接調用。
2.建立觸發器的語法:
Create TRIGGER 觸發器名稱
before|after 觸發的事件
on 表名
for each row|statement
[when 觸發條件]
觸發動做體
小貼士:①觸發事件能夠是Insert、DELETE、UPDATE,也能夠是這幾個事件的組合,如insert or update 。uodate後面還能夠有of<觸發列,...> ,即進一步指明修改拿些列時會激活觸發器。
②觸發器類型:Ⅰ.行級觸發器(for each row),執行SQL時每影響一條記錄,觸發動做就執行一次。Ⅱ語句級觸發器(for each statement),執行完全部語句,影響最終記錄後才總共發生一次觸發動做。
③觸發條件:若是定義觸發條件,觸發器被激活時,只有當觸發條件爲真時纔會執行觸發動做體,若是省略when觸發條件則觸發動做體在觸發器激活後當即執行。
④觸發動做體:能夠是PL/SQL過程塊,也能夠是存儲過程的調用
3.例子:爲老師表Teacher定義完整性規則"教授的工資不低於10000,若是低於10000自動改成10000"
create trigger tr_001
before insert or update
on teacher
for each row
as begin
IF(new.Job='教授') AND (new.Sal<10000)
then new.sal=10000
END IF
END;
參考: http://blog.csdn.net/madforg/article/details/7300265
4.觸發器的用處:
①. 能夠監控某些特殊的屬性列的值
②. 自動執行。觸發器在對錶的數據做了任何修改(好比手工輸入或者應用程序的操做)以後當即被激活。
③. 級聯更新。觸發器能夠經過數據庫中的相關表進行層疊更改,這比直接把代碼寫在前臺的作法更安全合理。
④. 強化約束。觸發器能夠引用其它表中的列,可以實現比CHECK約束更爲複雜的約束。
⑤. 跟蹤變化。觸發器能夠阻止數據庫中未經許可的指定更新和變化。
5. 強制業務邏輯。觸發器可用於執行管理任務,並強制影響數據庫的複雜業務規則。
10、事務:事務(Transaction)是併發控制的單位,是用戶定義的一個操做序列。這些操做要麼都作,要麼都不作,是一個不可分割的工做單位。就
是多個語句併發執行,要成功一塊兒成功,要失敗就全失敗(失敗後會回滾到執行前的狀態),好比銀行轉賬:SQL1:用戶A扣賬,SQL2:用戶B加賬,像這樣的就要用事物,不能說錢扣掉了,但沒轉過去,保持雙向更改數據。
數據庫事務是指由一個或多個SQL語句組成的工做單元,這個工做單元中的SQL語句相互依賴,若是有一個SQL語句執行失敗,就必須撤銷整個工做單元
1.事務4大屬性:
① 原子性(Atomicity):事務是一個完整的操做。
② 一致性(Consistency):當事務完成時,數據必須處於一致狀態。
③ 隔離性(Isolation):對數據進行修改的全部併發事務是彼此隔離的。
④ 持久性(Durability):事務完成後,它對於系統的影響是永久性的。
如何理解這四大屬性,參考http://blog.csdn.net/chosen0ne/article/details/10036775
事務具備原子性,要麼不執行,要麼全執行
2使用方法:
①開始事務: begin transaction
②提交事務:commit transaction
③回滾事務: rollback transaction
3.例子:
create procedure exchangemoney
@idA int ,@idB int ,@num int
as
begin transaction
update bank set moneySum=moneySum-@num where Id=@idA
update bank set moneySum=moneySum+@num where Id=@idB
if @@ERROR<>0
begin rollback transaction
return 0
end
else
begin commit transaction
return 1
end
執行該存儲過程:
execute exchangemoney 1,2,1000
參考http://www.cnblogs.com/zhuifengnianshao/archive/2010/11/24/1886939.html
小貼士:全局變量@@ERROR是返回與它 最近的SQL語句的錯誤碼,侷限於DML語句和select語句,若是執行他們出現錯誤,則返回一個不等於0的錯誤碼,若是沒有出錯,則返回0。
11、遊標:遊標(cursor)是系統爲用戶開設的一個數據緩衝區,存放SQL語句的執行結果。每一個遊標區都有一個名字。用戶能夠用SQL語句逐一從遊標中獲取記錄,並賦給主變量,交由主語言進一步處理.
1.遊標操做:使用遊標有四種基本的步驟:聲明遊標、打開遊標、提取數據、關閉遊標。
當用OPEN語句打開了遊標並在數據庫中執行了查詢後,您不能當即利用在查詢結果集中的數據。您必須用FETCH語句來取得數據。一條FETCH語句一次能夠將一條記錄放入程序員指定的變量中。事實上,FETCH語句是遊標使用的核心
2.例子:
table1結構以下
id int
name varchar(50)
declare @id int
declare @name varchar(50)
declare cursor1 cursor for --定義遊標cursor1
select * from table1 --使用遊標的對象(跟據須要填入select文)
open cursor1 --打開遊標
fetch next from cursor1 into @id,@name --將遊標向下移1行,獲取的數據放入以前定義的變量@id,@name中
while @@fetch_status=0 --判斷是否成功獲取數據
begin
update table1 set name=name+'1'
where id=@id --進行相應處理(跟據須要填入SQL文)
fetch next from cursor1 into @id,@name --將遊標向下移1行
end
close cursor1 --關閉遊標
deallocate cursor1
參考:http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html