數據庫操作 總結

本人錄製技術視頻地址:https://edu.csdn.net/lecturer/1899 歡迎觀看。

1.數據庫中關於字段加值的處理

update T_Teacher set tSalary=tSalary+2000 where tSex='true';

這種情況,必須寫成 tSalary = tSalary + 2000, 因爲是將數據庫中原來的值進行了修改。

select tSalary+2000 ,tName from T_Teacher

而這種情況,是取得數據庫中的數據,並將tSalary值加2000,顯示出來,而數據庫中原來的值並沒有被改變 

 

2.備份表時,約束不會備份 

1、  將數據和結構備份了下來 

select * into 新表名 from 源表名

2、  將表的結構備份了下來 

select * into 新表 from 源表 where 1>2


3.drop,delete與truncate的區別:

drop是將整個表刪除了(表的內容與表的結構都被刪除了)

delete是將表的內容刪除了,表的結構還在,當下次再插入數據的時候,id從上次最大的id+1開始算起

truncate也是將表的內容刪除了,表的結構還在,但下次再插入數據的時候,id會從1開始重新計算。但是,它不會將數據記錄到日誌文件,一旦刪除,就無法恢復了(慎用)! 


4.表中列的操作修改表(修改表的同時不能添加約束,修改完成之後可以添加約束):

刪除一列:  alter table 表名 drop column 列名

增加一列:  alter table 表名 add 列名 類型

修改數據類型:  alter table 表名 alter column 列名 類型 


5.數據庫中的類型轉化:

cast(expression as date_type) 或者 convert(date_type,expression) 


6.DISTINCT是對整個結果集進行數據重複抑制,而不是針對每一列

如select distinct FDepartment,FSubCompany from T_Employe是指當FDepartment,FSubCompany兩個字段的內容完全相同時,才一致;有一列相同也沒有關係。


7.UNION使用的兩個基本原則:1、每個結果集必須有相同的列數。2、每個結果集的列必須類型相容。

其中UNION將兩表合併,並且沒有重複的行出現,而UNION ALL是直接將兩表合併,不考慮重複問題。

例:查詢每位正式員工的信息,包括工號,工資,並且在最後一行加上所有員工工資合計

select FNumber ,FSalary from T_Employee UNION select '工資合計',sum(FSalary) from T_Employee


8.row_number()函數可以計算每一行數據在結果集中的行號(從1開始計數)

用法:row_number() over(排序規則),如下列,可以直接得到按工資降序排列的所有序號:

select ROW_NUMBER() over(order by FSalary desc),FNumber,FName,FSalary,FAge from T_Employee

row_number()不能用在where子句中!

Example:查詢工資按降序排列的第6到第8名的具體情況。

Method One:(子查詢)

select top 3 * from T_Employee where FNumber not in
(select top 5 FNumber from T_Employee order by FSalary desc )
order by FSalary desc

Method Two: (使用row_number(),推薦)

select * from
(select *,ROW_NUMBER() over(order by FSalary desc) as rownum from T_Employee) as a
where a.rownum>=6 and a.rownum<=8


9.isnull函數的使用(將FName爲null的地方用佚名取代)

select isnull(FName,'佚名') as 姓名 from T_Employee   如果FName是null,就用'佚名'替代,如果不是空,就直接取FName的值 

 

10.Group by 與 Order by

1、沒有出現在group by 子句中的列是不能放到select語句後的列名列表中的(聚合函數除外)

2、聚合函數是不可以出現在where子句中的,只能在group by語句後,把聚合函數放在having子句中

3、where是對原始的數據進行過濾,having是對分組以後的數據進行過濾的

4、當出現group by 和order by混合使用時,一般先分組再排序 


11.時間函數

1、得到當前日期: 

select CONVERT(varchar(50),GETDATE(),101) as CurrentDay

如 結果:06/05/2011

2、得到當前時間 

select CONVERT(varchar(50),GETDATE(),108) as CurrentTime

如 結果:20:17:31 

3、dateadd 

select FBirthday,DATEADD(YEAR,3,FBirthday) as threeyrs,
DATEADD(QUARTER,20,FBirthday) as ttqutrs, DATEADD(MONTH,68,FBirthday) as sxtmonths, DATEADD(WEEK,-1000,FBirthday) as thweeik from T_Person

