SQL server學習(四)T-SQL編程之事務、索引和視圖


今天來分享下T-SQL高級編程中的事務、索引、視圖,可以和之前的SQL server系列文章結合起來。

一、事務

  事務(TRANSACTION)是作為單個邏輯工作單元執行的一系列操作,這些操作作為一個整體一起向系統提交,要么都執行、要么都不執行,事務是一個不可分割的工作邏輯單元

這樣說可能太籠統,看個實例就會清晰很多,比如銀行轉賬業務,相信大家都辦理過。

create table bank
(
    customerName char(10),  --顧客姓名
    currentMoney money     --當前余額
)
go
alter table bank
   add constraint CK_currentMoney   
       check(currentMoney>=1)
go
insert into bank(customerName,currentMoney)
        values('張三',1000)
insert into bank(customerName,currentMoney)
        values('李四',1)

--模擬銀行轉賬:
/*--轉賬測試:張三轉賬1000元給李四--*/
--我們可能會這樣這樣編寫語句
--張三的賬戶少1000元,李四的賬戶多1000元
UPDATE bank SET currentMoney=currentMoney-1000
     WHERE customerName='張三'
UPDATE bank SET currentMoney=currentMoney+1000
     WHERE customerName='李四'
GO
--再次查看轉賬后的結果。
SELECT * FROM bank
GO

這樣寫的SQL代碼,實際結果會出現,張三的錢沒少,而李四的錢多了1000,是因為添加的約束條件,money要>=1,才導致這樣結果。

轉賬那個人的錢沒少,而另一方卻收到了錢,這樣的話,銀行豈不虧死,所以,這樣的代碼明顯是不合理的。根據事務概念,是要么執行成功,要是失敗,只有這兩種結果,而且是同步的。

代碼改進為如下:

使用事務解決:
BEGIN TRANSACTION
/*--定義變量,用於累計事務執行過程中的錯誤--*/
DECLARE @errorSum INT
SET @errorSum=0  --初始化為0,即無錯誤
/*--轉賬:張三的賬戶少1000元,李四的賬戶多1000元*/
UPDATE bank SET currentMoney=currentMoney-1000
   WHERE customerName='張三'
SET @errorSum=@errorSum+@@error
UPDATE bank SET currentMoney=currentMoney+1000
   WHERE customerName='李四'
SET @errorSum=@errorSum+@@error  --累計是否有錯誤

IF @errorSum<>0  --如果有錯誤<>表示不等於與!=的效果一樣
  BEGIN
    print '交易失敗,回滾事務'
    ROLLBACK TRANSACTION
  END 
ELSE
  BEGIN
    print '交易成功,提交事務,寫入硬盤,永久的保存'
    COMMIT TRANSACTION  
  END
GO
print '查看轉賬事務后的余額'
SELECT * FROM bank 
GO

添加事務后,就會保證數據的正確性了,到這,我想大家已經明白事務的好處了。

事務的四大屬性,簡稱ACID屬性

  原子性(Atomicity):事務是一個完整的操作。事務的各步操作是不可分的(原子的);要么都執行,要么都不執行

  一致性(Consistency):當事務完成時,數據必須處於一致狀態

  隔離性(Isolation):對數據進行修改的所有並發事務是彼此隔離的,這表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務

  永久性(Durability):事務完成后,它對數據庫的修改被永久保持,事務日志能夠保持事務的永久性

創建事務

開始事務:BEGIN TRANSACTION
提交事務:COMMIT TRANSACTION
回滾(撤銷)事務:ROLLBACK TRANSACTION

一旦事務提交或回滾,則事務結束。

判斷某條語句執行是否出錯:@@ERROR的返回值為0表示沒錯

使用全局變量@@ERROR;

@@ERROR只能判斷當前一條T-SQL語句執行是否有錯,為了判斷事務中所有T-SQL語句是否有錯,我們需要對錯誤進行累計;

            如: SET @errorSum=@errorSum+@@error

事務分類:

顯示事務:用BEGIN TRANSACTION明確指定事務的開始,這是最常用的事務類型

隱性事務:通過設置SET IMPLICIT_TRANSACTIONS ON 語句,將隱性事務模式設置為打開,下一個語句自動啟動一個新事務。當該事務完成時,再下一個 T-SQL 語句又將啟動一個新事務

