国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫(kù) > SQL Server > 正文

SQL Server 2005的XML支持與異常處理

2024-08-31 00:50:09
字體:
供稿:網(wǎng)友

  本文給出了類型化和非類型化xml列各自的優(yōu)勢(shì)、將sql server 2000數(shù)據(jù)庫(kù)遷移到sql server2005,新的異常處理如何工作;如果表的架構(gòu)發(fā)生更改,我如何執(zhí)行操作等,供大家參考!

  sql server 2005 包括對(duì)transact-sql (t-sql) 語言的幾項(xiàng)重要改進(jìn)。新增功能之一是一種新的觸發(fā)器,它在數(shù)據(jù)定義語言 (ddl) 語句運(yùn)行時(shí)激發(fā)。在跟蹤或保護(hù)數(shù)據(jù)庫(kù)對(duì)象的創(chuàng)建和修改,或?qū)?shù)據(jù)庫(kù)服務(wù)器進(jìn)行更改時(shí),ddl 觸發(fā)器非常有用。另一個(gè)新功能涉及異常處理,該功能因包含try/catch 塊而在異常處理方面向前飛躍了一大步。另一組新功能則以新的xml數(shù)據(jù)類型為中心,該數(shù)據(jù)類型在與sql server交互的企業(yè)應(yīng)用程序中管理xml數(shù)據(jù)方面前進(jìn)了一大部?,F(xiàn)在,xml 文檔或片段可以存儲(chǔ)于 xml 列、綁定到架構(gòu)、還可以利用 xquery 語法查詢。本文匯總各類問題來做出詳細(xì)解答。

  問:類型化和非類型化 xml 列各自的優(yōu)勢(shì)是什么?

  答:非類型化 xml 列可以存儲(chǔ)所有格式規(guī)范的 xml 片段或文檔,而類型化 xml 列可以綁定到 xml 架構(gòu)。如果不確定 xml 將遵循哪個(gè)架構(gòu),則非類型化 xml 很有用。例如,如果您必須使用另一個(gè)應(yīng)用程序的某些 xml,但無法確定數(shù)據(jù)將遵循哪個(gè) xml 架構(gòu),則可以使用非類型化 xml 列來執(zhí)行這項(xiàng)工作。當(dāng)然,非類型化 xml 也會(huì)帶來其他問題。例如,不能針對(duì)某個(gè)架構(gòu)編程,因此很難有效地使用 xml。但有時(shí)無法避免非類型化 xml。創(chuàng)建非類型化 xml 列非常簡(jiǎn)單,如下所示:

create table foo(fooid int, somexml xml)

  架構(gòu)不綁定到 xml 列的另一個(gè)結(jié)果是,sql server® 2005 會(huì)將非類型化 xml 作為一個(gè)字符串存儲(chǔ)。這是件好事還是壞事?實(shí)際上,既是好事也是壞事。將 xml 作為字符串存儲(chǔ)使您可以更靈活地存儲(chǔ)任何 xml 片段或文檔。根據(jù)應(yīng)用程序的業(yè)務(wù)規(guī)則,您可能需要這種方式。另一方面,將 xml 作為字符串存儲(chǔ)意味著,與類型化 xml 相比,既不能有效地存儲(chǔ)也不能有效地搜索 xml 數(shù)據(jù)。并且既不會(huì)告訴 sql server xml 將包含哪些內(nèi)容,也不會(huì)告訴它層次結(jié)構(gòu)和 xml 節(jié)點(diǎn)的數(shù)據(jù)類型。但請(qǐng)記住,僅僅因?yàn)檫@些是非類型化 xml 列并不意味著它們可以接受您設(shè)計(jì)出的任何格式。類型化和非類型化 xml 列仍然只接受格式規(guī)范的 xml。

|||

  如果您要存儲(chǔ)架構(gòu)已知的 xml 文檔,類型化 xml 列很理想。架構(gòu)可以定義元素、屬性、它們的數(shù)據(jù)類型、需要哪些字段以及數(shù)據(jù)的整個(gè)層次結(jié)構(gòu)。由于這種詳細(xì)信息有關(guān) xml 列的數(shù)據(jù),因此 sql server 2005 可以在內(nèi)部更加有效地存儲(chǔ) xml 數(shù)據(jù)。如果您嘗試存儲(chǔ)與架構(gòu)不匹配的 xml 數(shù)據(jù),則 sql server 會(huì)檢測(cè)到這一點(diǎn)并阻止您。

  創(chuàng)建類型化 xml 列就像在括號(hào)中添加架構(gòu)名稱一樣簡(jiǎn)單,如下所示:

