1. 程式人生 > >SQL Server數據庫筆記

SQL Server數據庫筆記

建議 共享 清空 別名 單列 自動 重新 設置 cname

1.主鍵

主鍵的作用:保證表中每條數據的唯一性

特點:主鍵不能重復,不能為空
--主鍵,建議選擇那些一般不會被修改的列
--選擇單列,不選擇多列(不用組合主鍵)
--選擇那些簡單列(整數列(自動編號))

2.char(),nchar(),varchar()之間的區別
--char(10)與varchar(10)的區別
char(10) 固定長度,表示在數據庫中存儲的時候占用10個字節的空間,如果超出10個則報錯,如果不夠10個則用空格補全。
varchar(10) 可變長度,表示該列最多可以存儲10個字節,如果實際存儲不夠10個字節,則會在存儲的時候自動計算一下實際的存儲個數,而動態的改變長度。【節省空間】
--char(10)與nchar(10)的區別
char(10) 可以存儲10個字母或者5個漢字。 用來存儲數據的時候,英文站1個字節,中文站2個字節。
nchar(10) 表示可以存儲10個字母或10個漢字,因為每個字符都是按照unicode方法來存儲的。當使用nchar(10),來存儲數據的時候無論存儲的是中文還是英文都是每個字符占2個。

3. 創建數據庫
--創建一個數據庫
create database School
--刪除數據庫
drop database School
--創建數據庫的時候,指定一些數據庫的相關參數。
create database School
on primary --主數據文件
(
name=‘School‘,
size=10mb,
filename=‘c:school.mdf‘,
filegrowth=10%,
maxsize=100mb
)
--切換數據庫
use school
go

4. 創建表
--創建表
create table Class
(
ClassId int identity(1,1) primary key,
ClassName varchar(50) not null,
ClassDesc varchar(50) not null
)

5.update 數據
--將所有年齡小於20歲的人的年齡都改成19(tage是Class表後加屬性)
update Class set tage = 19 where tage < 20
--將年齡為19歲的並且性別為0的人的姓名兩邊★改為☆
update Class set ClassName =replace (tname,‘★‘,‘☆‘) where tage=19 and tgender=0

6.刪除數據
delete from Class --刪除所有數據 自動編號沒有恢復到默認值 可以根據條件來刪除
truncate table Class --重新設置了自動編號 刪除只能一次性都清空,不能根據條件來刪除 清除速度(性能)比delete語句快的多

delete form Class where tage = 19 or tage is null --刪除19歲或者空值
刪除重復數據只保留一條(id最小的一條),刪除表中多余的重復記錄,重復記錄是根據單個字段(peopleId)來判斷,只留有rowid最小的記錄
delete from people
where peopleName in (select peopleName from people group by peopleName having count(peopleName) > 1)
and peopleId not in (select min(peopleId) from people group by peopleName having count(peopleName)>1)

7.條件查詢,模糊查詢
--查詢數學沒有及格的學生的學號
select
fid as 學號,
fmath as 分數
from MyStudent where fmath<60
--查詢年齡在20-30歲之間的男學生
select
fname as 姓名 from MyStudent where fage between 20 and 30 and fgender=‘男‘
--查詢班級id 1 2 3 的所有學生
select * from MyStudent where classid in (1,2,3)
--查詢所有姓趙的同學 (通配符%表示:任意多個任意字符)
select * from MyStudent where fname like ‘趙%‘
--查詢出姓名中只要包含一個‘民’字即可。
select * from MyStudent where fname like ‘%民%‘
--查詢所有姓趙的同學,並且姓名字數是3個
--通配符 _ :表示任意的單個字符。
select * from MyStudent where fname like ‘趙__‘
select * from MyStudent where fname like ‘趙%‘ and len(fname)=3
--查詢出姓名中包含‘民’或‘用’的同學
--通配符[]:表示中括號中的任意個字符,只選一個匹配
--通配符 ^a :表示除了a這個字符都行。
select * from MyStudent where fname like ‘%[民用]%‘

8.聚合函數
--查詢數學成績最高低分
select max(fMath) as 數學成績最高分 from MyStudent
select min(fMath) as 數學成績最低分 from MyStudent
--平均分(計算平均分的時候對空值不處理)
select avg(fMath) as 平均分 form MyStudent
--求數據記錄中的總條數(總人數)
select count(*) as 班級總人數 from MyStudent
--分數評級
--90以上 優秀
--80以上 良好
--70以上 中
--70以下 差
select chengji,
評級=
case
when shuxue >= 90 then ‘優秀‘
when shuxue >= 80 then ‘良好‘
when shuxue >= 70 then ‘中‘
else ‘差‘
end
from Student

