第六章 SQL定義和使用視圖

第六章 SQL定義和使用視圖

視圖是一種虛擬表,由執行時通過SELECT語句或幾個SELECT語句的UNION從一個或多個物理表中檢索到的數據組成。 SELECT可以通過指定表或其他視圖的任意組合來訪問數據。因此,存儲了視圖的視圖提供了物理表的所有靈活性和安全性特權。

InterSystemsIRIS?數據平臺上的InterSystems SQL支持在視圖上定義和執行查詢的功能。

注意:不能對以只讀方式安裝的數據庫中存儲的數據創建視圖。
無法在通過ODBC或JDBC網關連接鏈接的Informix表中存儲的數據上創建視圖。這是因為InterSystems IRIS查詢轉換對這種類型的查詢使用FROM子句中的子查詢。 Informix不支持FROM子句子查詢。

創建一個視圖

可以通過幾種方式定義視圖:

  • 使用SQL CREATE VIEW命令(在DDL腳本中或通過JDBC或ODBC)。
  • 使用管理門戶的“創建視圖”界面。

視圖名稱:不合格的視圖名稱是一個簡單的標識符:MyView。合格的視圖名稱由兩個簡單的標識符組成,即模式名稱和視圖名稱,以句點分隔:MySchema.MyView。視圖名稱和表名稱遵循相同的命名約定,并對不合格的名稱執行相同的架構名稱解析。同一模式中的視圖和表不能具有相同的名稱。

可以使用$SYSTEM.SQL.ViewExists()方法確定視圖名稱是否已存在。此方法還返回投影視圖的類名稱。可以使用$SYSTEM.SQL.TableExists()方法確定表名是否已存在。

視圖可用于創建表的受限子集。以下嵌入式SQL示例創建一個視圖,該視圖限制了可以通過該視圖訪問的原始表的行(通過WHERE子句)和列(假設Sample.Person包含兩個以上的列):

/// d ##class(PHA.TEST.SQL).View()
ClassMethod View()
{
    &sql(CREATE VIEW Sample.VSrStaff 
        AS SELECT Name AS Vname,Age AS Vage
        FROM Sample.Person WHERE Age>75)
    IF SQLCODE=0 {
        WRITE "創建一個視圖",!
    } ELSEIF SQLCODE=-201 {
        WRITE "視圖已經存在",!
    } ELSE {
        WRITE "SQL報錯: ",SQLCODE," ",%msg,! 
    }
}
DHC-APP>d ##class(PHA.TEST.SQL).View()
創建一個視圖
image.png

以下嵌入式SQL示例基于SalesPeople表創建一個視圖,并創建一個新的計算值列TotalPay

/// d ##class(PHA.TEST.SQL).View1()
ClassMethod View1()
{
    &sql(CREATE VIEW Sample.VSalesPay AS
        SELECT Name,(Salary + Commission) AS TotalPay
        FROM Sample.SalesPeople)
    IF SQLCODE=0 {
        WRITE "創建一個視圖",!
    } ELSEIF SQLCODE=-201 {
        WRITE "視圖已經存在",!
    } ELSE {
        WRITE "SQL報錯: ",SQLCODE," ",%msg,! 
    }
}

管理門戶創建視圖界面

可以從管理門戶創建視圖。轉到InterSystems IRIS管理門戶。在系統資源管理器中,選擇SQL。使用頁面頂部的Switch選項選擇一個名稱空間;這將顯示可用名稱空間的列表。選擇名稱空間后,單擊“操作”下拉列表,然后選擇“創建視圖”。

image.png