4、datediff

select FRegDay,FBirthday,DATEDIFF(WEEK,FBirthday,FRegDay) from T_Person

5、datepart,返回日期的指定格式

select FBirthday,datepart(WEEKDAY,FBirthday),FRegDay,datepart(WEEKDAY,FRegDay) from T_Person

12.Case函數 

1、如下表(條件是離散值的情況)


輸出下表形式的格式:


select FName, (
case [Level] --Level是數據庫中的關鍵字,用它作爲字段的時候,要用[]括起來 when 1 then '普通會員'
when 2 then '高級會員'
when 3 then 'VIP'
end
) as 會員級別
from T_Level

2、條件是在一個範圍的情況 

select FName,
(
case
when FSalary<2000 then 'Lower'
when FSalary>=2000 and FSalary<=5000 then 'Just soso' else 'Upper'
end
) as 收入水平 from T_Employee

3、表內容: 


輸出下表形式的格式:


select number, (
case
when amount>=0 then amount else 0 end
) as 收入, (
case
when amount<0 then ABS(amount) else 0 end
) as 支出 from T_Amount

4、表內容:


輸出下表形式的格式:


select Name, sum
(
case Score
when '勝' then 1 else 0 end
) as 勝, sum
(
case Score
when '負' then 1 else 0 end
) as 負
from T_Compare group by Name

5、表內容:


輸出下表形式的格式:


select id, sum
(
case 科目
when '語文' then 成績 else 0 end
) as 語文, sum
(
case 科目
when '數學' then 成績 else 0 end
) as 數學, sum
(
case 科目
when '英語' then 成績 else 0 end
) as 英語 from T_Class group by id

13. 表連接

1、內連接--常用!

--將學生表與學生成績表聯合起來(以學生的id作爲連接橋樑)輸出格式如下: 學生姓名、性別、年齡、班級、英語成績、數學成績 

select st.sname as 學生姓名,
(
--將0,1 數字表示的性別信息,用男、女代替
case st.sgender
when 0 then '女' else '男'
end
) as 性別,
st.sage as 年齡, --使用子查詢實現 (
select cname from T_Class201219 where cid=st.sclass ) as 班級,
--表連接實現
sc.scEnglish as 英語成績,
sc.scMath as 數學成績
from T_Student201219 as st [inner] join T_Score201219 as sc on st.sid=sc.scStudent

//注:輸出結果並不是所有學生的信息,因爲有的學生在T_Score201219表中都沒有記錄(爲null),所以只能連接有記錄的。 

2、左連接

顯示所有學生的信息,學生在T_Score201219表中沒有記錄的,成績項全用null代替 

select st.sid,st.sName,sc.scEnglish,sc.scMath
from T_Student201219 as st left join T_Score201219 as sc on st.sid=sc.scStudent

同理:右連接,即學生在T_Student201219表中沒有記錄的,學生信息項全用null代替


14.綜合例子1:

創建一張表,記錄電話呼叫員的工作流水,記錄呼叫員編號、對方號碼、通話開始時間、通話結束時

間。建表、插數據等最後都自己寫SQL語句。 

