數據庫設計:就是將數據庫中的數據庫實體及這些數據庫實體之間的關系,進行規劃和結構化的過程。
項目開發過程:
需求分析
概要設計
詳細設計
代碼編寫
運行測試
打包發行
數據庫的系統分析基本步驟:收集信息、標識實體、標識每個實體需要存儲的詳細信息、標識實體之間的關系。
?
實體,就是指現實世界中具有區分其它事物的特征或屬性,并與其他實體有聯系的實體。實體一般是名詞,對應表中的一行數據,但我們在開發時,也常常把整個表稱為一個實體。
屬性可以理解為實體的特征。
聯系是兩個或多個實體之間的關聯關系。一般為動詞。
映射基數表示通過聯系與實體關聯的其他實體的個數。
一對一、一對多、多對多、多對一
1:1、1:N、M:N、N:1
實體關系圖(E-R圖)組成部分:
矩形表示實體集
橢圓形表示屬性
菱形表示聯系集
直線表示連接屬性和實體集,也用來連接實體集和聯系集。
?
關系模式:一個關系描述的屬性名的集合。
?
三大范式:
第一范式,確保每列的原子性。
第二范式,確保每列都和主鍵相關。
第三范式,確保每列都和主鍵列直接相關。
?
數據庫文件,主數據文件:xxx.mdf、次要數據文件:xxx.ndf、日志文件:xxx.ldf
數據庫至少有一個數據文件和一個日志文件,實際應用中,為了保證的安全性,提高存儲逼真數據庫管理員會將數據文件
和日志文件分別放置在不同的驅到器上。
?
創建數據庫,下面使用T-SQL創建數據庫:
create?database?數據庫名
on?[primary]
(
<數據文件參數>[,...n]?[<文件組參數>]
)
[log?on]
(
{<日志文件參數>?[,...n]}
)
文件參數:
(
[name=邏輯文件名,]
filename=帶文件名的物理文件路徑
[,size=大小mb]
[,maxsize={最大容量|unlimited}]
[,filegrowth=增長量mb,也可以是百分比]
)[,...n]
文件組參數:
filegroup?文件組名<文件參數>?[,...n]
其中,[]?表示可選的部分,{}?表示必需的部分。
數據庫名:數據庫的名稱,最長為128個字符。
primary:該選項是一個關鍵字,指定主文件組中的文件。
log?on:指明事務日志文件的明確定義。
name:指定數據庫的邏輯名稱,這是在SQL?Server中使用的名稱,是數據庫在SQL?Server中的標識符。
filename:指定數據庫所在文件的操作系統文件名稱和路徑,該操作系統文件名和name的邏輯名稱一一對應。
size:指定數據庫的初始容量大小。
maxsize:指定操作系統文件可以增長到的最大值。
filegrowth:指定文件每次增加容量的大小,當指定數據為0時,表示文件不增長。
例: if?db_id(‘MySchool’)?is?not?null
drop?database?MySchool
go
create?database?MySchool
on?primary
(
name=’MySchool_data’,
filename=’D:\Projects\MySchool_data.mdf’,
size=10mb,
maxsize=100mb,
filegrowth=10%
)
log?on
(
name=’MySchool_log’,
filename=’D:\Projects\MySchool_log.ldf’,
size=2mb,
maxsize=10mb,
filegrowth=1mb
)
go
?
刪除數據庫:
drop?database?database_name;
exists(查詢語句)??檢測某個查詢是否存在。如果查詢結果為null,則整個exists語句返回false,反之true。
例:if?exists(select?*?from?sysdatabases?where?name=’MySchool’)
drop?database?MySchool
?go
?
創建表:
create?table?table_name
(column_name?數據類型?列的特征?[,...n])
列的特征包括:
是否為空?null/not?null
是否為標識列?identity(1,1)
是否為主鍵?primary?key
是否有默認值??=值
...
表的清單存放在該數據庫的系統表sysobjects中。
刪除表:drop?table?table_name
if?exists(select?*?from?sysobjects?where?name=’student’
drop?table?student
?
刪除數據庫和表都可以使用下面的簡便方式
刪除數據庫:if?db_id(‘database_name’)?is?not?null
drop?database?database_name
刪除表:if?object_id(‘table_name’)?is?not?null
drop?table?table_name
?
修改表結構:添加列、改變列的長度、改變列的數據類型、刪除列
alter?table?table_name
[alter?column?column_name?[新數據類型]]
[add?<new_column_name>?<數據類型>?[完整性約束]]
[drop?<完整性約束名>]
例: 添加列: alter?table?Book
add?bName?varchar(10);
修改列: alter?table?Book
alter?column?bName?char(10);
刪除列: alter?table?Book
drop?column?bname;
表操作
查看表:exec?sp_help?Book
重命名表:exec?sp_rename?[當前表名],[新表名]
?
常用約束類型:
主鍵約束(Primary?Key?Constraint):要求主鍵列數據唯一,并且不允許為空
非空約束(Not?Null):要求列不能存在空值
唯一約束(Unique?Constraint):要求該列的值必須唯一,允許為空,但只能出現一個空值,主鍵一般都具有唯一約束
檢查約束(Check?Constraint):某列的取值范圍限制、格式限制等。
默認約束(Default?Constraint):指定某列的默認值。如果插入數據時沒有插入該列數據,具使用默認值
外鍵約束(Foreign?Key?Constraint):用于在兩表之間建立關系,需要指定引用主表的哪一列。一般引用主表的主鍵列
?
添加約束,語法:alter?table?table_name
add?constraint?約束名?約束類型?具體的說明
--添加主鍵約束
alter?table?student
add?constraint?PK_studentNo?primary?key?(studentNo)?--如果要使用組合主鍵,可在括號內加列名,用逗號
隔開。
--添加唯一約束
alter?table?student
add?constraint?UQ_student_identityCard?unique?(identityCard)
--添加默認約束
alter?table?student?
add?constraint?DF_student_address?default(‘地址不詳’)?for?address
--添加檢查約束
alter?table?student?with?nocheck --這里的with?nocheck?可以建立檢查約束時不對舊數據進行檢測
add?constraint?CK_student_bornDate?check?(bornDate>=’1980-01-01’)
--添加外鍵約束
alter?table?result
add?constraint?FK_result_student?foreign?key(studentNo)?references?student(studentNo)
刪除約束:
alter?table?table_name
drop?constraint?constraint_name
?
創建序列:
create?sequence?sequence_name
start?with?種子
increment?by?增量
得到當前序列值:next?value?for?sequence_name
?
局部變量,以@開頭,全局變量以@@開頭,全局變量只能讀取不能聲明。
聲明局部變量:declare?@vaviable_name?<數據類型>
給局部變量賦值:
set?@variable_name?=?表達式,可以是一個查詢,但是必須返回的是一個值 --這種是直接把值賦給變量
select?@variable_name=value?from?table_name?where?....--這種是查詢出值之后再賦給變量
例: declare?@name?varchar(8) --聲明變量
declare?@studentNo?int??--聲明變量
set?@name=’李文才’ --使用set賦值
select?@studentNo=studentNo?from?student?where?studentName=@name
set語句與select語句的區別:
對比項 | set | select |
同時對多個變量賦值 | 不支持 | 支持 |
表達式返回多個值時 | 出錯 | 將返回的最后一個值賦給變量 |
表達式未返回值 | 變量被賦值為NULL | 變量保持原值 |
?
全局變量:
變量 | 含義 |
@@error | 最后一個T-SQL錯誤的錯誤號,>0則有錯,=0則無錯 |
@@identity | 最后一次插入的標識值 |
@@language | 當前使用的語言的名稱 |
@@max_connections | 可創建的、同時連接的最大數目 |
@@rowcount | 受上一個SQL語句影響的行數 |
@@servername | 本地服務器的名稱 |
@@servicename | 該計算機上的SQL服務器名稱 |
@@timeticks | 當前計算機上每刻度的微秒數 |
@@transcount | 當前連接打開的事務數 |
@@version | SQL?Server的版本信息 |
?
輸出語句:
print??變量或字符串 --直接在消息框中顯示信息
select?變量?as?自定義列名?--當作查詢結果輸出
例: print?‘服務器的名稱’+@@servername
print?‘SQL?Server的版本’+@@version
select?@@serverName?as?‘SQL?Server的版本’
select?@@version?as?‘SQL?Server的版本’
設置不顯示受影響行數:set?nocount?on;
?
數據類型轉換:
cast(表達式?as?數據類型)
convert(數據類型(長度),表達式[,樣式]) --第三個參數可略,一般只對日期格式有效,如101,102
?
邏輯控制語句:
begin-end語句,作用類似于編程語言的”{?}”,表示語句塊的開始和結束。在一個語句塊中可以包含另一個語句塊。
begin
語句或語句塊
end?--可以在end后加注釋,這樣可提高代碼的可讀性
if-else條件語句,屬于分支結構控制語句:
if(條件)
begin
語句或語句塊
end
else
begin
語句或語句塊
end
while循環語句,可以根據某些條件重復執行一條SQL語句或一個語句塊。可以使用continue和break語句來控制
while(條件)
begin
語句或語句塊
[break|continue]
end
case-end多分支語句,計算一組條件表達式,并返回其中一個符合條件的結果。像是if-else?if-else
case?
when?條件1?then?結果1
when?條件2?then?結果2
[else?其他結果]
end
try-catch,數據庫中的異常處理:
begin?try
語句或語句塊
end?try
begin?catch
語句或語句塊
end?catch
?
go?指令,它把一條或多條SQL語句作成一個可執行單元,稱為執行計劃。這樣的話,這一個執行單元和其它的執行單元就不
會互相干擾,相當于邏輯斷路,從而提部執行效率。
如: use?MySchool
go
?
子查詢,在語句中嵌入查詢語句。
select?...?from?表1?where?列1?>?(子查詢)?--這里的”>”運算符可以換成其他的運算符號。但是將子查詢和比較運
算符聯合使用,必須保證子查詢返回的值不能多于一個。
編寫查詢時,盡量寫列名列表,這樣會提高執行效率,以及減少服務器壓力。
子查詢可以在多表間查詢符合條件的數據,從而替換表連接(join)查詢。這個時候在查詢結果要有別名才行
表連接都可以用子查詢替換,但反過來不一定。子查詢比較靈活、方便、形式多樣,適合作為查詢的篩選條件;而表連接更
適合于查看多表的數據。
在給查詢出來的表達式取別名時,如果用“=”號,別名前置;?如果用“as”或空格“?”,別名后置。
當為某個表命名了別名后,在select語句中出現該表的列需要指定表名時,就必須統一使用該表的別名;否則語法錯誤。
?
in和not?in子查詢,用于限定列值的范圍。
例: select?studentNo,studentName?from?Student?
where?studentNo?in?{ --語法上in?和not?in?是一個樣的。
select?studentNo?from?Result
}
in子查詢,是指定限制某列的篩選范圍只能是子查詢結果集中的值。
not?in子查詢,是指定限制某確的篩選范圍不能包含子查詢結果集中的值。
?
exists和not?exists子查詢
exists子查詢:exists(子查詢)?--如果子查詢的結果為NULL,則exists(子查詢)返回false,否則返回true
not?exists子查詢:not?exists(子查詢) --效果和exists(子查詢)相反,為NULL返回true,否則返回false
可以利用exists和not?exists子查詢來作為if-else判斷語句、while循環、where子句的條件?
?
給結果集添加行號列:
select?列名=row_number()?over(order?by?列名?asc[desc])?from?table_name --結果集中添加了一列
?
子查詢注意事項
1.子查詢語句可以嵌套在SQL語句中任何表達式出現的位置,select,from,where,group?by?,having
select?tname=(select?tname?from?topic?where?topic.tid=news.ntid),ntitle,nauthor?from?news
此查詢代替了內聯接查詢
select?*?from?(子查詢)?as?表的別名 --可以把子查詢的結果當作一個表進行表聯接查詢。
2.在子查詢的select?子句中不能出現text,ntext或image數據類型的列,不支持在子查詢語句中查詢二進制的數據。
3.只出現在子查詢中而沒有出現在父查詢中的表不能包含在輸出列中。
?
事務(Transaction)是單個的工作單元。如果某一事務成功,則在該事務中進行的所有數據更改均會提交,永久保存。如果事
務遇到錯誤且必須取消或回滾,則所有數據更改均被清除。其實每一句SQL語句都是一個很小很小的事務。
事務是作為單個邏輯工作單元執行的一系列操作。
一個邏輯工作單元的4個屬性,ACID:
1.原子性(Atomicity):事務是一個完整的操作。事務的各元素是不可分的(原子的)。
2.一致性(Consistency):當事務完成時,數據必須外于一致狀態。
3.隔離性(Isolation):對數據進行修改的所有并發事務是彼此隔離的,這表明事務必須是獨立的,它不應該以任何形
式依賴于或影響其他事務。
4.持久性(Durability):事務的持久性指不管系統是否發生了故障,事務外理的結果都是永久的。
?
執行事務的語法
開始事務:begin?transaction
提交事務:commit?transaction
回滾事務:rollback?transaction
?
事務的分類
1.顯式事務:begin?transaction明確指定事務的開始。(最常用)
2.隱式事務:通過設置set?implicit_transactions?on?語句,將隱式事務模式設置為打開。當以隱式事務操作時,
SQL?Server將在提交或回滾事務后自動啟動新事務。只要提交或回滾事務即可。
3.自動提交事務:這是SQL?Server的默認模式,它將每條單獨的T-SQL語句視為一個事務。如果成功執行,則自動提交
。如果錯誤,則自動回滾。
?
編寫事務的原則:
1.事務盡可能簡短。
2.事務中訪問的數據量盡量最少。
3.查詢數據時盡量不要使用事務。
4.在事務處理過程中盡量不要出現等待用戶輸入的操作。事務長時間占用資源,有可能造成系統阻塞。
執行大型事務時,判斷是否需要回滾,可以用一個變量@err把每一條數據庫操作語句的@@error累加起來。如果到最后這個變量@err都是0,則證明這個事務沒有出錯,可以永久化這個操作。否則回滾事務。
?
視圖(view),是保存在數據庫中的select查詢。使用視圖的原因有:一個是出于安全考慮,用戶不必看到整個數據庫的結構
,而隱藏部分數據;?另一個是符合用戶日常業務邏輯,使他們對數據更容易理解。可以對視圖中的數據進行增刪改,但一
般用作查詢。
視圖是一種虛擬表通常是作為來自一個表或多個表的行或列的子集合成的。
用途:
篩選表中的行。
防止未經許可的用戶訪問敏感數據。
將多個物理數據表抽象為一個邏輯數據表。
對最終用戶的好處:
結果更容易理解
獲得數據更容易
對開發人員的好處:
限制數據檢索更容易
維護應用程序更方便
?
創建視圖:
create?view?view_name
as
<select語句>
刪除視圖:drop?view?view_name --視圖在當前數據庫下表sysobjects中。刪除視圖后,原始表不影響。
查詢視圖:select?*?from?view_name --把視圖當作一般物理表來用
使用視圖的注意事項:
1.每個視圖中可以使用多個表。
2.與查詢相似,一個視圖可以嵌套另一個視圖,但最好不要超過3層。
3.視圖定義中的select語句不能包括下列內容:
order?by子句,除非在select語句的選擇列表中也有一個top子句。
into關鍵字。
引用臨時表或表變量。
?
索引(index),作通過使用索引,大大提高數據庫的檢索速度,改善數據庫性能。
索引分類:
1.唯一索引,不允許兩行具有相同的索引值。若創建了唯一約束,則將自動創建唯一索引。盡管唯一索引有助于找到
信息,但為了獲得最佳性能,仍建立使用主鍵約束。
2.主鍵索引,定義一個主鍵列,將自動建立主鍵索引,要求主鍵中的的每個值是非空,唯一的。
3.聚集索引,表中各行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能有一個聚集索引。主鍵默認聚集索引
4.非聚集索引,建立在索引頁上,當查詢數據時可以從索引中找到記錄存放的位置。非聚集索引法中條行數據存放的?物理順序與鍵值的邏輯順序不匹配。聚集索引比非聚集索引有更快的數據訪問速度。
5.復合索引,可以將多個列組合作為索引,只有用到復合索引的第一列或整個復合索引列作為條件完成數據查詢時才
會用到該索引。
6.全文索引,是一種特殊類型的基于標記的功能性索引,由SQL?Server中全文引擎服務創建和維護。主要用于大量 文字中搜索字符串,此時使用全文索引的效率將大大高于使用like關鍵字的效率。
?
創建索引:
create?[unique][clustered|nonclustered]?index?index_name
on?table_name?(column_name[,...n])
[with?fillfactor=x]
--unique指指唯一索引,可選。
--clustered、nonclustered指定是聚集索引還是非聚集索引,可選。
--fillfactor表示填充因子,指定一個0~100的值,該值指示索引頁填洪的空間所占的百分比。
刪除索引:drop?index?table_name.index_name
--刪除表時,該表的所有索引將同時被刪除。
--如果要刪除退給所有索引,則先要刪除非聚集索引,再刪除聚集索引。
調用索引: select?*?from?table_name?
with(index=index_name)
where?條件?
查看索引:
1.用系統存儲過程sp_helpIndex查看:?exec?sp_helpIndex?table_name --查看該表下的索引
2.用視圖sys.indexes查看:select?*?from?sys.indexes?
?
優化SQL語句:
1.查詢時減少使用“*”返回全部列,不要返回不務要的列。
2.索引列的值應該盡量小,在字節數小的列上建立索引。
3.where子句中有多個條件表達式時,包含索引列的表達式應置于其他條件表達式之前。
4.避免在order?by子句中使用表達式。
5.根據業務數據發生頻率,定期重新生成或重新組織索引,進行碎片整理。
?
存儲過程,(Procedure)是SQL語句和控制語句的預編譯集合,保存在數據庫里,可由應用程序調用執行,而且允許用戶聲明
變量、邏輯控制語句及其他強大的編程功能。類似于方法、函數
優點:
1.模塊化程序設計。
2.執行速度快,效率高。
3.減少流量。
4.具有良好的安全性。
?
系統存儲過程,用戶可以通過系統存儲過程訪問和更新系統表。名稱以“sp_”開頭,并存放在Resource數據庫中。可以在
任何數據庫中運行系統存儲過程,但執行的結果會反映在當前數據庫中。
系統存儲過程 | 說明 |
sp_databases | 列出服務器上所有數據庫信息,包括數據庫名稱和數據庫大小 |
sp_helpdb | 報告有關指定數據庫或所有數據庫的信息 |
sp_renamedb | 重命名數據庫名稱 |
sp_tables | 返回當前環境下可查詢的表或視圖的信息 |
sp_columns | 返回某個表或視圖的列信息,包括列的數據類型和長度等 |
sp_help | 查看某個數據庫對象的信息,如列名、主鍵、約束、外鍵、索引等 |
sp_helpconstraint | 查看某個表的的約束 |
sp_helpindex | 根據某個表的索引 |
sp_stored_procudures | 顯示存儲過程的列表 |
sp_password | 添加或修改登錄賬戶的密碼 |
sp_helptext | 顯示默認值、未加密的存儲過程、用戶定義的存儲過程、觸發器或視圖的實際文本 |
?
執行存儲過程:
exec[ute]?procedure_name?[參數值列表]
--exec是execute的簡寫,如果是執行語句第一句,可以不用寫exec。
?
擴展存儲過程(Extended?Stored?Procedures)是SQL?Server提供的各類系統存儲過程中的一類。
exec?xp_cmdshell?DOS命令 [no_output] --no_output為可選參數,設置執行DOS命令后是否輸出返回信息。
例: exec?sp_configure?‘show?advanced?option’,1
go
reconfigure
go
exec?sp_configure?‘xp_cmdshell’,1
go
reconfigure
go
exec?xp_cmdshell?‘DOS命令’
?
用戶自定義存儲過程,一個完整的存儲過程包括:輸入參數和輸出參數、T-SQL語句、存儲過程的返回值
創建存儲過程:
create?proc[edure]?procedure_name
[ {@參數1?數據類型}[=默認值][output],
.....,
{@參數n?數據類型}[=默認值][output]
]
as
begin
SQL語句
end
刪除存儲過程:drop?proc[edure]?procedure_name --存儲過程信息在數據庫表sysobjects?中
創建帶輸入參數的存儲過程:
輸入參數:可以在調用時向存儲過程傳遞參數,此類參數可用來向存儲過程中傳入值。
輸出參數:如果希望返回值,則可以使用輸出參數,輸出參數后有“output”標記。
如果存儲過程的參數后面有“outpu”關鍵字,則表示此參數為輸出參數;?否則視為輸入參數,輸入參數還可以設置為?默認值default。
執行帶參數的存儲過程:
exec[ute]?[返回變量=]?存儲過程?[@參數1=]參數值1[output]|[default],
?.....,
?[@參數n=]參數值n[output]|[default]
為了調用方便,最好將有默認值的參數放在存儲過程參數列表的最后。
創建存儲過程時,參數有“output”關鍵字,則調用時也需要要變量后跟隨“output”關鍵字。
執行帶有輸出參數的存儲過程,如果不按參數順序傳遞參數值,則要指定參數名。一旦某個參數按“@參數名=值”格式傳
遞數據,那么之后的參數必須以同樣的格式傳遞數據
例: exec?usp_query_num?@UnpassNum?output,@TotalNum?output,@pass=50,@SubjectName=’Java?Logic’
?
raiserror語句,返回用戶定義的錯誤信息,可指定嚴重級別,設置系統變量記錄所發生的錯誤。
raiserror?({msg_id|msg_str}{,severity,state}[with?option[,.....n]])
--msg_id:在sysmessages系統表中指定的用戶定義錯誤信息。
--msg_str:用戶定義的特定信息,最長為255個字符。
--severity:與特定信息相關聯,表示用戶定義的嚴重性級別。用戶可使用的為0~18級,19~25級是為sysadmin固定角
色的成員預留的,并且需要指定with?log選項,20~25級被認為是致命錯誤。
--state:表示錯誤的狀態,是1~255中的值。
--option:錯誤的自定義選項,可以是下列任一值。
log:在Miscosoft?SQL?Server數據庫引擎實例的錯誤日志和應用程序日志中記錄錯誤。
nowait:將消息立即發送給客戶端。
seterror:將@@error值和error_number值設置為msg_id或50000,不用考慮嚴重級別。
例: begin?try
....
end?try
begin?catch
raiserror?(‘錯誤信息’,16,1)
return? --立即返回,退出存儲過程
end?catch
錯誤嚴重級別大于10,將自動設置系統全局變量@@error為非零值,表示意識執行錯誤。判斷語句執行是否出錯。
?
?
運行sql語句的文本:
1).exec?(@sql),N’參數列表’,參數值列表
2).exec?sp_executesql?@sql,N’參數’,參數
注意: 1.參數的數目、類別、順序必須和存儲過程中的要一致。后一種方法可以用輸出參數,用表與存儲過程相同。
2.語句進行拼接時,要注意長度是否不夠。
3.拼接參數時,兩個單引號?‘’?視為一個單引號’ 如:where?name=’’’+@name+’’’;
4.NULL不能被拼接。
?
insert時,如果用序列,那么最好定義一個變量存它,否則之后不好調用。
如果用標識列,可以用@@identity來獲得當前插入記錄的編號。