9.null 問題
--請查詢出學生表中所有數學成績為null的人的信息
select * from MyStudent where fMath is null
--查詢所有fmath為非null的值
select * from MyStudent where fMath is not null
--null值與任何數據運算後得到的還是null值。
update MyStudent set fage=fage+1 where fid=1

10.分組group by
--統計出mystudent表中,男女同學的個數
select
fgender as 性別, --這時,count(*)統計的是每一組的記錄條數, 不是總條數
count(*) as 人數
from MyStudent group by fgender --先執行group by語句分組,分完組在統計每 組個數。 分出來幾個組,那麽count(*)就統 計幾次

--查詢班級的男同學的人數大於2的信息
--having是group by的條件對分組後的數據進行篩選(與where類似,都是篩選,只不過having是用來篩選分組後的組的)
select
classid as 班級號,
count(*) as 班級人數
from TblStudent
where fgender=‘男‘
group by classid
having count(*)>2
語句執行順序
select
--distinct / top 之類的關鍵字
fgender as 性別, --5》選擇列
count(*) as 人數
from MyStudent --1》先從表中拿到數據
where fage>30 --2》從MyStudent的數據中篩選出所有年齡大於30歲的任的信息
group by fgender --3》按照性別分組,分完組得到一個新的結果集
having count(*)>500 --4》基於分組以後的結果集,然後再篩選,篩選出那些組中記錄大於500的組
order by 人數 asc --6》最後把顯示出來的結果排序
--語句執行順序
from > where > group by > having > select > order by

11.日期函數
--請查詢出所有入職一年以上的員工信息
select * from TblStudent
where dateadd(year,1,tsday)<getdate()

--計算兩個時間差
--查詢90年距今是多少年
select datediff(year,‘1990-9-9‘,getdate())

--查詢一個日期的特定部分
select year(getdate())
select datepart(year,getdate())
--輸出所有數據中通話時間最長的5條記錄。
select top 5 *,‘通話時長(秒)‘=datediff(second,Startdatetime,Enddatetime) from Calltecords order by datediff(second,Stardatetime,enddatetime) desc

12.子查詢
--把一個查詢結果作為另外一個查詢的查詢源
select * from (select * from Student where tbage between 3 and 5)
as ct where tbname=5 --ct是新創的表名
--把另外一個查詢的結果作為當前查詢的條件來使用。
--子查詢中=、!= 、< 、> 、<= 、>=之後只能返回單個值,如果多個值就會報錯
--解決辦法 可以用in 代替
select * from Student
where tbage in(select tbage from Student where tbname=3)
select * from Student
where tbage=(select tbage from Student where tbname=3)
子查詢分頁
1.顯示第一頁的數據
分頁查詢的時候首先是將數據排序
select * from Student order by id desc
第一頁 顯示5條數據
select Top 5 * from Student order by id desc
第二頁
select top 5 * from Student
where id not in (select top 5 * from Student order by id desc)
order by id desc
第三頁
select top 5 * from Student
where id not in (select top (2*5) * from Student order by id desc)
order by id desc
開窗函數分頁
--第七頁數據 每頁5條數據
--over屬於開窗函數
select * from
(
select * ,row_number() over( order by id desc) as paixu from Student
) as tbl
where tbl.paixu between 6*5+1 and 7*5

