SQLServer數據庫(二)
數據庫設計:就是將數據庫中的數據庫實體及這些數據庫實體之間的關系,進行規劃和結構化的過程。
項目開發過程:
需求分析
概要設計
詳細設計
代碼編寫
運行測試
打包發行
數據庫的系統分析基本步驟:收集信息、標識實體、標識每個實體需要存儲的詳細信息、標識實體之間的關系。
實體,就是指現實世界中具有區分其它事物的特征或屬性,並與其他實體有聯系的實體。實體一般是名詞,對應表中的一行數據,但我們在開發時,也常常把整個表稱為一個實體。
屬性可以理解為實體的特征。
聯系是兩個或多個實體之間的關聯關系。一般為動詞。
映射基數表示通過聯系與實體關聯的其他實體的個數。
一對一、一對多、多對多、多對一
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來獲得當前插入記錄的編號。
SQLServer數據庫(二)