SQLServer基礎開發入門
建立資料庫和資料表
資料庫的建立
資料庫分類
通過檢視物件資源管理器來區分資料庫型別
master
:儲存所有資料庫的資訊(系統登入、系統設定、已經連線的SERVER等)model
:建立新使用者資料庫的模板資料庫msdb
:用來儲存資料庫備份,SQL Agent資訊、DTS程式包、SQLSERVER任務等資訊tempdb
:存有臨時物件,列如臨時表格和儲存過程
使用者資料庫檔案組成
資料庫物理檔案的組成:資料庫檔案+日誌檔案
.mdf
(主資料檔案)或.ndf
(次要資料檔案).ldf
日誌檔案
一個數據庫必須且只能包含一個mdf,可以有多個ndf和ldf(至少一個)
建立資料庫
- 建立一個主資料檔案和一個日誌檔案
use master
go
create database StudentManageDB
on primary
(
-- 資料庫檔案的邏輯名
name='StudentManageDB_data',
-- 資料庫物理檔名(絕對路徑)
filename='D:\SQLserverDB\StudentManageDB_data.mdf',
-- 資料庫檔案初始大小
size=10MB,
-- 資料檔案增常量
filegrowth=1MB
)
-- 建立日誌檔案 log on ( name='StudentManageDB_log', filename='D:\SQLserverDB\StudentManageDB_log.ldf', size=2MB, filegrowth=2MB ) go
檔案組類似於資料夾,主要用於管理磁碟檔案,檔案組分為主檔案組和次檔案組,日誌檔案不屬於任何檔案組
- 建立一個主資料檔案和一個日誌檔案
use master go create database StudentManageDB on primary ( -- 資料庫檔案的邏輯名 name='StudentManageDB_data', -- 資料庫物理檔名(絕對路徑) filename='D:\SQLserverDB\StudentManageDB_data.mdf', -- 資料庫檔案初始大小 size=10MB, -- 資料檔案增常量 filegrowth=1MB ), ( name='StudentManageDB_data1', -- 建立次要資料檔案,不能和主資料檔案同名 filename='D:\SQLserverDB\StudentManageDB_data1.ndf', size=10MB, filegrowth=1MB )
-- 建立日誌檔案
log on
(
name='StudentManageDB_log',
filename='D:\SQLserverDB\StudentManageDB_log.ldf',
size=2MB,
filegrowth=2MB
),
(
name='StudentManageDB_log1',
filename='D:\SQLserverDB\StudentManageDB_log1.ldf',
size=2MB,
filegrowth=2MB
)
go
刪除資料庫
- 刪除方法
-- 判斷當前資料是否存在
if exists (select * from sysdatabases where name='StudentManageDB')
drop database StudentManageDB -- 刪除資料庫
go
drop
刪除後資料庫將不可恢復,謹慎使用
分離與附加資料庫
-
分離資料庫的必要性及語法
- 當資料庫執行中,通常無法直接移動和複製資料庫檔案
- 所謂分離資料庫就是將正在使用的資料庫檔案解除服務的限制
exec sp_detach_db @name=資料庫名稱
-
附加資料庫的必要性及語法
- 附加資料庫就是將指定位置的資料庫檔案加入到資料庫服務中並執行
- 資料庫只有附加後,使用者才能通過DBMS操作資料
exec sp_attach_db @dbname=資料庫名稱, @filename1=資料庫主檔案物理檔案路徑 @filename2=資料庫日誌檔案物理檔案路徑
--分離資料庫
exec sp_detach_db @dbname=StudentManageDB
--附加資料庫方法1
exec sp_attach_db @dbname=StudentManageDB,
@filename1='D:\SQLserverDB\StudentManageDB_data.mdf',
@filename2='D:\SQLserverDB\StudentManageDB_log.ldf'
--附加資料庫方法2
exec sp_attach_db StudentManageDB,
'D:\SQLserverDB\StudentManageDB_data.mdf',
'D:\SQLserverDB\StudentManageDB_log.ldf'
資料表的建立
SQL Server資料型別
-
文字型別:字元資料包含任意字母、符號或數字字元的組合
char
:固定長度的非Unicode字元資料,最大長度為8000個字元varchar
:可變長度的非Unicode資料,最大長度為8000個字元text
:儲存長文字資訊,最大長度為231-1(2147483647)個字元nchar
:固定長度的Unicode資料,最大長度為4000個字元nvarchar
:可變長度的Unicode資料,最大長度為4000個字元ntext
:儲存可變長度的長文字,230-1(1073741823)個字元
-
整數型別
bigint
:佔用8個位元組,可表示範圍:-263~263-1之間的整數int
:佔用4個位元組,可表示範圍:-231~231-1之間的整數smallint
:佔用兩個位元組,可表示範圍:-215~215-1之間的整數tinyint
:佔用1個位元組,可表示範圍:0~255之間的整數
-
精確數字型別
decimal
:-1038~1038-1之間的固定精度和小數的數字numeric
:功能等同於decimal- 寫法:decimal(整數,小數)和numeric(整數,小數)
- 預設:如果不指定位數,預設18位整數,0位小數
-
近似資料(浮點)型別
- float[(n)]表示範圍:-1.79E+308~1.79E+308(1.79乘以10的308次冪)
- n表示精度,在1-53之間取值,當n在1-24之間時,精度為7位有效數字,佔用4個位元組;當n在25~53之間是,精度為15位有效數字,佔用8個位元組
- real表示範圍:-3.40E+38~3.40E+38佔用4個位元組儲存空間,相當於float(24)
-
日期型別
datetime
:允許的範圍1753-1-1至9999-1-1smalldatetime
:允許的範圍1900-1-1至2079-6-6- 時間精度不同:datetime精確到3/100秒;smalldatetime精確到1分鐘
- 格式說明:
- 分隔數字方式:2013-08-20或08/20/2013
- 純數字方式:08202013
- 英文數字方式:Aug 20,2013
- 注意問題:日期在使用的時候需要使用單引號(' ')括起來
-
貨幣型別
money
:貨幣數值介於-263與263-1之間,精確到貨幣單位的千分之一smallmoney
:貨幣資料介於-214748.3648與-214748.3648之間,精確到貨幣單位的千分之十
-
位型別
bit
:表示“是/否”型別的資料(0,1/true,false)
-
二進位制型別
binary
:固定長度的二進位制資料,最大長度為8000個位元組vbinary
:可變長度的二進位制資料,其最大長度為8000個位元組image
:可變長度的二進位制資料,其最大長度為231個位元組- 應用場合:可儲存圖片
建立資料表
-
建表的語法
create table 表名 ( 欄位1 資料型別 列的特徵, 欄位2 資料型別 列的特徵, ... ) go
-
列的特徵包含的內容
- 是否為空(Null):在輸入資料時,資料庫的列允許為空,可以不輸入資料,否者必須輸入。列表是否為空要根據資料庫設計的具體要求決定,對於關鍵列必須禁止為空。
- 是否是標識列(自動編號)
- 是否有預設值:如果資料表的某列在使用者不輸入資料的時候,希望提供一個預設的內容
- 是否為主鍵:主鍵是實體的唯一標識,保證實體不被重複。一個數據表必須有主鍵才有意義
識別符號的特殊說明
- 標識列使用的意義
- 一個數據表儲存的實體,很難找到不重複的列作為主鍵
- SQLServer提供一個“標識列”,也叫“自動增長列”或“自動編號”,它本身沒有什麼具體意義,但我們也可以讓它表示特定意義。
- 標識列的使用方法
- 該列必須是整數型別,或沒有小數位數的精確型別
- 標識種子:標識列的起始大小
- 標識增量:標識列每次遞增的(自動增加)值
- 注意問題
- 有標識列的資料表被刪除某一行時,資料庫會將該行空缺,而不會填補
- 標識列由系統自動維護,使用者既不能自己輸入資料,也不能修改數值
- 標識列可以同時定義為主鍵,也可以不定義為主鍵,根據需要決定
use StudentManageDB
go
if exists(select * from sysobjects where name='Students')
drop table Students
go
create table Students
(
StudentID int identity(100000,1), --學號
StudentName varchar(20) not null, --姓名
Gender char(2) not null, --性別
Birthday datetime not null, --出生日期
StudentIdNo numeric(18,0) not null, --身份證號
Age int not null, --年齡
PhoneNumber varchar(50), --手機號
StudentAddress varchar(500), --地址
ClassId int not null --班級外來鍵
)
go
-- 建立班級表
if exists(select * from sysobjects where name='StudentClass')
drop table StudentClass
go
create table StudentClass
(
ClassId int primary key, --班級編號
ClassName varchar(20) not null
)
go
-- 建立成績表
if exists(select * from sysobjects where name='ScoreList')
drop table ScoreList
go
create table ScoreList
(
Id int identity(1,1) primary key,
StudentID int not null, --學號外來鍵
CSharp int null,
SQLServer int null,
UpdateTime datetime not null --更新時間
)
go
-- 建立管理員表
if exists(select * from sysobjects where name='Admins')
drop table Admins
go
create table Admins
(
LoginId int identity(1000,1) primary key,
LoginPwd varchar(20) not null, --登入密碼
AdminName varchar(20) not null
)
go
資料的基本操作
插入實體
-
插入實體(資料行)語法
insert [into] <表名> [列名] values <值列表>
-
插入實體的SQL語句示例
insert into Students(StudentName,Gender,Birthday,StudentIdNo,Age,PhoneNumber,StudentAddress,ClassId) values('張三','男','1990-01-20',433302198730989090,26,'010-1231231','深圳海上世界',4)
-
注意事項
- 列名個數=對應值的個數
- 非值型別的資料,必須放在單引號內
- 資料值的型別必須與定義的欄位型別一致
查詢實體
-
基本查詢語法
select <列名> from <源表名>[where<查詢條件>]
-
查詢實體的SQL語句示例
select StudentId,StudentName from Students -- 查詢兩個欄位 select * from Students -- *表示查詢所有欄位
T-SQL中的運算子
-
資料庫常用運算子號
運算子 含義 = 等於 > 大於 < 小於 >= 大於或等於 <= 小於或等於 <> 不等於 ! 非 -- 查詢年齡大於22的學號,姓名,性別 select StudentId,StudentName,Gender from Students where Age>=22
更新實體
-
更新實體語法
update <表名> set <列名=更新值>[where <更新條件>]
-
更新實體的SQL語句示例
-- 更新資料 update Students set Age=100, PhoneNumber='12345678910' where StudentID=100011
使用update語句時,一定要注意where條件的配合使用
刪除實體
-
刪除資料表中資料語法
delete from <表名>[where <刪除條件>]
truncate table <表名>
-
刪除實體的SQL語句示例
delete from Students where StudentID=100010 delete from Students truncate table Students
使用刪除語句時,一定要注意where條件的配合使用
delete刪除資料時,要求該記錄不能被外來鍵引用,刪除後標識列繼續增長
truncate刪除資料時,要求刪除的表不能由外來鍵約束,刪除後重新新增資料,刪除後標識列重新編排
truncate比delete執行速度快,而且使用的系統資源和事務日誌資源更少
資料完整性設計與實現
資料完整性的設計
完整性約束的型別
-
常用三種類型的約束保證資料完整性
- 域(列)完整性
- 實體完整性
- 引用完整性
-
主鍵約束與唯一約束
-
新增約束的基本語法
alter table 表名 add constraint 約束名 約束型別 具體的約束說明
-
約束名的取名規則推薦採用:約束型別、約束欄位
- 主鍵(Primary)約束:如 PK_StudentId
- 唯一(Unique Key)約束:如UQ_StudentIdNo
use StudentManageDB go use StudentManageDB go -- 建立主鍵約束 if exists(select * from sysobjects where name='pk_StudentId') alter table Students drop constraint pk_StudentId alter table Students add constraint pk_StudentId primary key(StudentId) -- 建立唯一約束 if exists(select * from sysobjects where name='uq_StudentIdNo') alter table Students drop constraint uq_StudentIdNo alter table Students add constraint uq_StudentIdNo unique(StudentIdNo)
-
檢查約束
-- 建立檢查約束
if exists(select * from sysobjects where name='ck_Age')
alter table Students drop constraint ck_Age
alter table Students add constraint ck_Age check(Age between 18 and 25)
if exists(select * from sysobjects where name='ck_PhoneNumber')
alter table Students drop constraint ck_PhoneNumber
alter table Students add constraint ck_PhoneNumber check(len(PhoneNumber)=11)
預設約束
-- 預設約束
if exists(select * from sysobjects where name='df_StudentAddress')
alter table Students drop constraint ck_StudentAddress
alter table Students add constraint ck_StudentAddress default('地址不詳') for StudentAddress
外來鍵約束
-- 外來鍵約束
if exists(select * from sysobjects where name='fk_ClassId')
alter table Students drop constraint fk_ClassId
alter table Students add constraint fk_ClassId foreign key (ClassId) references StudentClass(ClassId)
資料完整性總結
實體完整性
- 能夠唯一標識表中的每一條記錄
- 實現方式:主鍵、唯一鍵、IDENTITY屬性
域完整性
- 表中特定列資料的有效性,確保不會輸入無效的值
- 實現方式:資料型別限制、預設值、非空值
引用完整性
- 維護表間資料的有效性、完整性
- 實現方式:建立外來鍵,關聯另一表的主鍵
完整資料庫建立過程
graph LR 建庫 --> 建表 --> 主鍵約束 --> 域完整性約束 --> 外來鍵約束插入資料過程
graph LR 驗證主鍵 --> 主外來鍵關係 --> 約束檢查 --> 插入成功常用資料查詢
資料的基本查詢
理解查詢
- 伺服器執行命令,在原始資料表中查詢符合條件的資料,產生一個虛擬表
- 虛擬表是資料組合後的重新展示,而不是原始的物理資料
基本語法構成
-
查詢一般有四個基本組成部分
-
查詢內容,如
select studentId, StudentName, Gender
-
查詢物件,如
from Students
-
過濾條件,如
where Gender='男'
-
結果排序,如
oder by StudentId DESC
-
-
基本查詢語法框架
select <列名> from <表名> [where <查詢條件表示式>] [order by <排序的列名>[ASC或DESC]]
-
查詢全部行和列
-- 查詢全部行和列 select * from Students
-
查詢部分行
查詢部分行 select StudentName,Gender,Birthday,Age from Students where Gender='男' and Age>=22 select StudentName,Gender,Birthday,Age from Students where Age>=22
多個條件使用and連線
-
使用"AS"或使用"="重新命名欄位
-- 自定義命名行 select StudentName as 學生姓名,性別=Gender,年齡=Age from Students
-
加號的使用
-- 列的合併 select 姓名=StudentName,地址和電話=StudentAddress+'['+PhoneNumber+']' from Students
注意:
+
連線的資料型別必需相容- 如果使用
+
連線字元型資料,結果為字串資料的連線 - 如果使用
+
連線數值型資料,結果為數值的和
-
查詢空列
insert into ScoreList(StudentId,CSharp)values(100001, 89) select * from ScoreList where SQLServer is null
-
使用常量列
select StudentName,Gender,Age='28' from Students where Gender='男'
無中生有新增列
-
限制固定行數
select top 5 StudentName,Gender,Birthday from Students
-
返回百分之多少行
select top 20 percent StudentName,Gender,Birthday from Students
-
按多列排序
select StudentId,CSharp as C#,DB=SQLServerDB from ScoreList order by SQLServerDB ASC,CSharp DESC
查詢函式的使用
聚合函式
-
對某一列求總和、對滿足條件的記錄總數求和
select SUM(CSharp) as C#總成績 from ScoreList select 總人數=COUNT(*) from Students
-
求最大值、最小值
select MAX(CSharp) as C#最高分, MIN(CSharp) as C#最低分 from ScoreList
多表之間的資料查詢
內連線查詢
查詢結果是兩個源表中嚴格滿足連線條件的記錄相連
select Students.StudentId,C#成績=CSharp,StudentName,ClassName
from ScoreList
inner join Students on Students.StudentId=ScoreList.StudentId
inner join StudentClass on Students.ClassId=StudentClass.ClassId
where CSharp > 80
需要注意的問題:
- 需要連線的表
- 兩個表連線的條件(主外來鍵)
- 兩個表中相同的公共欄位必需說明來自那個表
左外連線查詢
查詢的結果包括兩個表所有滿足連線條件的記錄,以及左表所有不滿足條件的其他記錄。這些不滿足的左表記錄,在結果的右邊位置,全部填上Null值
select Students.StudentId,StudentName, Gender,C#成績=CSharp
from Students
left outer join ScoreList on Students.StudentId=ScoreList.StudentId
where Gender='男'
右外連線查詢
查詢的結果包括兩個表所有滿足連線條件的記錄,以及右表所有不滿足條件的其他記錄。這些不滿足的右表記錄,在結果的左邊位置,全部填上Null值
select Students.StudentId,StudentName,ClassName
from Students
right outer join StudentClass on Students.ClassId=StudentClass.ClassId
分組查詢與統計
-- 分組查詢
select 班級=StudentClass.ClassName,人數=COUNT(*),C#最高分=MAX(CSharp)
from Students
inner join StudentClass on Students.ClassId=StudentClass.ClassId
inner join ScoreList on ScoreList.StudentId=Students.StudentId
group by ClassName
分組統計篩選--having
select 班級=StudentClass.ClassName,人數=COUNT(*),C#最高分=MAX(CSharp),DB平均分=AVG(SQLServer)
from Students
inner join StudentClass on Students.ClassId=StudentClass.ClassId
inner join ScoreList on ScoreList.StudentId=Students.StudentId
group by ClassName
having AVG(CSharp)>=70 and AVG(SQLServer)>=70
查詢重複資料
-- 在知道那個欄位重複的情況下
select StudentId from ScoreList group by StudentId having COUNT(*)>1
-- 查詢所有的重複的記錄
select * from ScoreList
where StudentId in(select StudentId from ScoreList group by StudentId having COUNT(*)>1)
order by StudentId
-- 其他方法
select * from ScoreList
where (select COUNT(*) from ScoreList s where s.StudentId=ScoreList.StudentId)>1
order by StudentId
分組查詢對比
where
子句:- 從資料來源中去掉不符合其搜尋條件的資料
group by
子句:- 蒐集資料行到各個組中,統計函式為各個組計算統計值
having
子句:- 在分組結果中,去掉不符合其組搜尋條件的各組資料行
資料庫設計
資料庫設計的基本步驟
-
需求分析
-
通過向客戶調研,瞭解客戶的實際需求
-
總結分析客服所需要的管理系統,究竟需要哪些處理資料
以學員管理系統開發為背景,分析系統的基本功能:
- 學院資訊管理模組:資料庫中存放著學員的個人資訊;需要對學員資訊進行管理
- 學員成績管理模組:資料庫中儲存每次學員的考試成績;需要對考試成績進行分析
- 學員班級管理模組:資料庫中儲存著學員的班級資訊
- 課程管理模組:資料庫中存放著課程資訊
-
-
標識物件(實體)並設計物件的屬性
- 物件(或實體)將來對映為資料庫中的資料表
- 物件的屬性,對映為資料表的欄位
- 物件應該有唯一的標識(ID)
注意:
- 需要設計多少實體,取決於需求分析結果,以及設計人員的其他考慮
- 對於實體的多少,以及實體屬性的確定,需要設計人員不斷的根據需要修改
- 實體必須有唯一的標識,如果當前實體屬性沒有能夠作為標識的,需要新增ID
- 實體設計的好壞,關係到後續系統的修改,應當力求做到完善
-
確定物件之間的對映關係
- 物件之間通過外來鍵對映,減少資料冗餘
- 物件之間的對映關係是通過物件的唯一標識建立的
- 常見的物件對映關係有一對一和一對多或者多對多
資料庫設計的檢驗與模型設計
資料庫三正規化
- 正規化:是具有最小冗餘的表結構
- 正規化型別:
- 第一正規化(1st NF - First Normal Form)
- 第二正規化(2nd NF - Second Normal Form)
- 第三正規化(3nd NF - Third Normal Form)
第一正規化(1st NF - First Normal Form)
- 第一正規化:目標是確保每列的原子性(即不可再分的最小資料單元)
- 第一正規化一般都能滿足
- 常見的第一正規化不滿足情況:地址、姓名(有時分開使用)
第二正規化(2nd NF - Second Normal Form)
如果一個關係滿足1NF,並且除了主鍵以外的其他列,都和主鍵列相關,則滿足第二正規化(2NF)