13.連表查詢
--查詢所有學生的姓名、年齡及所在班級 (班級在另一個表中)
--當多個列在不同的表中時,要跨表查詢,所以一般可以使用inner join
--tc ts是對表名起的別名
select
ts.tsname,
ts.tsage,
tc.tclassname
from TblStudent as ts
inner join TblClass as tc on ts.tsclassid=tc.tclassid(只查詢兩個表中都有的數據)
--full join 是查詢所有的數據(沒有的為空)
--左外聯接(左聯接)
--查詢沒有參加考試的學生的姓名與編號
--把左表(left join 關鍵字左邊的表)中的全部記錄都顯示出來,對於那些在右表中能找到匹配的記錄,顯示對應匹配數據,對於那些右表中找不到匹配的記錄顯示為null
select
ts.tsid,
ts.tsname,
TblScore.*
from TblStudent as ts
left join TblSore.tsid=ts.tsid
--右外聯接
--表示要將右表(right join 右邊的表)中的所有數據都顯示,左表中只顯示那些匹配的數據。
select
ts.tsid,
ts.tsname,
TblScore.*
from TblStudent as ts
right join TblSore.tsid=ts.tsid
--右外聯與左外聯都是先將匹配的數據找到,然後再將那些沒有匹配的數據添加進來,(註意:不是一起查詢出來的,有先後順序)
--練習:查詢所有學生(參加和未參加的考試)的學生姓名、年齡、成績,如果沒有參加考試顯示缺考,如果小於english或者math 小於60分顯示不及格
select
ts.tsname,
ts.tsage,
tscore.tsid,
case
when tscore.tenglish is null then ‘缺考‘
else convert(varchar(10),tscore.tenglish)
end as 英語成績,
case
when tscore.tmath id null then ‘缺考‘
else convert (varchar(10),tscore.tmath)
end as 數學成績,
是否報考=
case
when tscore.tscoreid is null then ‘是‘
else ‘否‘
end
from TblStudent as ts
left join TblScore as tscore on ts.tsid=tscore.tsid

14.視圖
視圖本身並不存儲數據,只是存儲的查詢語句,如果把真實表中的數據修改後,則通過視圖查詢到的結果也變了。
視圖的目的是方便查詢,所以一般情況下不能對視圖進行增刪改查
--在視圖中的查詢語句,必須為每一列創建一個列名
create view vw2
as
select
tsname,
case
when tsage>13 and tsage<=16 then ‘少年‘
when tsage>50 then ‘老年‘
else ‘青壯年‘
end as 稱呼
from TblStudent
--在視圖中不能使用order by語句。除非:另外還指定了top 或for xml
--錯誤
create view vw3
as
select * from TblStudent order by tsage desc
--正確
create view vw3
as
select top 3 * from TblStudent order by tsage desc

15.聲明變量與使用
--局部變量
--聲明變量
declare @name varchar(10)
declare @age int
--賦值
set @name=‘yhz‘
set @age=17
--輸出值
print @name
print @age
--使用set與select為變量賦值的區別
declare @rcount int
set @rcount=(select count(*) from TblStudent)
print @rcount
declare @rcount int
select @rcount=count(*) from TblStudent
print @rcount

--全局變量
print @@language
print @@version
print ‘aaa‘+100
--通過判斷@@error變量中是否不為0,就可以判斷上一條sql語句執行是否出錯了
--如果@@error為0,表示上一條sql語句執行沒出錯,如果@@error不為0,則表示上一條sql語句出錯了。
print@@error
--通過while計算1-100之間所有奇數的和
--聲明變量並初始化
declare @sum int=0
declare @i int =1
while @i<=100
begin
if @i%2<>0
begin
set @sum=@sum+@i
end
end
print @sum

16.事務
事務有四個屬性:原子性 一致性 隔離性 持久性
原子性:對於數據修改,要麽全都執行,要麽全都不執行
一致性:當數據完成時,數據必須處於一致狀態
隔離性:對數據進行修改的所有並發事務時彼此隔離的。這表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務
永久性:事務完成後,他對數據庫的修改被永久保持,事務日誌能夠保持事務的永久性
--打開事務
begin transaction
--提交事務
commit transaction
--回滾事務
rollback transaction

--賬戶A給賬戶B轉賬 當一方出問題時,兩個語句都不執行
begin tran
declare @sum int=0
update bank set balance =balance-1000 where cid=‘0001‘
set @sum=@sum+@@error
update banl set balance =balance+1000 where cid=‘0002‘
set @sum=@sum+@@error
if @sum<>0
begin
rollback tran
print ‘回滾‘
end
else
begin
commit tran
print ‘提交了‘
end

17.存儲過程
--創建一個自定義的存儲過程
create proc usp_HelloWorld
as
begin
print ‘hello world‘
end
--輸出存儲過程
exec usp_HelloWorld
--創建一個存儲過程計算兩個數的和
create procedure usp_Add
@num1 int,
@num2 int
as
begin
print @num1+@num2
end
--輸出值
exec usp_Add 100,230

--存儲過程中的參數的問題
--存儲過程如果有參數,則調用的時候必須為參數賦值
exec usp_Add --不傳參數則報錯

