在Oracle資料庫中,可以利用Create Table語句中巢狀子查詢來實現基於已有的表或者檢視來建立新表。這個功能可能對於大部分使用者來說,不會感到陌生。但是在使用這個語句的過程中,需要遵循哪些限制條件呢?對於這一點,可能不少資料庫管理員沒有一個清晰的認識。
為此,筆者就在這裡給大家總結一下,利用查詢來建立表時需要遵守的一些限制。
限制條件一:不能夠改變資料型別與長度。
在利用子查詢來建立新表的時候,資料庫管理員可以修改新表中列的名稱,但是不能夠修改列的資料型別和長度。新表中所有列的資料型別和長度必須與查詢列一致。
如資料庫管理員從一個員工資訊表中獲取員工姓名、員工出生日期等資訊建立一個新表。如果在員工資訊表中員工出生日期是一個日期型的欄位,那麼在新表中就必須也是日期型的資料型別。在建立新表的過程中,資料庫管理員不能夠修改資料型別。
那麼如果系統管理員需要更改資料型別,如想把日期型的資料調整為字元型的資料,難道就沒有其他辦法了嗎?其實,透過一些其他方法,這個需求仍然可以實現。
上面的限制條件說,新表中的資料型別必須與查詢列中的資料型別相同,而不是說跟基表中的資料型別相同。為此如果資料庫管理員想要把日期型的資料(基表中的資料型別)調整為字元型的資料型別(新表中的資料型別),那麼只需要在查詢語句中,利用日期字元轉換函式,將日期型的資料轉換為字元型的資料即可。
在建立新表時,資料型別是以查詢列為準,而不是以基表中列的資料型別為準。所以透過在查詢語句中使用資料型別轉換函式,就可以改變新表中的資料型別。
限制條件二:不能夠複製約束條件與列的預設值。
在基表中,可能某些欄位有約束條件,如唯一性約束等等。
某些欄位也可能設定了預設值,如系統的當前時間等等。但是,如果利用子查詢來建立信標的話,那麼這些欄位的約束條件、預設值等等都不會在新表中體現出來。也就是說,這些內容需要資料庫管理員在新表建立後手工重新建立。如果有需要的話,要對照基表的約束條件與預設值,分別在新表的欄位中進行定義。
這個沒有取巧的方法。至少到限制為止,筆者還沒有找到可以利用其他方法來突破這個限制。為此資料庫管理員在利用子查詢來建立這個新表的時候,要特別注意這個約束條件。特別是預設值,不少管理員在利用這個方法建立新表後,會忘記重新設定相關列的預設值。
限制條件三:不能夠為新表指定表空間。
在正常情況下,利用Create建立表的時候,資料庫管理員可以為表指定其所屬的表空間。如果不指定的話,則其預設情況下采用的是當前使用者的預設表空間。但是在使用查詢來建立新表的時候,在語句中不能夠為新表指定表空間。如使用TableSpace關鍵字為其指定表空間的話,則系統會提示錯誤資訊:SQL命令未正確結束。
注意這並不是說這個SQL語句哪裡有問題,而是指不能夠在這種方式下為新表指定表空間。從這裡也可以看出,Oracle資料庫系統的錯誤提示還是有模稜兩可的地方,還需要改進,即錯誤資訊要能夠反映出真實的問題所在。因為不能夠為新表指定表空間,此時其所屬的表空間就是執行這條語句的使用者的預設表空間。
那麼資料庫管理員就可以透過採用不同的使用者來為新表指定所屬的表空間。如現在資料庫管理員要想把這個新表放置在sales表空間下。那麼就可以新建一個使用者或者利用原有的使用者,先把這個使用者的預設表空間設定為sales。然後再利用這個使用者來執行這條語句(必要的時候可能需要調整這個使用者的許可權)。
透過這種方式就可以控制這種形式建立新表所屬的表空間。俗話說,條條道路通羅馬。既然不能夠利用直接的方式來為這新表設定表空間,那麼就只能夠採取這曲線救國的方法了。只要最終能夠達到預計的目的就好。
限制條件四:某些資料型別的資料不能夠匯入。
如果在查詢結果中,帶有大物件資料型別或者Long資料型別的資料,則這個語句就會執行不成功。
換句話說,如果採用子查詢來建立新表,則在Select語句中就不能夠包含大物件資料型別或者Long資料型別。這是Oracle資料庫的一種強制性規定。如果確實需要這些資料的話,則可以採用其它的方式來解決。如先不匯入這些型別的資料。先利用子查詢把表建立起來。
等新表建立完成後。再利用Update關鍵字結合子查詢來更新這些列的資料即可。雖然這麼操作比較麻煩一點,但是總比不能夠實現要好。
在使用這種方法建立新表時,除了要注意上面這些限制條件之外,最好再掌握下面這些技巧。這有助於提高透過查詢來建立新表的利用價值。
技巧一:使用Nologging選項提高建表效率。
Nologging這個可選項相信大部分資料庫管理員都知道其作用。但是到真的需要用到這個選項時,很多人就忘記了。這個選項主要是用來控制重做日誌的。即在對資料庫進行相關的操作時,是否需要日誌檔案中寫入相關的記錄。
因為日誌檔案是一把雙刃劍。一方面王日誌檔案中記錄所有的操作,有利於資料庫的安全。當出現一些錯誤的操作時,可以透過恢復事務日誌挽回損失。另一方面,由於資料庫同時需要更新資料、更新事務日誌資訊,為此當對資料庫進行大批次的操作時,就會降低這個操作的效能,延長時間。
透過查詢來建立新表是也遇到了類似的問題。因為在利用子查詢建立新表時,如果不採用這個選項的話,則在新表中每插入一條記錄都將會產生重做日誌資訊,這會佔用額外的空間與時間。如果插入的記錄比較多的話,這會給資料庫的正常執行帶來很大的負面影響。在大部分情況下,筆者建議使用Nologging選項來節省建立新表的時間。
因為透過子查詢來建立新表,基本上不會對基表的內容產生任何不利的影響。所以即使不用重做日誌,也不會帶來多大的風險。換句話話說,此時投入與產出不成正比。也就是說,此時犧牲效能,來換取所謂的安全,是不值得的。因為不影響其它表的資料,所以風險基本上就談不上。
在這種情況下,採用Nologging選項,讓資料庫在建立記錄的時候,不往事務日誌中記錄資訊,以縮短建立新表的時間。筆者認為這是非常明智的做法。
技巧二:利用查詢來建立表結構,不匯入資料。
有時候我們需要複製表的結構,而不需要複製資料。在PL Developer開發工具中,可以直接複製某張表。
但是這麼操作的話,除了會複製表的結構外,還會把相關的資料都複製過去。顯然,這不符合我們的要求。而表中的紀錄比較多的時候,這個複製作業就會佔用比較長的時間與資料庫伺服器的資源,會給資料庫的效能帶來不利的影響。那麼是否有方法,可以只複製表的結構,而不匯入任何資料呢?
在談這個解決方案之前,大家先來回顧一下Select語句。
在使用Select語句中,可以帶Where條件語句。如果要查詢的記錄沒有一條記錄符合Where條件中規定的限制條件時,則在顯示視窗,仍然會顯示要查詢的各個列的名稱。但是不會顯示任何一條記錄。現在要複製表的結構,而不需要匯入任何資料,就可以參考這種實現機制來完成。
其實要實現這個需求的話,資料庫管理員就可以利用透過查詢來建立新表的方法。如先利用Select語句將相關的列等結構查詢出來,然後再在Where查詢語句中,設定一些根本不存在的條件。如此的話,最終的新表中就只有表的結構,而沒有任何基礎表中的紀錄。
可見,雖然透過子查詢來建立新表是一項比較強大的功能,可以實現一些複雜的管理需求。但是在使用這個功能的時候,上面對這些限制條件資料庫管理員要銘記在心。否則的話,很可能在使用這項功能的時候,四處碰壁;或者最後竹籃子打水一場空。
在Oracle資料庫中,可以利用Create Table語句中巢狀子查詢來實現基於已有的表或者檢視來建立新表。這個功能可能對於大部分使用者來說,不會感到陌生。但是在使用這個語句的過程中,需要遵循哪些限制條件呢?對於這一點,可能不少資料庫管理員沒有一個清晰的認識。
為此,筆者就在這裡給大家總結一下,利用查詢來建立表時需要遵守的一些限制。
限制條件一:不能夠改變資料型別與長度。
在利用子查詢來建立新表的時候,資料庫管理員可以修改新表中列的名稱,但是不能夠修改列的資料型別和長度。新表中所有列的資料型別和長度必須與查詢列一致。
如資料庫管理員從一個員工資訊表中獲取員工姓名、員工出生日期等資訊建立一個新表。如果在員工資訊表中員工出生日期是一個日期型的欄位,那麼在新表中就必須也是日期型的資料型別。在建立新表的過程中,資料庫管理員不能夠修改資料型別。
那麼如果系統管理員需要更改資料型別,如想把日期型的資料調整為字元型的資料,難道就沒有其他辦法了嗎?其實,透過一些其他方法,這個需求仍然可以實現。
上面的限制條件說,新表中的資料型別必須與查詢列中的資料型別相同,而不是說跟基表中的資料型別相同。為此如果資料庫管理員想要把日期型的資料(基表中的資料型別)調整為字元型的資料型別(新表中的資料型別),那麼只需要在查詢語句中,利用日期字元轉換函式,將日期型的資料轉換為字元型的資料即可。
在建立新表時,資料型別是以查詢列為準,而不是以基表中列的資料型別為準。所以透過在查詢語句中使用資料型別轉換函式,就可以改變新表中的資料型別。
限制條件二:不能夠複製約束條件與列的預設值。
在基表中,可能某些欄位有約束條件,如唯一性約束等等。
某些欄位也可能設定了預設值,如系統的當前時間等等。但是,如果利用子查詢來建立信標的話,那麼這些欄位的約束條件、預設值等等都不會在新表中體現出來。也就是說,這些內容需要資料庫管理員在新表建立後手工重新建立。如果有需要的話,要對照基表的約束條件與預設值,分別在新表的欄位中進行定義。
這個沒有取巧的方法。至少到限制為止,筆者還沒有找到可以利用其他方法來突破這個限制。為此資料庫管理員在利用子查詢來建立這個新表的時候,要特別注意這個約束條件。特別是預設值,不少管理員在利用這個方法建立新表後,會忘記重新設定相關列的預設值。
限制條件三:不能夠為新表指定表空間。
在正常情況下,利用Create建立表的時候,資料庫管理員可以為表指定其所屬的表空間。如果不指定的話,則其預設情況下采用的是當前使用者的預設表空間。但是在使用查詢來建立新表的時候,在語句中不能夠為新表指定表空間。如使用TableSpace關鍵字為其指定表空間的話,則系統會提示錯誤資訊:SQL命令未正確結束。
注意這並不是說這個SQL語句哪裡有問題,而是指不能夠在這種方式下為新表指定表空間。從這裡也可以看出,Oracle資料庫系統的錯誤提示還是有模稜兩可的地方,還需要改進,即錯誤資訊要能夠反映出真實的問題所在。因為不能夠為新表指定表空間,此時其所屬的表空間就是執行這條語句的使用者的預設表空間。
那麼資料庫管理員就可以透過採用不同的使用者來為新表指定所屬的表空間。如現在資料庫管理員要想把這個新表放置在sales表空間下。那麼就可以新建一個使用者或者利用原有的使用者,先把這個使用者的預設表空間設定為sales。然後再利用這個使用者來執行這條語句(必要的時候可能需要調整這個使用者的許可權)。
透過這種方式就可以控制這種形式建立新表所屬的表空間。俗話說,條條道路通羅馬。既然不能夠利用直接的方式來為這新表設定表空間,那麼就只能夠採取這曲線救國的方法了。只要最終能夠達到預計的目的就好。
限制條件四:某些資料型別的資料不能夠匯入。
如果在查詢結果中,帶有大物件資料型別或者Long資料型別的資料,則這個語句就會執行不成功。
換句話說,如果採用子查詢來建立新表,則在Select語句中就不能夠包含大物件資料型別或者Long資料型別。這是Oracle資料庫的一種強制性規定。如果確實需要這些資料的話,則可以採用其它的方式來解決。如先不匯入這些型別的資料。先利用子查詢把表建立起來。
等新表建立完成後。再利用Update關鍵字結合子查詢來更新這些列的資料即可。雖然這麼操作比較麻煩一點,但是總比不能夠實現要好。
在使用這種方法建立新表時,除了要注意上面這些限制條件之外,最好再掌握下面這些技巧。這有助於提高透過查詢來建立新表的利用價值。
技巧一:使用Nologging選項提高建表效率。
Nologging這個可選項相信大部分資料庫管理員都知道其作用。但是到真的需要用到這個選項時,很多人就忘記了。這個選項主要是用來控制重做日誌的。即在對資料庫進行相關的操作時,是否需要日誌檔案中寫入相關的記錄。
因為日誌檔案是一把雙刃劍。一方面王日誌檔案中記錄所有的操作,有利於資料庫的安全。當出現一些錯誤的操作時,可以透過恢復事務日誌挽回損失。另一方面,由於資料庫同時需要更新資料、更新事務日誌資訊,為此當對資料庫進行大批次的操作時,就會降低這個操作的效能,延長時間。
透過查詢來建立新表是也遇到了類似的問題。因為在利用子查詢建立新表時,如果不採用這個選項的話,則在新表中每插入一條記錄都將會產生重做日誌資訊,這會佔用額外的空間與時間。如果插入的記錄比較多的話,這會給資料庫的正常執行帶來很大的負面影響。在大部分情況下,筆者建議使用Nologging選項來節省建立新表的時間。
因為透過子查詢來建立新表,基本上不會對基表的內容產生任何不利的影響。所以即使不用重做日誌,也不會帶來多大的風險。換句話話說,此時投入與產出不成正比。也就是說,此時犧牲效能,來換取所謂的安全,是不值得的。因為不影響其它表的資料,所以風險基本上就談不上。
在這種情況下,採用Nologging選項,讓資料庫在建立記錄的時候,不往事務日誌中記錄資訊,以縮短建立新表的時間。筆者認為這是非常明智的做法。
技巧二:利用查詢來建立表結構,不匯入資料。
有時候我們需要複製表的結構,而不需要複製資料。在PL Developer開發工具中,可以直接複製某張表。
但是這麼操作的話,除了會複製表的結構外,還會把相關的資料都複製過去。顯然,這不符合我們的要求。而表中的紀錄比較多的時候,這個複製作業就會佔用比較長的時間與資料庫伺服器的資源,會給資料庫的效能帶來不利的影響。那麼是否有方法,可以只複製表的結構,而不匯入任何資料呢?
在談這個解決方案之前,大家先來回顧一下Select語句。
在使用Select語句中,可以帶Where條件語句。如果要查詢的記錄沒有一條記錄符合Where條件中規定的限制條件時,則在顯示視窗,仍然會顯示要查詢的各個列的名稱。但是不會顯示任何一條記錄。現在要複製表的結構,而不需要匯入任何資料,就可以參考這種實現機制來完成。
其實要實現這個需求的話,資料庫管理員就可以利用透過查詢來建立新表的方法。如先利用Select語句將相關的列等結構查詢出來,然後再在Where查詢語句中,設定一些根本不存在的條件。如此的話,最終的新表中就只有表的結構,而沒有任何基礎表中的紀錄。
可見,雖然透過子查詢來建立新表是一項比較強大的功能,可以實現一些複雜的管理需求。但是在使用這個功能的時候,上面對這些限制條件資料庫管理員要銘記在心。否則的話,很可能在使用這項功能的時候,四處碰壁;或者最後竹籃子打水一場空。