數據庫(八)之T-SQL編程


什么是Transact-SQL?

  結構化查詢語言(SQL)是有美國國家標准協會(ANSI)和國際標准化組織(ISO)定義的標准,而Transact-SQL是Microsoft公司對此標准的一個實現。

  transact-SQL語言是結構化查詢語言(SQL)的增強版本,與多種ANSI SQL標准兼容,而且在標准的基礎上還進行了許多擴展。Transact-SQL代碼已成為SQL Server的核心。Transact-SQL在關系數據庫管理系統中實現數據的檢索,操縱和添加功能。

分類

  在Microsoft SQL Server 2008系統中,Transact-SQL可以創建,維護,保護數據對象中的數據,所以Transact-SQL語言是一種完整的語言。根據T-SQL語言的執行功能特點,可以將T-SQL語言分為三種基本類型:

  • 數據定義語言
  • 數據操縱語言
  • 數據控制語言

  還有一些其他類型:

  • 數據控制語言
  • 流程控制語言
  • 附加的語言元素

常量與變量

  變量聲明:

declare
{@local_variable[as]data_type | @cursor_variable_name CURSOR
}[,…n]

  賦值:

  要給聲明的局部變量賦值,可以使用set或select語句,格式如下:

set @local_variable = expression
select @local_variable = expression [,…n]

  例子:

declare @name nvarchar(50)
set @name = 'Bob'
select @name = 'Peter'
select @name
print @name

運算符:

  算術運算符:

        

  位運算符:

        

  比較運算符:

        

  邏輯運算符:

        

       其他運算符:

       

  表達式:

       

  注釋:

       

  if…else語句:

  語法格式:

if boolean_expression
    {sql_statement | statement_block}
else
    {sql_statement | statement_block} 

 

例子:
declare @num int
select @num = avg(分數) from 成績信息
where 考試編號 = '0802' and 課程編號 = '2'

if @num > 80
begin
print 'good'
end
else
begin
print 'bad'
end

if…else語句嵌套
declare @num int

select @num = avg(分數) from 成績信息
where 課程編號 = '2' and 考試編號 = '0802'

if @num >= 60
begin
if @num < 70
print 'just so so'
else if @num < 80
print 'mid'
else if @num < 90
print 'good'
else
print 'wonderful'
end
else
begin
print 'terrible'
end

case 語句
語法格式:
case input_expression
when when_expresion then result_expression
[…n]
[else else_result_expression]
end

例子:
select 員工姓名,所任職位,員工職稱 =
case 所任職位
when '經理' then '高級職稱;
when '主管' then '中級職稱'
when '職員' then '初級職稱'
else '其他職稱'
end
from 員工信息

while 語句
while boolean_expression
{sql_statement | statement_block}
[break]
{sql_statement | statement_block}
[continue]
{sql_statement | statement_block}

例子:
declare @i int, @sum int
set @i = 1
set @sum = 0
while @i <= 10
begin
set @sum = @sum + @i
set @i = @i + 1
end
select @sum as result

例2:
declare @i int
declare @j int
set @i = 3

while @i <= 100
begin
declare @bol int
set @bol = 1
set @j = 2
while @j <= sqrt(@i)
begin
if @i % @j = 0
begin
set @bol = 0
break
end
set @j = @j + 1
end
if @bol = 1 print @i
set @i = @i + 1
end

wati for延遲語句
語法格式:
waitfor
{
delay time | time time
}

例子:
watifor delay '00:00:05'
exec sp_helpdb

例2:
waitfor time '11:20:00'
select getdate()

goto語句
例子:
declare @Counter int
set @Counter = 1
while @Counter < 10
begin
print @Counter
set @Counter = @Counter + 1
if @Counter = 1 goto branch_one
else @counter = 2 goto branch_two
else goto branch_three
end
branch_one:
print 'Jumping to branch one'
goto branch_three
branch_two:
print 'Jumping to branch two'
branch_three:
print 'Jumpint to branch_three'

try … catch錯誤處理語句
begin try
{sql_statement | statement_block}
end try
begin catch
{sql_statement | statement_block}
end catch

例子:
begin try
declare @num int
set @num = 1/0
select @num
end try
begin catch
select error_line() as '錯誤行數', error_message() '錯誤消息'
end catch

數學函數
abs 絕對值
exp 返回指定表達式以e為底的指數
ceiling 返回大於或等於數值表達式的最小整數
floor 返回小於或等於數值表達式的最大整數
ln 返回數值表達式的自然對數
log
power
round 返回舍入到指定長度或精度的數值表達式
sign 返回+,-或0
square 返回數值表達式的平方
sqrt 返回數值表達式的平方根