--第二個參數如果用戶不傳,則有一個默認值
create procedure usp_Add
@num1 int,
@num2 int 1000 --為存儲過程的參數設置默認值
as
begin
print @num1+@num2
end
--創建分頁存儲過程
create proc usp_PageBum
@pageSize int, --每頁顯示的數量
@pageIndex int --第幾頁
as
begin
select * from (select *,row_number()over (order by CityID asc)as num from S_City )as s
where s.num between (@pageIndex -1)*@pageSize +1 and @pageIndex *@pageSize
end
--查詢第5頁內容每頁顯示10條數據
exec usp_PageBum 10,5
--刪除一個存儲過程
drop proc usp_Add

18.觸發器
盡量避免在觸發器中執行耗時操作,因為觸發器會與sql語句認為在同一個事務中(事務不結束,就無法釋放鎖)
--創建插入數據觸發器
create trigger tri_Teacher_insert_after
on Teacher after insert
as
begin
declare @id int
declare @name varchar(10)
declare @phone int
declare @mail varchar(50)
select @id=tcid,@name=tcname,@phone=tcphone,@mail=tcmail from inserted
print @id
print @name
print @phone
print @mail
end
--插入數據
insert into Teacher values(‘網名好‘,‘12352536‘,‘[email protected]‘)

--創建刪除數據觸發器
--不能有主鍵
create trigger tri_Teacher_after
on Teacher after delete
as
begin
insert into TeacherBak
select * from deleted
end
--刪除數據
--sql server中的觸發器是表級觸發器,無論刪除多少行或者插入多少行,只觸發一次
--是按語句來觸發的,每次執行一次語句,觸發一次觸發器
delete from Teacher where tcid>18

19.遊標
--1.定義遊標
declare cur_Student cursor fast_forward for select * from Student
--2.打開遊標
open cur_Student
--2.1 對遊標的操作
--將每條數據讀取並輸出
--2.1.1將遊標向後移動一條
fetch next from cur_Student
--將遊標循環向後移動,直到末尾
while @@fetch_status=0
begin
fetch next from cur_Student
end
--3.關閉遊標
close cur_Student
--4.釋放資源
deallocate cur_Student

20.(補充)全局臨時表,局部臨時表
局部臨時表:表名以#為開頭。只在當前會話中有效,不能跨連接訪問。如果直接在連接會話中創建,則當前連接斷開後刪除,如果是在存儲過程中創建的,則存儲過程執行完畢後刪除
全局臨時表:表名以##為開頭。多個會話可共享全局臨時表。當創建全局臨時表的會話斷開,並且沒有用戶正在訪問全局臨時表時刪除

21.(補充)約束
--刪除一列(EmpAddress列)
alter table Class drop column EmpAddress
--增加一列(增加一列EmpAddr varchar(1000))
alter table Class Add EmpAddr varchar(1000)
--修改一下Emp 的數據類型(varchar(200))
alter table Class alter column Emp varchar(200)
--為EmpId增加一個主鍵約束
alter table Class add constraint PK_Class_EmpId primary key(EmpId)
--為EmpName增加一個唯一約束
alter table Class add constraint UQ_Class_EmpName unique(EmpName)
--為性別增加一個默認約束,默認為男
alter table Class add constraint DF_Class_EmpGender default(‘男‘) for EmpGender
--為年齡增加一個檢查約束,年齡必須在1—120歲之間(包含)
alter table Class add constraint CK_Class_EmpAge check(EmpAge>=0 and EmpAge<=120)
--增加外鍵約束,表Class中有一列EmpDeptId引用Student表中的DeptId
alter table Class add EmpDeptId int not null
alter table Student add constraint PK_Student_DeptId primary key(DeptId)
alter table Class add constraint FK_Class_Student foreign key(EmpDeptId)
references Student(DeptId)

--一條語句刪除多個約束,約束名用 逗號 隔開
alter table Class drop constraint
PK_Student_DeptId,
FK_Class_Student,
CK_Class_EmpAge

--用一條語句為表增加多個約束
alter table Class add
constraint PK_Student_DeptId primary key(DeptId),
constraint CK_Class_EmpAge check(EmpAge>=0 and EmpAge<=120),
add constraint DF_Class_EmpGender default(‘男‘) for EmpGender

SQL Server數據庫筆記