create table foo(fooid int, somexml xml(content fooschema))

  該語句指出 somexml 列必須遵循名為 fooschema 的 xml 架構(gòu)集合。通過分別包含相應(yīng)的關(guān)鍵字 document 或 content,xml 可指定為必須是一個(gè)文檔或者可以包含一個(gè)片段。如果省略,則默認(rèn)值為 content。

  可以使用 t-sql 命令將 xml 架構(gòu)集合添加到數(shù)據(jù)庫(kù)中,如下所示:

create xml schema collection [fooschema] as n 'put your schema here'

  也可以使用 sql server management studio (ssms) 創(chuàng)建 xml 架構(gòu)集合模板。從 view 菜單打開 template explorer,然后導(dǎo)航到 xml schema collections 節(jié)點(diǎn)并展開它。然后,您可以雙擊 create 模板打開一個(gè)模板,該模板為您創(chuàng)建 xml 架構(gòu)集合提供了一個(gè)良好的語法開端(參見圖 1)。

  圖1:xml架構(gòu)集合模板是ssms

  sql server 2005 隨附的 adventureworks 數(shù)據(jù)庫(kù)有一個(gè)名為 humanresources.jobcandidate 的表。該表包含一個(gè)名為 resume 的列,該列是一個(gè)綁定到架構(gòu)集合 humanresources.hrresumeschemacollection 的 xml 列。該列中存儲(chǔ)的所有 xml 數(shù)據(jù)都必須遵循該架構(gòu)。



|||

  圖2:resume架構(gòu)

  類型化和非類型化 xml 列都可以進(jìn)行索引,但索引時(shí),綁定到架構(gòu)的 xml 列比非類型化 xml 列具有更多優(yōu)點(diǎn)。將 xml 索引應(yīng)用于非類型化 xml 列時(shí),必須分析大部分 xml 結(jié)構(gòu)來定位匹配的節(jié)點(diǎn)。但是,將 xml 索引應(yīng)用于類型化 xml 列時(shí),特定節(jié)點(diǎn)是可識(shí)別的并可根據(jù)架構(gòu)定位。因此,索引可以在類型化 xml 中更有效地工作,因?yàn)樗涝谀睦锊檎?。此外,如果需要搜索一個(gè)數(shù)值范圍,則索引將用非類型化 xml 執(zhí)行一個(gè)數(shù)據(jù)類型轉(zhuǎn)換(因?yàn)閿?shù)據(jù)類型是未知的)。類型化 xml 定義自己的數(shù)據(jù)類型,從而避免了轉(zhuǎn)換開銷。

  問:我剛剛將 sql server 2000 數(shù)據(jù)庫(kù)遷移到 sql server 2005。我聽說 sql server 2005 在 t-sql 中引入了 try/catch 異常處理。與現(xiàn)有的 if @@error <> 0 技術(shù)相比,新的異常處理如何工作呢?

  答:通常對(duì)使用 t-sql 編寫代碼的抱怨是,t-sql 始終缺少一個(gè)健壯的異常處理結(jié)構(gòu)。通過 sql server 2000,您可以編寫 t-sql 批處理代碼,以檢查是否存在錯(cuò)誤甚至何時(shí)引發(fā)錯(cuò)誤(如果需要)。但與 try/catch 技術(shù)相比,執(zhí)行此操作的技術(shù)是最基本的。首先,我將使用 @@error 函數(shù)定義與異常處理相關(guān)聯(lián)的問題,然后展示新的 try/catch 技術(shù)與之相比是如何執(zhí)行的。

  sql server 公開內(nèi)置的 @@error 函數(shù),該函數(shù)返回所執(zhí)行的上一條 t-sql 命令的錯(cuò)誤號(hào)。該函數(shù)的問題在于,它始終返回從剛剛執(zhí)行的上一個(gè)語句返回的錯(cuò)誤。這意味著,如果您執(zhí)行一個(gè)導(dǎo)致錯(cuò)誤的 insert 語句,然后執(zhí)行另一個(gè)不會(huì)導(dǎo)致錯(cuò)誤的任意 sql 語句,之后再查看 @@error 的返回值,則該函數(shù)將返回 0,原因是上一個(gè)語句沒有返回錯(cuò)誤。您必須十分小心,以確保在執(zhí)行每個(gè)單獨(dú)語句之后檢查 @@error 的值。