字符串函數
ascii 返回字符表達式中最左側的字符的ascii代碼值
char ascii代碼轉換函數,返回指定ascii代碼的字符
left 左字串函數,返回字符串中從左邊開始指定個數的字符
len 字符串函數,返回指定字符串表達式的字符數,其中不包含尾隨空格
lower 小寫字母函數,將大寫字符數據轉換位小寫字符數據后返回字符表達式
ltrim 刪除前導空格字符串,返回刪除了前導空格之后的字符表達式
replace 替換函數,用第三個表達式替換第一個字符串表達式中出現的所有第二個指定字符串表達式的匹配項
replicate 賦值函數,以指定的詞數重復字符表達式
right 右子串函數,返回字符串中從右邊開始指定個數的字符
rtrim 刪除尾隨空格函數,刪除所有尾隨空格后返回一個字符串
space 空格函數,返回由重復空格組成的字符串
str 數字向字符轉換函數,返回由數字數據轉換來的字符數據
substring 字串函數,返回字符表達式,二進制表達式,文本表達式或圖像表達式的一部分
upper 大寫函數,返回小寫字符數據轉換為大寫的字符表達式

字符串函數
charindex()
返回字符串中某個指定的字串出現的開始位置。
charindex(<'substring_expression'>, <expression>)
其中substring_expression是所要查找的字符表達式,expression可以為字符串也可為列名表達式。如果沒有發現子串,則返回0值
此函數不能用於test和image數據類型

patindex()
返回字符串中某個指定的子串出現的開始位置
patindex(<'%substring_expression%'>, <column_name>)其中子串表達式前后必須有百分號‘%’否則返回值為0
與charindex函數不同的是,patindex函數的子串中可以使用通配符,且此函數可用於char,varchar和test數據類型。

例子:
declare @str1 nvarchar(20),
@str2 nvarchar(20),
@str3 nvarchar(20),
@str4 nvarchar(20),
@str5 nvarchar(20)

set @str1 = '上海分公司經理'
set @str2 = '北京分公司經理'
set @str3 = '天津分公司經理'
set @str4 = '上海分公司財務經理'
set @str5 = '天津分公司財務經理'

select charindex('經理', @str4)
select right(@str4, len(@str4) - charindex('分公司', @str4) + 1)

聚合函數
avg 平均值
count 計數
max 最大值
min 最小值
sum 求和

例子:
select avg(分數) as 平均成績
from 成績信息
where 考試編號 = '0801' and 課程編號 = '2'


select sum(分數) as 總分數
from 成績信息
where 考試編號 = '0801' and 課程編號 = '2'


select min(分數) as 最低分
from 成績信息
where 考試編號 = '0801' and 課程編號 = '2'


select max(分數) as 最高分
from 成績信息
where 考試編號 = '0801' and 課程編號 = '2'


select count(分數) as 人數
from 成績信息
where 考試編號 = '0801' and 課程編號 = '2'

日期和時間函數
dateadd 返回給指定日期加上一個時間間隔后的新datetime值
datediff 返回跨兩個日期的日期邊界數和時間邊界數
datename 返回表示指定日期的指定日期部分的字符串
datepart 返回表示指定日期的指定日期部分的整數
day 返回一個整數,表示指定日期的天datepart部分。
getdate 以datetime值得SQL Server 2008標准內部格式返回當前系統日期和時間
getutcdate 返回表示當前得utc時間得datetime值。
month 返回表示指定日期得“月”部分的整數
year 返回表示指定日期的年份的整數。

例子:
select GETDATE() as 日期

select GETutcDATE() as 日期

select YEAR(getdate())
select month(getdate())
select day(getdate())

select DATEPART(YY, GETDATE())
select DATEPART(mm, GETDATE())
select DATEPART(dd, GETDATE())

select DATEADD(DD, 1, GETDATE())

標量值函數
語法格式:
create function function_name
([{@parament_name scalar_parameter_data_type [ = default]}[,…n]])
returns scalar_return_data_type
[with encryption]
[as]
begin
function_body
return scalar_expression
end

例子:
create function sorceAve(@id, nvarchar(50))
returns int
as
begin
declare @score int
select @sorce = avg(分數) from 成績信息
where 課程編號 = @id
return @score
end
go

select dbo.sorceAvg('2')

表值函數
語法格式:
create function function_name
([{@parameter_name scalar_parameter_data_type [ = default]}[,…n]])
returns table
with encryption
as
return (select_statement)

例子:
create function findSorce(@id varchar(10))
returns table
as
return (
select 課程名稱,姓名,分數 from (
select B.課程名稱, c.姓名, avg(A.分數) 分數
from 成績信息 A join 課程信息 B
on A.課程編號 = B.課程編號
join 教師信息 c on b.任課教師 = c.教師編號
where A.考試編號= @id
group by B.課程編號, C.姓名
) a
where 分數 >= 85
)