CREATE TABLE [CallRecords] (
[Id] [int] NOT NULL identity(1,1),
[CallerNumber] [nvarchar](50), --三位數字,呼叫中心員工編號(工號) [TelNum] [varchar](50),
[StartDateTime] [datetime] NULL,
[EndDateTime] [datetime] NULL --結束時間要大於開始時間,默認當前時間
)
--主鍵約束
alter table [CallRecords]
add constraint PK_CallRecords primary key(id)
--檢查約束
alter table [CallRecords]
add constraint CK_CallRecords check(CallerNumber like '[0-9][0-9][0-9]') alter table [CallRecords]
add constraint CK_CallRecords_EndDateTime check(EndDateTime > StartDateTime)
--默認約束
alter table [CallRecords]
add constraint DF_CallRecords default(getdate()) for EndDateTime
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('001', '0208888888', CAST(0x00009DAF00A4CB80 AS DateTime), CAST(0x00009DAF00A62E94 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('001', '0208888888', CAST(0x00009DB000D63BC0 AS DateTime), CAST(0x00009DB000D68DC8 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('001', '89898989', CAST(0x00009DB000E85C60 AS DateTime), CAST(0x00009DB000E92F50 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('002', '98987676', CAST(0x00009DB2015BB7A0 AS DateTime), CAST(0x00009DB2015C4DA0 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('002', '02188839389', CAST(0x00009DA4014C9C70 AS DateTime), CAST(0x00009DA4014E0308
AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('001', '767676766', CAST(0x00009DB400DAA0C0 AS DateTime), CAST(0x00009DB400DD5FE0 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('003', '0227864656', CAST(0x00009DB200B9AB40 AS DateTime), CAST(0x00009DB200B9FC1C AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('003', '676765777', CAST(0x00009DB8014042B8 AS DateTime), CAST(0x00009DB80141804C AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('001', '89977653', CAST(0x00009D9A00FB9898 AS DateTime), CAST(0x00009D9A00FE6118 AS DateTime));
INSERT [dbo].[CallRecords] ([CallerNumber], [TelNum], [StartDateTime], [EndDateTime]) VALUES ('004', '400400400', CAST(0x00009D9A00FB9898 AS DateTime), CAST(0x00009D9A00FE6118 AS DateTime));

要求:
1、輸出所有數據中通話時間最長的5條記錄

2、輸出所有數據中撥打長途號碼(對方號碼以0開頭)的總時長

3、輸出本月通話總時長最多的前三個呼叫員的編號

4、輸出所有數據的撥號流水,並且在最後一行添加總呼叫次數

1)記錄呼叫員編號、對方號碼、通話時長

2)......

3)彙總【市內號碼總時長】【長途號碼總時長】 

Answer 1.

select top 5 * from CallRecords order by DATEDIFF(S,StartDateTime,EndDateTime) desc

Answer 2.

select SUM(DATEDIFF(S,StartDateTime,EndDateTime)) from CallRecords where TelNUm like '0%'

Answer 3.

select CallerNumber from CallRecords
where convert(int,datepart(month,StartDateTime))=7 --表示7月份 group by CallerNumber
order by SUM(DATEDIFF(S,StartDateTime,EndDateTime)) desc

Answer 4.

select CallerNumber as 呼叫員編號,TelNum as 對方號 碼,DATEDIFF(s,StartDateTime,EndDateTime) as 通話時長
from CallRecords union
select '彙總', convert( varchar(50),
(
select SUM(DATEDIFF(s,StartDateTime,EndDateTime)) from CallRecords
where TelNum not like '0%'
) ),
(
select SUM(DATEDIFF(s,StartDateTime,EndDateTime))
    from CallRecords
where TelNum like '0%' )

15. 綜合例子2:

create table T_Departments (
department_id int identity(1,1) primary key,
department_name nvarchar(50) )
create table T_Employees (
employee_id int identity(1,1) primary key, employee_name nvarchar(50),
employee_job nvarchar(50),
manager nvarchar(50),
salary int,
department_id int )
insert into T_Departments values('行政部') insert into T_Departments values('財務部') insert into T_Departments values('人資部') insert into T_Departments values('技術部')
insert into T_Employees values('jason','PE','Peter',3000,4) insert into T_Employees values('nina','clerk','Walter',4000,3) insert into T_Employees values('quiet','clerk','walter',3500,3) insert into T_Employees values('ada','clerk','walter',2800,3) insert into T_Employees values('brenda','clerk','walter',4200,3) insert into T_Employees values('wallen','ME','jarry',5000,2) insert into T_Employees values('daniel','MQ','Johnson',3100,1) insert into T_Employees values('crystal','ME','jarry',5600,2) insert into T_Employees values('linda','MQ','Johnson',4100,1) insert into T_Employees values('lily','MQ','Johnson',6200,2) insert into T_Employees values('sunny','clerk','jarry',4700,2) insert into T_Employees values('ken','clerk','Johnson',2600,1)
insert into T_Employees values('wander','clerk','jarry',3100,2) insert into T_Employees values('bill','clerk','Johnson',5300,1) insert into T_Employees values('judy','clerk','Johnson',6800,2) insert into T_Employees values('billy','clerk','Peter',8000,4) insert into T_Employees values('alla','clerk','Peter',2000,4) insert into T_Employees values('Peter','Header',null,9200,4) insert into T_Employees values('Walter','Header',null,13800,3) insert into T_Employees values('jarry','Header',null,8200,2) insert into T_Employees values('Johnson','Header',null,7800,1)

1、列出employees表中各部門的部門號,最高工資,最低工資

select department_Id,max(salary) as 最高工資,min(salary) as 最低工資 from T_Employees group by department_Id

2、列出employees表中各部門employee_job爲'clerk'的員工的最低工資,最高工資

select department_Id,max(salary) as 最高工資,min(salary) as 最低工資 from T_Employees where employee_Job='clerk'
group by department_Id

3、對於employees中最低工資小於1000的部門,列出employee_job爲'clerk'的員工的部門號,最低工資,最高工資

select department_Id,max(salary) as 最高工資,min(salary) as 最低工資 from T_Employees where department_Id in (select department_Id from T_Employees group by department_Id
having min(salary) < 3000) and employee_Job='clerk' group by department_Id

4、根據部門號由高而低,工資有低而高列出每個員工的姓名,部門號,工資

select employee_Name as 姓名,department_Id as 部門號,salary as 工資 from T_Employees order by department_Id desc,salary asc

5、列出'張三'所在部門中每個員工的姓名與部門號

select employee_Name as 姓名,department_Id as 部門號 from T_Employees where department_Id=(select department_Id from T_Employees where employee_Name='lily')
6、列出每個員工的姓名,工作,部門號,部門名

select e.employee_Name as 姓名,e.employee_Job as 工作,e.department_Id as 部門號, d.department_Name as 部門名
from T_Employees as e join T_Departments as d on e.department_Id=d.department_Id

7、列出employees中工作爲'clerk'的員工的姓名,工作,部門號,部門名

select e.employee_Name as 姓名,e.employee_Job as 工作,e.department_Id as 部門號, d.department_Name as 部門名
from T_Employees as e join T_Departments as d on e.department_Id=d.department_Id where e.employee_Job='clerk'

8、對於employees中有管理者的員工,列出姓名,管理者姓名(管理者外鍵爲manager)

select employee_Name as 姓名,manager as 管理者姓名 from T_Employees where manager is not null

9、對於departments表中,列出所有部門名,部門號,同時列出各部門工作爲'clerk'的員工名與工作

select d.department_Name as 部門名,d.department_Id as 部門號,e.employee_Name as 員工名, e.employee_Job as 工作
from T_Employees as e join T_Departments as d on e.department_Id = d.department_Id where e.employee_Job='clerk'

10、對於工資高於本部門平均水平的員工,列出部門號,姓名,工資,按部門號排序

select department_Id as 部門號, employee_Name as 姓名,salary as 工資
from T_Employees as a
where a.salary>(select avg(salary) from T_Employees as b where a.department_Id = b.department_Id)
order by department_Id

11、對於employees中工資高於本部門平均水平,人數多與1人的,列出部門號,人數,按部門號排序

select department_Id as 部門號,count(*) as 人數
from T_Employees as a
where a.salary >(select avg(salary) from T_Employees as b where
a.department_Id=b.department_Id) group by department_Id
having count(*)>1
order by department_Id

12、對於employees中低於自己工資至少5人的員工,列出其部門號,姓名,工資,以及工資少於自己的人數 

select department_Id as 部門號, employee_Name as 姓名,salary as 工資,
(select count(b.employee_Id) from T_Employees as b where a.salary>b.salary) as 人數 from T_Employees as a
where (select count(b.employee_Id) from T_Employees as b where a.salary>b.salary)>=5

16.約束: 主鍵約束、唯一約束、檢查約束、默認約束、外鍵約束

手動添加約束:

唯一約束:右擊表-->設計-->索引/鍵-->然後對對應的內容進行設置即可(命名方式:UQ_表名_字段名)唯一約束的目的:即字段中當已經存在了某項內容,當繼續添加時,則不允許。

檢查約束:右擊表-->設計-->check約束-->在表達式中填寫相關約束條件(命名方式:CK_表名_字段名)檢查約束的目的:使指定字段滿足一定的條件,當不滿足的話,則不允許輸入。

外鍵約束:右擊外鍵表-->設計-->關係-->設置對應的主鍵表及外鍵字段(命名方式:FK_外鍵表_主鍵表_外鍵字段)
注:含有外鍵字段的那張表就是外鍵表,另一張就是主鍵表外鍵約束的目的:建立外鍵表與主鍵表的一種約束關係。當插入數據的時候,必須先在主鍵表中進行插入,然後外鍵表根據主鍵表的id才能進行相應的插入工作;當進行表刪除的時候(如果外鍵表沒有對主鍵表的記錄進行引用,可以直接刪除主鍵表中的那項記錄),但外鍵表對主鍵表中的記錄有引用時,必須先刪除外鍵表對應的記錄(即刪除了外鍵表對主鍵表的引用),再刪除主鍵表相關的記錄。

代碼實現約束:

Situation One:表已經創建好
唯一約束:alter table 表名 add constraint UQ_表名_字段名 unique(字段名)

檢查約束: alter table 表名 add constraint CK_表名_字段名 check(字段名)

默認約束: alter table 表名 add constraint DF_表名_字段名 default(默認值) for 字段名

外鍵約束:alter table 外鍵表 add constraint FK_外鍵表_主鍵表_外鍵表中的外鍵名 foreignkey(外鍵表中的外鍵名) references 主鍵表(主鍵表中的id)

刪除表中的約束:alter table 表名 drop constraint 約束形式_表名_字段名

Situation Two: 在創建表的時候,一起添加約束,Example 

create table TT
(
studentId int identity(1,1) primary key, [name] nvarchar(10) unique not null,
age int check(age>=18 and age<=40) default(20)
)

約束的例子:
--Teacher表中
--tId 主鍵
--tSex 控制只能是男 女,默認男
--tAge 在30-40之間 默認30

方法一:先建表,再給約束 

create table T_Teacher (
tId int identity(1,1), tSex nvarchar(10), tAge int
)
alter table T_Teacher
add
constraint PK_T_Teacher_tId primary key(tId),
constraint CK_T_Teacher_tSex constraint DF_T_Teacher_tSex constraint CK_T_Teacher_tAge constraint DF_T_Teacher_tAge

方法二:建表的同時添加約束 

create table T_Teacher
(
tId int primary key,
tSex nvarchar(10) check(tSex='男' or tSex='女') default('男'), tAge int check(tAge>=30 and tAge<=40) default(30)
)

17. 視圖

視圖是一張虛擬表,它表示一張表的部分數據或多張表的綜合數據,其結構和數據是建立在對錶的查詢基礎上視圖在操作上和數據表沒有什麼區別,但兩者的差異本質是不同的:數據表是實際存儲記錄的地方,然而視圖並不保存任何記錄,它存儲的實際上是查詢語句相同的數據表,根據不同用戶的不同需求,可以創建不同的視圖(不同的查詢語句)視圖的目的是方便查詢,所以一般情況下不能對視圖進行增刪改

創建視圖:
create view vw_視圖名as
SQL語句

執行視圖:
select * from vw_視圖 


18.局部變量與全局變量 

局部變量(最好使用set給變量賦值):聲明: declare @變量名 數據類型賦值: set @變量名 = 值

select @變量名=值(一般爲單值) from ...打印結果: print @變量名

-----------------------------------
全局變量(系統變量):
必須以標記@@作爲前綴
Example: @@error 表示所有執行的SQL語句,最後一次執行是否出現了錯誤如果最後一次執行的語句沒有錯誤,則@@error值爲0 


19.if else 語句

if 條件

begin

end

else

begin

end

Example1[查找是否存在叫夢琪的人,有就打印出此人信息,沒有則打印'查無此人']: 

if (select count(*) from MyStudent where FName='夢琪')>0
begin
select * from MyStudent where FName='夢琪'
end else
begin
print '查無此人'
end

Example2[計算english平均分,如果平均分超過60,輸出成績最高的三個學生的成績,否則輸出後三名的學生] 

declare @avgScore float
set @avgScore=(select avg(english) as 平均分 from score) print '平均分是:'+convert(varchar(50),@avgScore) if(@avgScore>=60)
begin
select top 3 * from score order by english desc
end else
begin
select top 3 * from score order by english asc
end

20. while語句 

Example1:計算1+2+...+100的值 

declare @index int
declare @sum int
set @index=1
set @sum=0 while(@index<=100) begin
       set @sum=@sum+@index
set @index=@index+1 end
print @sum

Example2:如果不及格的人超過半數(考試題出難了),則給每個人增加2分,循環加,直到不及格的人數少於一半。 

declare @losers int
set @losers=(select count(*) from score where english<60) declare @halfCount int
set @halfCount=(select ceiling(count(*)/2.0) from score) while(@losers<@halfCount)
begin
update score set english=english+2 where english<60
set @losers=(select count(*) from score where english<60) end


21.事物[Transaction](就是由多個sql語句組成,必須作爲一個整體執行!要麼都執行,要麼都不執行): 

事物語法步驟:
開始事物:begin transaction

事物提交:commit [transaction]

事物回滾:rollback [transaction]

【銀行轉賬問題】--沒有用事務範例(建表並添加約束,編號0001向0002轉賬,自己錢沒有少,但0002的錢多了!) 

create table bank
(
cId char(4) primary key,
balance money, --餘額
)
alter table bank
add constraint CH_balance check(balance >=10)
go
--delete from bank
insert into bank values('0001',1000) insert into bank values('0002',10) go
update bank set balance=balance-1000 where cid='0001' update bank set balance=balance + 1000 where cid='0002'

執行update語句之後,編號爲0001的金額不會少,因爲它受check約束,只有當餘額至少爲爲1100的時候,才能進行轉賬業務,所以他轉不了,但0002的不會受限制,所以還是增加了1000!

使用事務解決上面的問題:

Method One(可以實現,結果正確,但第一句update語句還是會報錯,有check約束): 

begin transaction
declare @myError int
set @myError=0 //要初始化,不然默認值爲null
update bank set balance=balance-100 where cid='0001' set @myError=@myError+@@error
update bank set balance=balance + 100 where cid='0002' set @myError=@myError+@@error
if(@myError=0)
begin commit
end else
begin rollback
end

Method Two(用try--catch捕獲異常!如果update語句沒有問題,則正常執行;否則,打印異常) 

begin transaction
begin try
update bank set balance=balance-100 where cid='0001' update bank set balance=balance + 100 where cid='0002' --沒有錯誤就執行上面的兩句代碼
commit
end try begin catch
print '有錯誤' --回滾條件,update語句一句都不執行 rollback
end catch

22. 存儲過程(就像數據庫中運行方法) 

存儲過程與函數的區別:

1.一般來說,存儲過程實現的功能要複雜一點,而函數的實現的功能針對性比較強。

2.對於存儲過程來說可以返回參數(output),而函數只能返回值或者表對象。

3.存儲過程一般是作爲一個獨立的部分來執行,而函數可以作爲查詢語句的一個部分來調用,由於函數可以返回一個表對象,因此它可以在查詢語句中位於FROM關鍵字的後面。

優點:
執行速度更快 – 在數據庫中保存的存儲過程語句都是編譯過的允許模塊化程序設計 – 類似方法的複用
提高系統安全性 – 防止SQL注入
減少網絡流通量 – 只要傳輸 存儲過程的名稱

系統存儲過程一般以sp開頭,用戶自定義的存儲過程一般以usp開頭

定義存儲過程語法create proc 存儲過程名

  1. @參數1  數據類型 [=默認值] [output],

  2. @參數2  數據類型 [=默認值] [output],

...

as
SQL語句

執行存儲過程語法:exec 存儲過程名

Example One:
定義存儲過程:

create proc usp_StudentByGenderAge
@gender nvarchar(10) [='男'],
@age int [=30]
as
select * from MyStudent where FGender=@gender and FAge=@age

執行存儲過程:
Situation One(調用默認的參數):

exec usp_StudentByGenderAgeSituation Two(調用自己指定的參數):

exec usp_StudentByGenderAge '女',50
或者指定變量名 exec usp_StudentByGenderAge @age=50,@gender='女' 

alter proc usp_StudentByGenderAge
@gender nvarchar(10) [='男'],
@age int [=30], --加output表示該參數是需要在存儲過程中賦值並返回的 @recorderCount int output
as
select * from MyStudent where FGender=@gender and FAge=@age
set @recorderCount=(select count(*) from MyStudent where FGender=@gender and FAge=@age)說明:將上面的存儲過程修改一下,加一個返回記錄的條數

說明:將上面的存儲過程修改一下,加一個返回記錄的條數

--output參數的目的,就是調用者需要傳遞一個變量進來,然後在存儲過程中爲該變量完成賦值工作,存儲過程執行完成以後,將執行的對應結果返回給傳遞進來的變量。(與C#中的out原理一模一樣)

調用(記住這裏的語法!)因爲該存儲過程前面還有其他參數,所以要把 @recorderCount寫上,該存儲過程執行後,相當與完成了以上的查詢工作,同時將查詢結果得到的條數賦值給了@count變量。(@count是當做參數傳給usp_StudentByGenderAge,當存儲過程執行完畢以後,將得到的條數返回給@count) 

declare @count int
exec usp_StudentByGenderAge @recorderCount=@count output print @count

Example Two: 銀行轉賬問題(存儲過程版本) 

create proc usp_tranMoney @exportId nvarchar(max), @importId nvarchar(max), @money money
as
begin
begin tran
declare @exportLeftMoney money
set @exportLeftMoney=(select salary from T_tran where id=@exportId) if @exportLeftMoney-@money>=10
begin
update T_tran set salary=salary-@money where id=@exportId update T_tran set salary=salary+@money where id=@importId commit
end else
begin rollback
end end

Example Three:分頁(存儲過程版)

create proc usp_page
@page int, ---一頁顯示多少條記錄 @number int, ---用戶選擇了第幾頁數據 as
begin
select * from
--小括號裏面內容是專門得到排列好的序號 (
select *, ROW_NUMBER() over(order by(Fid)) as number
from MyStudent ) as t
where t.number>= (@number-1)*@page+1 and t.number<=@number*@page end

23.觸發器其是一種特殊的存儲過程。

一般的存儲過程是通過存儲過程名直接調用,而觸發器主要是通過事件(增、刪、改)進行觸發而被執行的。其在表中數據發生變化時自動強制執行。常見的觸發器有兩種:after(for)、instead of,用於insert、update、delete事件。

after(for) 表示執行代碼後,執行觸發器

instead of 表示執行代碼前,用已經寫好的觸發器代替你的操作

觸發器語法:

create trigger 觸發器的名字for|after instead ofupdate|insert|delete
as

SQL語句

on 操作表

Example1 

--禁止用戶插入數據(實際上是先插入,然後立刻將其刪除!)
create trigger tr_insert on bank
for --for表示執行之後的操作
insert --即先執行了插入操作,同時在臨時表中保存了插入記錄 as
--執行完插入之後,在新生成的表中將剛剛插入的那條記錄刪除,
--而此時得到的剛剛插入的記錄的id是通過臨時表 inserted得到的 delete * from bank where cid=(select cid from inserted)

生成上面的觸發器後,當用戶再輸入insert語句後就見不到效果了!如:insert into bank values('0004',10000),是插入不進數據庫的。 

Example2:有兩張表,學生表和成績表,當向學生表中插入數據,如果學生的課程Id在課程表中不存在,則執行after觸發器,禁止插入

create table T_Student
(
Stuid int identity(1,1) primary key, StuName nvarchar(50),
CourseId int
)
create table Course (
CourseId int ,
   CouName nvarchar(50)
)
insert into Course values(1,'語文') insert into Course values(2,'數學') insert into Course values(3,'英語')

觸發器如下:

create trigger tri_Student_insert on T_Student
after insert
as
begin
//判斷剛插入的數據在課程表中是否有對應的課程id
if not exists(select * from Course where CourseId=(select CourseId from inserted)) begin
delete from T_Student where CourseId=(select CourseId from inserted)
end
end

Example3:

--刪除誰就讓誰的賬戶加上10元
create trigger tr_dalete on bank
instead of
delete
as
update bank balance=balance+10 where cid=(select cid from deleted) 

生成這個觸發器之後,當用戶輸入delete語句後,對應的那個id不但沒有被刪除掉,而且他的賬戶增加了10元 , 如:

delete from bank where cid='0002',執行完這句話後,編號爲0002的賬戶會增加10元

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章