|||begin transaction
delete [order details] where orderid in
(select orderid from orders where customerid = 'alfki')
if @@error <> 0
begin
rollback transaction
return
end
delete orders where customerid = 'alfki'
if @@error <> 0
begin
rollback transaction
return
end
delete customers where customerid = 'alfki'
if @@error <> 0
begin
rollback transaction
return
end
print 'i got here'
-- normally do a commit transaction here.
-- but i do a rollback so i don't truly delete my test data.
rollback transaction

  展示一些示例代碼,這些代碼將在事務(wù)內(nèi)部運(yùn)行,依次刪除客戶的定單詳情、定單以及客戶本身。在每個(gè) delete 語句之后,代碼都會(huì)檢查 @@error 函數(shù)的值,以查看 delete 語句是否導(dǎo)致了錯(cuò)誤。如果是,則回滾事務(wù),停止執(zhí)行代碼,然后從批處理操作返回。

  這是標(biāo)準(zhǔn)的事務(wù)管理,即如果發(fā)生錯(cuò)誤,則中止事務(wù),然后將數(shù)據(jù)的狀態(tài)返回至其初始狀態(tài)。請(qǐng)注意,如果一切順利并且沒有發(fā)生錯(cuò)誤,我會(huì)打印一個(gè)成功消息,然后回滾事務(wù)。通常,我不會(huì)成功地進(jìn)行回滾,因?yàn)檫@是一個(gè)測(cè)試事務(wù),我實(shí)際上并不希望刪除我的數(shù)據(jù)。

  請(qǐng)注意,我必須遵循帶有 @@error 函數(shù)的每個(gè)語句,然后再使用 rollback 和 return。該方法十分糟糕。假設(shè)編寫一個(gè)包含許多查詢(這些查詢都需要檢查)的事務(wù)。該過程可以通過 goto 語句來稍加簡(jiǎn)化,當(dāng)然我并不是 goto 語句的提倡者,因?yàn)樗鼈円琅f未解決需要在查詢操作之后立即檢查 @@error 函數(shù)的問題。


|||

  sql server 2005 仍然支持 @@error 函數(shù),但它還包括了廣為人知的 try/catch 模式。try/catch 結(jié)構(gòu)與 c# try/catch 結(jié)構(gòu)的類似之處在于,在 try 塊中捕獲錯(cuò)誤,然后轉(zhuǎn)移到 catch 塊執(zhí)行。(t-sql 版本的 try/catch 沒有 finally 子句選項(xiàng),但 c# 版本有。您可以通過捕獲異常、不執(zhí)行返回、然后使用適當(dāng)?shù)那宄a執(zhí)行 catch 塊來進(jìn)行模擬。)因此,在某些情況下需要注意這一點(diǎn),例如,在指定了 cursor 并在 t-sql try 塊中引發(fā)錯(cuò)誤時(shí)打開該游標(biāo)的情況。在這種情況下,應(yīng)該在 catch 塊中檢查游標(biāo)以查看它是否已打開;如果已打開,則應(yīng)將其關(guān)閉并取消指定。