自動提交事務:這是 SQL Server 的默認模式,它將每條單獨的 T-SQL 語句視為一個事務,如果成功執行,則自動提交;如果錯誤,則自動回滾

二、索引

索引根據索引鍵查找定位數據行

索引:是SQL Server編排數據的內部方法。它為SQL Server提供一種方法來編排查詢數據 。

索引頁:數據庫中存儲索引的數據頁;索引頁類似於漢語字(詞)典中按拼音或筆畫排序的目錄頁。

索引的作用:通過使用索引,可以大大提高數據庫的檢索速度,改善數據庫性能。

索引類型

  唯一索引:唯一索引不允許兩行具有相同的索引值

  主鍵索引:為表定義一個主鍵將自動創建主鍵索引,主鍵索引是唯一索引的特殊類型。主鍵索引要求主鍵中的每個值是唯一的,並且不能為空

  聚集索引(Clustered):表中各行的物理順序與鍵值的邏輯(索引)順序相同,每個表只能有一個,比如:拼音

  非聚集索引(Non-clustered):非聚集索引指定表的邏輯順序。數據存儲在一個位置,索引存儲在另一個位置,索引中包含指向數據存儲位置的指針。可以有多個,小於249個,比如:偏旁

創建索引

CREATE [UNIQUE] [CLUSTERED|NONCLUSTERED] --唯一索引,聚集索引或非聚集索引
INDEX   index_name
ON table_name (column_name…)
[WITH FILLFACTOR=x]

其中:

UNIQUE表示唯一索引,可選

CLUSTERED、NONCLUSTERED表示聚集索引還是非聚集索引,可選

FILLFACTOR表示填充因子,指定一個0到100之間的值,該值指示索引頁填滿的空間所占的百分比

創建索引舉例:

USE stuDB
GO
IF EXISTS (SELECT name FROM sysindexes 
          WHERE name = 'IX_writtenExam')
   DROP INDEX stuMarks.IX_writtenExam  
/*--筆試列創建非聚集索引:填充因子為30%--*/
CREATE NONCLUSTERED INDEX IX_writtenExam
     ON stuMarks(writtenExam)
       WITH FILLFACTOR= 30
GO
/*-----指定按索引 IX_writtenExam 查詢----*/
SELECT * FROM stuMarks   with(INDEX=IX_writtenExam)
    WHERE writtenExam BETWEEN 60 AND 90

創建索引的指導原則

請按照下列標准選擇建立索引的列。

  該列用於頻繁搜索

  該列用於對數據進行排序

請不要使用下面的列創建索引:

  列中僅包含幾個不同的值。

  表中僅包含幾行。為小型表創建索引可能不太划算,因為SQL Server在索引中搜索數據所花的時間比在表中逐行搜索所花的時間更長

三、視圖

視圖是一張虛擬表,它表示一張表的部分數據或多張表的綜合數據,其結構和數據是建立在對表的查詢基礎上,視圖中並不存放數據,而是存放在視圖所引用的原始表(基表)中,同一張原始表,根據不同用戶的不同需求,可以創建不同的視圖

視圖的用途:

  篩選表中的行

  防止未經許可的用戶訪問敏感數據

  降低數據庫的復雜程度

  將多個物理數據庫抽象為一個邏輯數據庫

SQL Server中允許用戶創建視圖,在同一原始數據表的基礎上,為不同的用戶選擇不同的列,從而達到不同用戶的需求。

創建視圖語法:

CREATE VIEW view_name 
   AS
   <select語句>

舉例:

IF EXISTS (SELECT * FROM sysobjects WHERE name = 'view_stuInfo_stuMarks') 檢查視圖是否存在
DROP VIEW view_stuInfo_stuMarks 刪除視圖
GO
CREATE VIEW view_stuInfo_stuMarks 創建視圖
  AS
  SELECT 姓名=stuName,學號=stuInfo.stuNo,筆試成績 =writtenExam,機試成績=labExam,平均分=(writtenExam+labExam)/2
  FROM stuInfo LEFT JOIN stuMarks ON stuInfo.stuNo=stuMarks.stuNo
GO
SELECT * FROM view_stuInfo_stuMarks 使用視圖

 


免責聲明!

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



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