select * from findcourse('0802')

游標
什么是游標?
游標(Cursor)是一種數據訪問機制,它允許用戶訪問單獨的數據行,而不是對整個行集進行操作。
用戶可以通過單獨處理每一條逐行收集信息並對數據逐行進行操作,這樣可以降低系統開銷和潛在的
阻隔情況。用戶也可以使用這些數據生成SQL代碼並立即執行或輸出。

游標主要包括以下兩個部分:
(1)游標結果集 由定義游標的select語句返回的行的集合。
(2)游標位置 指向這個結果集中的某一行的指針。

游標的特點:
游標返回一個完整的結果集,但允許程序設計語言只調用集合中的一行。
允許定位在結果集中的特定行。
從結果集的當前位置檢索一行或多行
支持對結果集中當前位置的行進行數據修改。
可以為其他用戶對顯示在結果集中的數據庫數據所做的更改提供不同級別的可見性支持。
提供腳本,存儲過程和觸發器中使用的訪問結果集中數據的T-SQL語句。

語法格式:
declare cursor_name [insensitive] [scroll] cursor
for select_statement
[for{read only|update [of column_name [,…n]]}]

例子:
declare student_cursor scroll cursor
for
select * from 學生信息
for read only

declare student_cursor cursor
for
select * from 學生信息
for update

釋放游標
deallocate student_cursor

操作有標
打開游標 open{{[global] cursor_name} | cursor_variable_name}
檢索游標 fetch
[[next | prior | first | last | absolute { n | @nvar } | relative{n|@nvar}]

from]
{{[global] cursor_name} | @cursor_variable_name }
[into @variable_name[,…n]]

關閉游標 close {{[global] cursor_name} | @cursor_variable_name}
釋放游標 deallocate {{[global] cursor_name} | @cursor_variable_name}

例子:
declare stu_cursor scroll cursor for
select 姓名 from 學生信息

declare @name varchar(20)

open stu_cursor
fetch next from stu_cursor into @name
close stu_cursor
deallocate stu_cursor

print @name

游標可選項:next, prior, first, last, absolute

判斷游標提取狀態
@@fetch_statue
0, fetch 語句成功
-1, fetch 語句失敗或行不在結果集中
-2 提取的行不存在

例子:
declare stu_cursor scroll cursor for
select 姓名 from 學生信息

open stu_cursor
declare @name varchar(20)
fetch next from stu_cursor into @name

if @@fetch_status = 0
print @name
else
print 'error'
close stu_cursor
deallocate stu_cursor

游標應用示例
declare stu_cursor scroll cursor for
select 學號 from 學生信息

create table #t(name nvarchar(20), sorce int)

open stu_cursor

fetch next from stu_cursor into @name
while @@fetch_status = 0
begin
insert into #t
select B.姓名, avg(分數) as 分數
from 成績信息 A join 學生信息 B
on A.學生編號 = B.學號
where A.考試編號 = '0801' and B.學號 = @name
group by B.姓名

fetch next from stu_cursor into @name
end
close stu_cursor
deallocate stu_cursor

select name 姓名, sorce 平均分數 from #t
drop table #t

例2
declare stu_cursor scroll cursor for
select 姓名from 學生信息

create table #t_name(姓名 varchar(20))

declare @name varchar(20)

open stu_cursor
fetch next from stu_cursor into @name

while @@fetch_status = 0
begin
insert into #t_name values(@name)
fetch next from stu_cursor into @name
end
close stu_cursor
deallocate stu_cursor

select * from #t_name
drop table #t_name

事務
在SQL Server 2008中只要使用下列4條語句管理事務:
begin transaction
commit transaction
rollback transaction
save transaction

例子:
begin transaction

declare @nation varchar(20)
set @nation = '漢族'

insert into 學生信息
values('2111605165', '小龍', '男', '1999-1-1', @nation, 102, '上海', '111111')

if @nation = '漢族'
begin
commit transaction
end
else
rollback transaction


所謂鎖,就是一個事務可向系統提出請求,對被操作的數據加鎖(lock)。其他事務必須
等到此事務解鎖(unlock)之后才能訪問該數據。從而,在多個用戶並發訪問數據庫時,
確保不互相干擾。可封鎖的單位是:行,頁,表,盤區和數據庫。

鎖的類型
共享鎖(S) :用於讀操作。
多個事務可封鎖一個共享單位的數據。
任何事物都不能修改加S鎖的數據。
通常是加S鎖的數據被讀取完畢,S鎖立即被釋放。