begin try
begin transaction
delete [order details] where orderid in
(select orderid from orders where customerid = 'alfki')
delete orders where customerid = 'alfki'
delete customers where customerid = 'alfki'
print 'committing deletes'
commit transaction
end try
begin catch
rollback transaction
return
end catch

  看到上面代碼中的 try/catch 結(jié)構(gòu)后,您可能會(huì)震驚于它與 @@error 技術(shù)相比是多么簡(jiǎn)潔。請(qǐng)注意,對(duì)于 try/catch 塊,不需要重復(fù)檢查是否有錯(cuò)誤,因而減少了代碼行數(shù)同時(shí)也減少了出現(xiàn)編碼錯(cuò)誤的地方。

  上面代碼中的代碼試圖開始一個(gè)事務(wù),執(zhí)行一系列 delete 語句,然后提交該事務(wù)。(另請(qǐng)注意,在我的示例中,我沒有提交事務(wù)而是回滾該事務(wù),因此實(shí)際上并沒有刪除數(shù)據(jù)。實(shí)際上,這應(yīng)該是一個(gè) commit tran 語句。)

  可以在 try/catch 結(jié)構(gòu)中訪問多個(gè)內(nèi)置函數(shù),以幫助您確定導(dǎo)致代碼進(jìn)入 catch 塊的原因。例如,可以在 catch 塊內(nèi)部添加以下語句,返回有關(guān)該錯(cuò)誤的信息:

  • 網(wǎng)站運(yùn)營(yíng)seo文章大全
  • 提供全面的站長(zhǎng)運(yùn)營(yíng)經(jīng)驗(yàn)及seo技術(shù)!
  • |||select
    error_line() as errorline,
    error_message() as errormessage,
    error_number() as errornumber,
    error_procedure() as errorprocedure,
    error_severity() as errorseverity,
    error_state() as errorstate

      這些函數(shù)(如果適用)將返回發(fā)生錯(cuò)誤的行號(hào)、錯(cuò)誤消息、錯(cuò)誤號(hào)、存儲(chǔ)過程或發(fā)生錯(cuò)誤的觸發(fā)器、錯(cuò)誤的嚴(yán)重級(jí)別以及錯(cuò)誤的狀態(tài)級(jí)別。

      try/catch 結(jié)構(gòu)捕獲嚴(yán)重度為 11 到 19(包括 11 和 19)的錯(cuò)誤。低于 11 的嚴(yán)重級(jí)別是警告,不視為錯(cuò)誤。嚴(yán)重級(jí)別為 20 及以上的錯(cuò)誤視為嚴(yán)重錯(cuò)誤。然而,如果這些嚴(yán)重級(jí)別為 20 及以上的錯(cuò)誤沒有導(dǎo)致數(shù)據(jù)庫(kù)引擎停止,則它們將由 try/catch 捕獲??傊?,try/catch 語句更易于讀取、更易于維護(hù),且更不容易導(dǎo)致復(fù)制和粘貼錯(cuò)誤。此外,@@error 技術(shù)也不總是很可靠。例如,某些錯(cuò)誤會(huì)中止計(jì)劃或整個(gè)批處理。

      問:我知道可以創(chuàng)建觸發(fā)器來審核對(duì)數(shù)據(jù)的更改,但是如果表的架構(gòu)發(fā)生更改,我如何執(zhí)行操作呢?

      答:我在簡(jiǎn)介中提到過,現(xiàn)在有了一個(gè)新的觸發(fā)器:sql server 2005 中的 ddl 觸發(fā)器。數(shù)據(jù)操作語言 (dml) 觸發(fā)器基于數(shù)據(jù)操作激發(fā),而 ddl 觸發(fā)器在對(duì)數(shù)據(jù)庫(kù)架構(gòu)或服務(wù)器進(jìn)行更改時(shí)激發(fā)。創(chuàng)建的 ddl 觸發(fā)器只能在發(fā)生觸發(fā)事件之后激發(fā),而 dml 觸發(fā)器則不同,它可以在事件之后或代替事件激發(fā)。以下是創(chuàng)建 ddl 觸發(fā)器的語法,在 sql server 2005 文檔中進(jìn)行了概述:

    create trigger trigger_name
    on { all server | database }
    [ with encryption ]
    { for | after } { event_type [ ,...n ] | ddl_database_level_events }
    [ with append ]
    [ not for replication ]
    { as
    { sql_statement [ ...n ] | external name < method specifier > }
    }
    < method_specifier > ::= assembly_name:class_name[::method_name]


    |||

      請(qǐng)注意,您可以創(chuàng)建觸發(fā)器,以便它在對(duì)數(shù)據(jù)庫(kù)的架構(gòu)或數(shù)據(jù)庫(kù)服務(wù)器進(jìn)行更改時(shí)激發(fā)。您還可以通過指定事件類型(這些類型都列在 sql server 2005 文檔中)來定義導(dǎo)致觸發(fā)器激發(fā)的事件?;蛘撸部梢酝ㄟ^指定 ddl_database_level_events 標(biāo)識(shí)符讓 ddl 觸發(fā)器在所有事件之后激發(fā)。

      通過 ddl 觸發(fā)器,您可以記錄對(duì)數(shù)據(jù)庫(kù)的架構(gòu)所作的更改??梢允褂?ddl 觸發(fā)器審核更改,而不是防止更改。或者,也可以通過 ddl 觸發(fā)器記錄嘗試操作,然后將其回滾。您可能還希望在創(chuàng)建對(duì)象時(shí)對(duì)其強(qiáng)制命名約定。例如,您可能希望所有存儲(chǔ)過程都以 pr 為前綴。通過 ddl 觸發(fā)器,您可以強(qiáng)制該命名約定。

      ddl 觸發(fā)器與 dml 觸發(fā)器的類似之處在于,它們都可以回滾事務(wù)。然而,ddl 觸發(fā)器沒有插入或刪除的表。ddl 觸發(fā)器能夠訪問一個(gè)名為 eventdata 的內(nèi)置函數(shù),該函數(shù)在 xml 數(shù)據(jù)類型中返回 xml(包含有關(guān)激發(fā)觸發(fā)器的事件的信息)。每個(gè)事件在事件數(shù)據(jù)中顯示的信息都略有不同。但是,eventdata 函數(shù)始終為所有事件返回以下信息:

      ◆事件的時(shí)間

      ◆事件的類型

      ◆導(dǎo)致觸發(fā)器激發(fā)的連接 spid

      ◆發(fā)生事件的用戶上下文的登錄名和用戶名

    create trigger ddltrigger_procnamingconvention
    on database
    after create_procedure, alter_procedure
    as
    declare @eventdataxml xml
    set @eventdataxml = eventdata()
    if substring(@eventdataxml.value('(//objectname)[1]',
    'varchar(200)'), 1, 2) = 'pr'
    print 'starts with pr'
    else
    begin
    print 'does not start with pr'
    rollback transaction
    end
    go

    最大的網(wǎng)站源碼資源下載站,

    |||

      請(qǐng)注意,這段代碼中的 ddl 觸發(fā)器定義為,在當(dāng)前數(shù)據(jù)庫(kù)上創(chuàng)建或更改存儲(chǔ)過程時(shí)激發(fā)。當(dāng)觸發(fā)器激發(fā)后,事件的數(shù)據(jù)會(huì)被捕獲并存儲(chǔ)在本地 xml 變量中。盡管這不是必要的,但如果您打算多次訪問 eventdata 函數(shù),這有助于使觸發(fā)器更高效。然后,觸發(fā)器會(huì)檢查對(duì)象的名稱是否以 pr 開頭。如果是,則允許事務(wù)完成;如果不是,則回滾事務(wù),并且存儲(chǔ)過程將保持不變。在本例中,我知道 objectname 元素將包含存儲(chǔ)過程的名稱,因?yàn)閮H在創(chuàng)建或更改存儲(chǔ)過程時(shí)才會(huì)調(diào)用觸發(fā)器。

    <event_instance>
    <eventtype>create_procedure</eventtype>
    <posttime>2005-10-20t00:52:16.160</posttime>
    <spid>51</spid>
    <servername>mydbserver</servername>
    <loginname>camelotjpapa</loginname>
    <username>dbo</username>
    <databasename>adventureworks</databasename>
    <schemaname>dbo</schemaname>
    <objectname>test1</objectname>
    <objecttype>procedure</objecttype>
    <tsqlcommand>
    <setoptions ansi_nulls="on" ansi_null_default="on" ansi_padding="on"
    quoted_identifier="on" encrypted="false" />
    <commandtext>create proc test1 as select getdate()</commandtext>
    </tsqlcommand>
    </event_instance>

      顯示執(zhí)行以下命令后該觸發(fā)器的事件數(shù)據(jù):

    create proc test1 as select getdate

      您還可以捕獲事件數(shù)據(jù),并將其完整存儲(chǔ)到審核表的 xml 列中。另一個(gè)選擇是抽出特定節(jié)點(diǎn)的內(nèi)容,并將其單獨(dú)存儲(chǔ)。顯然,實(shí)現(xiàn)視具體情況而定,但 ddl 觸發(fā)器為您提供的選擇有很多。使用 ddl 觸發(fā)器時(shí)需要記住的一件事是,它們是同步操作的。由于是同步執(zhí)行,觸發(fā)器應(yīng)該盡可能不執(zhí)行費(fèi)時(shí)的操作。否則,它們會(huì)對(duì)數(shù)據(jù)庫(kù)服務(wù)器的性能造成負(fù)面影響。與 dml 觸發(fā)器一樣,應(yīng)該將 ddl 觸發(fā)器定義為僅執(zhí)行所需的操作并快速完成。如果需要異步執(zhí)行,可以使用 service broker 和 event notification 模型。

    發(fā)表評(píng)論 共有條評(píng)論
    用戶名: 密碼:
    驗(yàn)證碼: 匿名發(fā)表
    主站蜘蛛池模板: 婺源县| 永济市| 陆川县| 佛山市| 凌源市| 阿勒泰市| 麟游县| 太和县| 曲沃县| 石家庄市| 泰宁县| 手游| 鞍山市| 横峰县| 乐陵市| 牡丹江市| 安康市| 东乡族自治县| 佳木斯市| 若羌县| 葵青区| 嘉善县| 大港区| 望谟县| 白城市| 郎溪县| 土默特右旗| 桦甸市| 淮阳县| 大英县| 潼关县| 松溪县| 枣阳市| 靖西县| 鹤峰县| 冀州市| 陆河县| 碌曲县| 碌曲县| 杭州市| 蓬溪县|