這將顯示“創建視圖”窗口,其中包含以下字段:

  • 模式:可以決定將視圖包含在現有模式中,也可以創建一個新模式。如果選擇選擇現有模式,則會提供一個現有模式的下拉列表。如果選擇創建新架構,請輸入架構名稱。在這兩種情況下,如果省略模式,則InterSystems IRIS都會使用系統范圍內的默認模式名稱。
  • 視圖名稱:有效的視圖名稱。不能對同一模式中的表和視圖使用相同的名稱。
  • 使用Check Option:選項為READONLYLOCALCASCADED
  • 將視圖的所有特權授予_PUBLIC:如果選中,則此選項為該視圖授予所有用戶執行特權。默認設置是不授予所有用戶訪問該視圖的權限。
  • 查看文字:可以通過以下三種方式中的任意一種來指定查看文字:
    • 在“查看文本”區域中鍵入SELECT語句。
    • 使用查詢生成器創建SELECT語句,然后按OK將此查詢提供給“查看文本”區域。
    • 如果在Management Portal SQL界面的左側選擇了一個緩存查詢名稱(例如%sqlcq.USER.cls4),然后調用Create View,則該緩存查詢將提供給“視圖文本”區域。請注意,在保存視圖文本之前,必須在“視圖文本”區域中用實際值替換主機變量引用。
image.png

視圖和相應的類

定義視圖時,InterSystems IRIS會生成一個相應的類。按照名稱轉換規則,SQL視圖名稱用于生成相應的唯一類名稱。 Management Portal SQL界面顯示現有視圖的“目錄詳細信息”,包括此類名稱。

修改視圖

在Management Portal SQL界面中,可以選擇一個現有視圖以顯示該視圖的“目錄詳細信息”。 “目錄詳細信息視圖信息”選項顯示“編輯視圖”鏈接,該鏈接提供了用于編輯視圖文本(視圖的SELECT語句)的界面。它還提供了一個下拉列表,以將“帶檢查選項”選擇為無,READONLYLOCALCASCADED

可更新的視圖

可更新的視圖是可以在其上執行INSERTUPDATEDELETE操作的視圖。僅當滿足以下條件時,才認為視圖是可更新的:

  • 視圖查詢的FROM子句僅包含一個表引用。該表引用必須標識可更新的基表或可更新的視圖。
  • 視圖查詢的SELECT列表中的值表達式必須全部是列引用。
  • 視圖的查詢中不得指定GROUP BYHAVINGSELECT DISTINCT
  • 該視圖不是投影為視圖的類查詢。
  • 視圖的類不包含類參數READONLY = 1(如果視圖定義包含WITH READ ONLY子句,則為true)。

WITH CHECK選項

為了防止在視圖上執行INSERTUPDATE操作,而該操作會導致基礎基表中的行不屬于派生視圖表的一部分,InterSystems SQL在視圖定義中支持WITH CHECK OPTION子句。此子句只能與可更新視圖一起使用。

WITH CHECK OPTION子句指定可更新視圖上的任何INSERTUPDATE操作必須對照視圖定義的WHERE子句驗證結果行,以確保插入或修改的行將成為派生視圖表的一部分。

例如,以下DDL語句定義了一個可更新的GoodStudent視圖,其中包含所有具有高GPA(平均績點)的學生:

CREATE VIEW GoodStudent AS
    SELECT Name, GPA
      FROM Student
        WHERE GPA > 3.0
    WITH CHECK OPTION

由于視圖包含WITH CHECK OPTION,因此任何嘗試在GPA值小于或等于3.0的GoodStudent視圖中插入或更新行都將失敗(此類行將不表示“好學生”)。

有兩種類型的WITH CHECK選項:

  • WITH LOCAL CHECK選項意味著只檢查INSERTUPDATE語句中指定的視圖的WHERE子句。
  • 與級聯檢查選項(和級聯檢查選項)意味著視圖的WHERE子句中指定的INSERTUPDATE語句以及所有視圖檢查基于這一觀點,無論外表或與當地檢查沒有其他選項在這些視圖定義條款。

如果指定了just WITH CHECK選項,默認值是級聯的。

在更新或插入期間,在為基礎表的字段計算了所有默認值和觸發的計算字段之后,并在常規表驗證(必需字段、數據類型驗證、約束等)之前,檢查WITH CHECK選項條件。

WITH CHECK選項驗證通過后,插入或更新操作繼續進行,就像在基表本身上執行插入或更新一樣。
檢查所有約束,拉出觸發器,等等。

如果在INSERTUPDATE語句中指定了%NOCHECK選項,則不檢查WITH CHECK選項的有效性。

有兩個與WITH CHECK選項驗證相關的SQLCODE值(插入/更新會導致派生視圖表中不存在一行):

  • SQLCODE -136-INSERT中視圖的WITH CHECK OPTION驗證失敗。
  • SQLCODE -137-視圖的WITH CHECK OPTION驗證在UPDATE中失敗。

只讀視圖

只讀視圖是不能在其上執行INSERTUPDATEDELETE操作的視圖。任何不符合可更新視圖標準的視圖都是只讀視圖。

視圖定義可以指定WITH READ ONLY子句,以強制其成為只讀視圖。

如果嘗試針對只讀視圖編譯/準備INSERTUPDATEDELETE語句,則會生成SQLCODE -35錯誤。

查看ID:%VID

InterSystems IRIS為視圖或FROM子句子查詢返回的每一行分配一個整數視圖ID%VID)。與表行ID號一樣,這些視圖行ID號是系統分配的,唯一的,非空的,非零的和不可修改的。該%VID通常對用戶不可見,并且僅在明確指定時返回。它以數據類型INTEGER返回。因為%VID值是順序整數,所以如果視圖返回有序數據,它們將更有意義。視圖與TOP子句配對時,只能使用ORDER BY子句。以下嵌入式SQL示例創建一個名為VSrStaff的視圖:

/// d ##class(PHA.TEST.SQL).View()
ClassMethod View()
{
    &sql(CREATE VIEW Sample.VSrStaff 
        AS SELECT Name AS Vname,Age AS Vage
        FROM Sample.Person WHERE Age>75)
    IF SQLCODE=0 {
        WRITE "創建一個視圖",!
    } ELSEIF SQLCODE=-201 {
        WRITE "視圖已經存在",!
    } ELSE {
        WRITE "SQL報錯: ",SQLCODE," ",%msg,! 
    }
}

下面的示例返回VSrStaff視圖定義的所有數據(使用SELECT *),并且還指定應返回每一行的視圖ID。與表行ID不同,使用星號語法時不顯示視圖行ID。僅當在SELECT中明確指定時才顯示:

SELECT *,%VID AS ViewID FROM Sample.VSrStaff
image.png

%VID可用于進一步限制SELECT從視圖返回的行數,如以下示例所示:

SELECT *,%VID AS ViewID FROM Sample.VSrStaff WHERE %VID BETWEEN 5 AND 10
image.png

因此,可以使用%VID代替TOP(或除TOP之外)來限制查詢返回的行數。通常,TOP子句用于返回數據記錄的一小部分。 %VID用于返回大多數或所有數據記錄,以小的子集返回記錄。此功能可能很有用,尤其是對于移植Oracle查詢(%VID輕松映射到Oracle ROWNUM)而言。但是,與TOP相比,用戶應了解使用%VID時的一些性能限制:

  • %VID不執行第一行時間優化。 TOP優化為盡快返回第一行數據。 %VID優化以盡快返回完整的數據集。
  • 如果查詢指定排序的結果,則%VID不會執行有限的排序(這是TOP進行的特殊優化)。該查詢首先對完整的數據集進行排序,然后使用%VID限制返回數據集。 TOP是在排序之前應用的,因此SELECT只能執行有限的排序,僅涉及有限的行子集。

為了節省第一行優化和有限排序優化的時間,可以將FROM子句子查詢與TOP%VID結合使用。在FROM子查詢中指定上限(在本例中為10)作為TOP的值,而不是使用TOP ALL。使用%VIDWHERE子句中指定下限(在這種情況下,> 4)。以下示例使用此策略返回與上一個視圖查詢相同的結果:

SELECT *,%VID AS SubQueryID
   FROM (SELECT TOP 10 Name,Age 
         FROM Sample.Person
         WHERE Age > 75
         ORDER BY Name)
   WHERE %VID > 4
image.png

即使顯式指定了%PARALLEL關鍵字,也無法對指定%VID的查詢執行并行執行。

List視圖屬性

INFORMATION.SCHEMA.VIEWS持久類顯示有關當前名稱空間中所有視圖的信息。它提供了許多屬性,包括視圖定義,視圖的所有者以及創建和最后修改視圖時的時間戳。這些屬性還包括視圖是否可更新,如果可更新,是否使用檢查選項定義。

在嵌入式SQL中指定時,INFORMATION.SCHEMA.VIEWS需要#include%occInclude宏預處理程序指令。 Dynamic SQL不需要此偽指令。

VIEWDEFINITION屬性(SqlFieldName = VIEW_DEFINITION)以字符串形式返回當前名稱空間中所有視圖的視圖字段名稱和視圖查詢表達式。例如,

SELECT View_Definition FROM INFORMATION_SCHEMA.VIEWS
image.png

返回諸如“(vName,vAge)SELECT Name,Age FROM Sample.Person WHERE Age> 21”的字符串。當從Management Portal SQL執行查詢界面發出時,此字符串的顯示僅限于前100個字符,其中不包括空格和換行符,并且(如有必要)附加表示省略號的省略號(...)。否則,發出此查詢將為每個視圖返回最多1048576個字符的字符串,在視圖字段列表和查詢文本之間有一個換行符,并保留了視圖查詢表達式中指定的空格,并(如有必要)附加了省略號(...)表示內容被截斷。

以下示例返回當前名稱空間中所有視圖的視圖名稱(Table_Name字段)和所有者名稱:

SELECT Table_Name,Owner FROM INFORMATION_SCHEMA.VIEWS
image.png

以下示例返回當前名稱空間中所有非系統視圖的所有信息:

SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE Owner != '_SYSTEM'
image.png

INFORMATION.SCHEMA.VIEWCOLUMNUSAGE持久性類顯示當前名稱空間中每個視圖的源表字段的名稱:

SELECT * FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE WHERE View_Name='VSrStaff'
image.png

可以使用管理門戶網站SQL界面中的“目錄詳細信息”選項卡為單個視圖顯示與INFORMATION.SCHEMA.VIEWS相同的信息。視圖的“目錄詳細信息”包括每個視圖字段的定義(數據類型,最大長度,最小值/最大值等),以及INFORMATION.SCHEMA視圖類未提供的詳細信息。 “目錄詳細信息”視圖信息顯示還提供了用于編輯視圖定義的選項。

列出視圖依賴

INFORMATION.SCHEMA.VIEWTABLEUSAGE持久類顯示當前名稱空間中的所有視圖及其依賴的表。在下面的示例中顯示:

SELECT View_Schema,View_Name,Table_Schema,Table_Name FROM INFORMATION_SCHEMA.VIEW_TABLE_USAGE
image.png

可以調用%Library.SQLCatalog.SQLViewDependsOn類查詢以列出指定視圖所依賴的表。可以為此類查詢指定schema.viewname。如果僅指定視圖名稱,則它將使用系統范圍的默認架構名稱。調用者必須具有指定視圖的特權才能執行此類查詢。在下面的示例中顯示:

/// d ##class(PHA.TEST.SQL).View3()
ClassMethod View3()
{
    SET statemt=##class(%SQL.Statement).%New()
    SET cqStatus=statemt.%PrepareClassQuery("%Library.SQLCatalog","SQLViewDependsOn")
    IF cqStatus'=1 {
        WRITE "%PrepareClassQuery failed:" DO $System.Status.DisplayError(cqStatus) QUIT
    }
    SET rset=statemt.%Execute("vschema.vname")
    DO rset.%Display()
}

DHC-APP>d ##class(PHA.TEST.SQL).View3()
 
 
Dumping result #1
SCHEMA  TABLE_NAME
 
0 Rows(s) Affected

SQLViewDependsOn查詢列出了視圖所依賴的表,并列出了表架構和表名。如果調用者沒有該視圖所依賴的表的特權,則該表及其模式將列為<NOT PRIVILEGED>。這允許沒有表特權的調用者確定視圖所依賴的表數量,而不是表的名稱。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容