獨占(X)鎖:用於寫操作。
僅允許一個事務封鎖此共享數據。
其他任何事物必須等到X鎖被釋放才能對該數據進行訪問。
X鎖一直到事務結束才能被釋放。

更新(U)鎖
用來預定對此頁施加X鎖,它允許其他事務讀,但不允許再施加U鎖或X鎖。
當被讀取數據頁要被更新時,則升級為X鎖。
U鎖一直到事務結束時才能被釋放。

系統與元數據函數
convert() 講一種數據類型的數據轉變為另一種數據類型的數據。
current_user() 返回當前用戶的名稱。
isdate() 判斷它的輸入是不是一個有效日期。
isnull() 用一個指定替換值替換任何空值。
isnumeric() 判斷它的輸入是不是一個數值。

例子:
declare @str varchar(10), @i int, @j int
set @str = '12'
set @i = 10

if isnumeric(@str) = 1
begin
print convert(int, @str) *i
end

print isnull(@j, 10) @i

begin…end語句塊
begin
{
sql_statement | statement_block
}
end

例子:
declare @sex varchar(5)
if @sex is not null
begin
select * from 學生信息 where 性別 = @sex
print '查詢成功'
end
else
begin
print '查詢失敗'
end

事務模式
自動提交事務 每條單獨的語句都是一個事務
顯示事務 每個事務均以begin transaction開始,以commit或rollback語句顯
式結束。
隱式事務 在前一個事務完成時新事物隱式啟動,但每個事務仍以commit或
rollback語句顯示完成。
批處理級事務 只能用於多個活動結果集(MARS),在MARS會話中啟動的Transact-
SQL顯示或隱式事務變為批處理級事務。當批處理完成時沒有提交
或回滾的批處理級事務自動由SQL Server進行回滾。

xact_abort選項
xact_abort選項用於指定當SQL語句出現運行時錯誤時,SQL Server是否自動回滾當前
事務。其語法格式如下所示:
set xact_abort{on | off}
當set xact_abort為on時,如果執行SQL語句產生運行時錯誤,則整個事務將終止並回滾
當set xact_abort為off時,有時只回滾產生錯誤的SQL語句,而事務將繼續進行處理。
如果錯誤很嚴重,那么即使set xact_abort為off,也可能回滾整個事務。

set xact_abort的設置是在執行或運行時設置,而不是在分析時設置。對於大多數ole db
提供程序,必須將隱式或顯示事務中的數據修改語句中的xact_abort設置為on。唯一不
需要該選項的情況是在提供程序支持嵌套事務時。

死鎖
所謂死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待
的現象,若無外力作用,它們都將無法推進下去,此時稱系統處於死鎖狀態或系統產生
了死鎖,這些永遠在互相等待的進程稱為死鎖進程。

由於資源占用是互斥的,當某個進程提出申請資源后,使得有關進程在無外力協助下,
永遠分配不到必需的資源而無法繼續運行,這就產生了一種特殊現象死鎖。

一種情形,此時執行程序中兩個或多個線程發生永久阻塞(等待),每個線程都在等待
被其他線程占用並阻塞了的資源。例如,如果線程A鎖住了記錄1並等待記錄2,而
線程B鎖住了記錄2並等待記錄1,這樣兩個線程就發生了死鎖現象。

必要條件:
互斥條件 一個資源每次只能被一個進程使用
請求與保存條件:一個進程因請求資源阻塞,對已獲得的資源保持不妨
不剝奪條件:進程已獲得的資源,在未使用完之前,不能強行剝奪。
循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
這四個條件是死鎖的必要條件,只要系統發送死鎖,這些條件必然成立,而只要
上述條件之一不滿足,就不會死鎖。

死鎖的解除和預防:
按同一順序訪問對象
避免事務中的用戶交互
保持事務簡短並在一個批處理中
使用低隔離級別
使用綁定連接

死鎖的建議:
對於頻繁使用的表使用集簇化的索引
設法避免一次性影響大量記錄的T-SQL語句,特別是insert和update語句
設法讓update和delete語句使用索引
使用嵌套事務時,避免提交和回退沖突
對一些數據不需要及時讀取更新值得表在寫SQL得時候在表后台加上nolock
如:select * from tableA(nolock)

嵌套事務:
begin transaction t1
update 班級信息 set 班級名 = '金融管理系1班'
where 班級編號 = '20180101'

if exist(select * from 班級信息 where 班級名 = '金融管理系1班')
begin
begin transaction t2
update 班級信息 set 輔導員 = '李民'
where 班級名 = '金融管理系1班'

if exist(select * from 輔導員信息 where 姓名 = '李民'
commit transaction t2
else
begin
rollback transaction t2
end

commit transaction t1
end
else
rollback transaction t1

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM