日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

CREATE TYPE

CREATE TYPE用于在當前數據庫中注冊一個新的用戶定義數據類型。

簡介

CREATE TYPE用于在當前數據庫中注冊一個新的用戶定義數據類型。執行此命令的用戶自動成為新數據類型的擁有者。該命令允許用戶為數據庫創建具有特定屬性和行為的自定義數據結構。

如果在執行CREATE TYPE命令時指定了一個模式名稱,那么新創建的數據類型將位于該指定模式內。如果沒有指定模式名稱,則該數據類型將默認被創建在當前激活的模式下。

說明

新創建的類型名必須在同一模式內是唯一的,即它不能與該模式中已存在的任何其他類型、域或者表的名稱重復。這是因為表在數據庫中也被看作是一種數據類型,所以數據類型的名稱必須在其所屬模式中保持唯一,以避免任何潛在的命名沖突。

CREATE TYPE命令有五種不同的變體。這五種變體分別用于創建如下類型:組合類型(composite type)、枚舉類型(enumerated type)、范圍類型(range type)、基礎類型(base type),以及shell類型。本文將詳細討論前四種類型的創建方法。至于shell類型,它實質上是一個占位符,用于預留一個名稱供將來定義的類型使用。這個占位符可以通過發布一個CREATE TYPE命令并僅帶有類型名稱來創建,不需要其他參數。當創建范圍類型和基礎類型時,shell類型用作一種前向引用,這樣可以在實際定義類型的細節之前就預先聲明其存在。

語法

   CREATE [ OR REPLACE ] TYPE name AS
    ( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] );

CREATE TYPE name AS ENUM
    ( [ 'label' [, ... ] ] );

CREATE TYPE name AS RANGE (
    SUBTYPE = subtype
    [ , SUBTYPE_OPCLASS = subtype_operator_class ]
    [ , COLLATION = collation ]
    [ , CANONICAL = canonical_function ]
    [ , SUBTYPE_DIFF = subtype_diff_function ]
);

CREATE TYPE name (
    INPUT = input_function,
    OUTPUT = output_function
    [ , RECEIVE = receive_function ]
    [ , SEND = send_function ]
    [ , TYPMOD_IN = type_modifier_input_function ]
    [ , TYPMOD_OUT = type_modifier_output_function ]
    [ , ANALYZE = analyze_function ]
    [ , INTERNALLENGTH = { internallength | VARIABLE } ]
    [ , PASSEDBYVALUE ]
    [ , ALIGNMENT = alignment ]
    [ , STORAGE = storage ]
    [ , LIKE = like_type ]
    [ , CATEGORY = category ]
    [ , PREFERRED = preferred ]
    [ , DEFAULT = default ]
    [ , ELEMENT = element ]
    [ , DELIMITER = delimiter ]
    [ , COLLATABLE = collatable ]
);

CREATE TYPE name;

組合類型

使用CREATE TYPE命令的第一種形式可以創建組合類型(composite types)。這種類型由一組屬性名組成,每個屬性名都與一個特定的數據類型相關聯。如果屬性的數據類型支持排序操作,則還可以為每個屬性指定一個排序規則。組合類型在本質上與表結構的行類型相似,不過使用CREATE TYPE創建組合類型可以避免實際上創建一個完整的表。

在創建組合類型時,可以選擇性地使用OR REPLACE子句。當包含這個子句時,如果數據庫中已經存在一個與你想要創建的組合類型同名的類型,那么現有的類型將會被新定義的類型替換。這樣的功能允許你更新一個已存在的組合類型的定義而不需要事先手動刪除舊的類型,從而簡化了類型維護的過程。

說明

使用OR REPLACE時應當小心,因為這會覆蓋原有類型的定義,可能會影響依賴于該類型的數據庫對象。

組合類型可以用作函數的參數類型或返回類型,提供一種定義復雜結構的便捷方式,而不必為此創建一張新的表。組合類型的這種特性使得它在數據庫設計中非常靈活且實用,尤其是在需要傳遞多個值作為一個整體時,或者當函數需要返回多個值而不僅僅是一個簡單數據類型的值時。

為了成功創建一個組合類型,創建者必須具備在該組合類型的所有屬性數據類型上的USAGE權限。

枚舉類型

使用CREATE TYPE命令的第二種形式可以創建枚舉類型(enumerated type)。枚舉類型是由一系列預定義的標簽組成,這些標簽在創建時必須用引號包圍。每個標簽的長度不得超過NAMEDATALEN字節的限制,通常是64字節。

盡管可以創建一個不包含任何標簽的枚舉類型,但在對該類型使用ALTER TYPE命令并添加至少一個標簽之前,您將無法使用該枚舉類型存儲任何值。即一個空的枚舉類型在添加枚舉值之前,無法在實際數據庫操作中使用。該特性提供了枚舉類型的靈活擴展性,允許數據庫設計者在初始定義枚舉類型時不必立即確定所有可能的枚舉值,而是可以隨著應用需求的變化逐漸添加新的枚舉值。

范圍類型

使用CREATE TYPE命令的第三種形式可以創建范圍類型(range type)。范圍類型允許用戶表示一個連續區間,該區間內的值是基于某個子類型定義的。所謂的subtype是構成范圍的基本數據類型,它必須有對應的B樹操作符類來決定范圍值的順序。大多數情況下,子類型的默認B樹操作符類會被用作排序依據。若需使用非默認操作符類進行排序,可以通過subtype_opclass選項來指明其名稱。如果子類型是可排序的,并且需要應用非默認的排序規則于范圍類型值,可以用collation選項指定相應的排序規則。

創建范圍類型時,還可以定義一個可選的canonical函數,該函數接受一個范圍類型的參數并返回同類型的規范化值。這個函數用來將范圍值轉換為其規范形式。然而,創建canonical函數有一定難度,因為它需要在范圍類型聲明前定義好。為了實現這一點,必須先創建一個所謂的shell類型,這是一種只有名稱和所有者而沒有具體屬性的占位符類型,可以通過執行CREATE TYPE name命令(不帶其他參數)來創建。創建之后,可以使用該shell類型來聲明canonical函數的參數和返回類型。最后,當聲明實際的范圍類型時用同樣的名稱,系統將自動將shell類型占位符替換為完整定義的范圍類型。

另一個可選的功能是定義subtype_diff函數,它接受兩個子類型值作為參數,并返回一個double precision類型的值來表示兩個值之間的差異。雖然這不是必須的,但提供subtype_diff函數可以提高在該范圍類型的列上使用GiST索引的效率。

基礎類型

CREATE TYPE命令的第四種形式用于創建新的基礎類型,也稱為標量類型。創建一個新的基礎類型是一項高權限操作,因此要求執行者必須是數據庫的超級用戶。這樣的權限要求是為了安全考慮——如果類型定義不當,可能會導致服務器出現錯誤行為乃至崩潰。

在定義新的基礎類型時,參數可以按任何順序出現,并不局限于在語法說明中展示的順序,而且其中大多數參數是可選的。但在定義這個類型之前,必須已經使用CREATE FUNCTION命令注冊了至少兩個函數。其中,input_functionoutput_function這兩個支持函數是創建新基礎類型時的必要條件。另外,receive_functionsend_functiontype_modifier_input_functiontype_modifier_output_functionanalyze_function這些函數則是可選的。

一般而言,這些函數需要使用C語言或其他低級語言編寫,因為他們必須能夠在底層與數據庫系統緊密配合,以處理數據類型的輸入、輸出、接收、發送和分析等操作。這些函數的編寫和注冊是創建新基礎類型過程中最為技術性的部分,他們確保了新類型能夠在數據庫系統中正常工作。

input_function是將用戶定義類型的外部文本表示轉換為數據庫內部使用的格式,這種內部格式適用于該類型定義的所有操作符和函數。output_function則執行相反的轉換過程,把內部格式轉換回可讀的文本表示。輸入函數可以接受一個單一的cstring類型參數,或者接受三個參數,類型分別為cstringoid(對象標識符)和integer。第一個參數是輸入文本的C字符串形式,第二個參數是該類型本身的OID,或者對于數組類型來說,是其元素類型的 OID;第三個參數是目標列的類型修飾符typmod(如果此信息未知,則會傳遞值-1) 。輸入函數必須返回對應的新數據類型值。通常,輸入函數應聲明為STRICT,這意味著如果輸入為NULL,函數將不會被調用。如果輸入函數不是STRICT,在接收到NULL輸入值時,其第一個參數會是NULL。在這種情況下,函數應返回NULL,除非發生錯誤(這種設計主要是為了支持領域輸入函數,它們可能需要拒絕NULL輸入)。

輸出函數需要接受一個新數據類型的參數,并將其轉換為cstring類型的返回值。如果值是NULL,則不會調用輸出函數。

可選的receive_function是處理類型的外部二進制表示,并將其轉換為內部格式的函數。如果不提供該函數,則該類型將無法進行二進制輸入。二進制表示形式通常更加高效并易于在不同系統之間移植。例如,標準整數數據類型使用網絡字節序作為其外部二進制表示,而內部格式則采用機器的本地字節序。接收函數應當進行足夠的校驗確保輸入值是有效的,并且可以接受一個internal類型的參數,或者三個參數(internaloidinteger),其中internal參數指向一個StringInfo緩沖區,該緩沖區包含接收到的字節串。其余參數與文本輸入函數一致。通常,接收函數也應聲明為STRICT。如果不是,那么在接收到NULL輸入時,其第一個參數將會是NULL,并且函數應該返回NULL,除非它遇到錯誤。

類似的,可選的send_function將內部格式轉換為外部二進制表示。如果沒有提供該函數,該類型將無法進行二進制輸出。發送函數必須接受一個新數據類型的參數,并返回bytea類型的值。對于NULL值,發送函數不會被調用。這些函數為用戶定義類型提供了與內部數據庫系統的交互方式,確保類型能夠適應數據庫的存儲和通信機制。

您可能對如何能夠在創建新類型之前聲明輸入和輸出函數這一過程感到疑惑,因為這些函數需要引用尚未創建的新類型作為返回值或參數。解決該問題的方法是先定義一個shell type,也就是一種僅具有名稱和擁有者但沒有其他屬性的占位符類型。這可以通過執行不攜帶額外參數的命令CREATE TYPE name來完成。之后,就可以用C語言編寫的輸入輸出函數引用該shell type。最終,使用帶有完整定義的CREATE TYPE命令來替換這個shell type,使其變成一個完整且合法的類型定義,隨后新類型就可以正常使用了。

如果該類型支持類型修飾符——即在類型聲明上附加的可選約束,例如char(5)numeric(30,2)——則您還需要定義可選的type_modifier_input_functiontype_modifier_output_functionPolarDB允許用戶定義類型接受一個或多個簡單常量或標識符作為修飾符。為了在系統目錄中存儲這些信息,修飾符必須能夠被封裝進一個非負整數值內。類型修飾符由type_modifier_input_function接受,該函數以cstring數組形式接收聲明的修飾符,并必須檢查其合法性。如果修飾符無效,函數應該拋出錯誤;如果有效,則返回一個非負整數,該整數將存儲在typmod列中。如果類型沒有type_modifier_input_function,則任何類型修飾符都會被拒絕。

type_modifier_output_function則是將系統目錄中存儲的整數typmod值轉換回用戶可理解的格式。它必須返回一個cstring值,這個值是拼接到類型名稱后面的字符串。例如,對于numeric類型,該函數可能會返回(30,2)。如果默認的顯示格式就是只將存儲的typmod整數值放在圓括號內,則可以省略type_modifier_output_function。這些函數為用戶定義的類型提供了一種方式,以實現對類型修飾符的解析和顯示,從而在類型聲明中允許額外的自定義約束。

可選的analyze_function用于執行與特定數據類型相關的統計信息收集。這適用于那些列的數據類型。默認情況下,如果該數據類型具有默認的B-樹操作符類,ANALYZE將嘗試通過使用類型的equalsless-than操作符來收集統計信息。然而,這種方式對于非標量類型并不合適,因此可以通過指定自定義的分析函數來替代默認行為。自定義分析函數需聲明單個類型為internal的參數,并返回boolean結果。

盡管只有針對新類型創建的I/O函數和其他函數才了解該類型內部表示的詳細信息,但某些關于內部表達的屬性必須聲明給PolarDB。其中最重要的屬性是internallength。基本數據類型可以是固定長度的(這種情況下internallength是一個正整數),也可以是可變長度的(將internallength設置為VARIABLE,在內部將typlen設置為-1表示)。所有可變長度類型的內部表示都必須以一個4字節整數開頭,該整數表示該值的總長度。

PASSEDBYVALUE這一可選的標志,表示新創建的數據類型應該通過值傳遞而不是通過引用傳遞。要使用PASSEDBYVALUE,該類型必須是定長的,且其內部表示的大小不能超過Datum類型所能容納的大小限制,這在某些系統上是4字節,在其他系統上可能是8字節。

alignment參數定義了數據類型的內存對齊要求。可能的值包括按1、2、4或8字節邊界對齊。

說明

所有變長類型的alignment參數至少必須為4,因為變長類型需要在內部包含一個int4類型的長度值作為它們的首部元素。

storage參數允許為變長數據類型選擇合適的存儲策略。對于定長類型,唯一允許的策略是plain,意味著該類型的數據總是存儲在行內,并且不會進行壓縮。extended策略表示系統將嘗試對過長的數據值進行壓縮,并在必要時將數據移到主表行之外。external策略允許將數據移出行,但系統不會嘗試壓縮。main策略雖然允許壓縮,但不鼓勵將數據移出主表行,只有在沒有其他方式能使行大小合適的情況下,帶有這種存儲策略的數據才會被移出,而它會優先于extendedexternal策略的數據保留在行內。

除了plain之外,所有的storage選項都隱含該數據類型的函數能夠處理TOASTThe Oversized-Attribute Storage Technique,超大屬性存儲技術)過的值。這里指定的值只是決定一種可TOAST數據類型列的默認TOAST存儲策略,用戶仍可以使用ALTER TABLE SET STORAGE來為列選擇其他策略。

like_type參數提供了一種基于現有類型來定義新類型基本屬性的方法:直接復制一個已存在的類型的屬性。internallengthpassedbyvaluealignmentstorage這些屬性的值將從指定的類型中復制過來(雖然這些屬性的值可以在LIKE子句中被覆蓋,但這通常是不必要的)。當新類型的底層實現實際上是以某個現有類型作為承載體的時候,這種方法來指定類型的屬性特別有用。

categorypreferred參數提供了助力,用于在存在模棱兩可的情形下決定應用哪種隱式類型轉換。每種數據類型都被分配到以單個ASCII字符命名的類別中,同時每種類型都有可能成為其所屬類別中的首選類型。當需要消除重載函數或操作符的歧義時,解析器將優先考慮轉換為首選類型(但僅限于同一類別內的類型轉換)。對于那些既不隱式轉換為任何其他類型,也不接受從任何其他類型隱式轉換過來的類型,可以保持這些設置的默認值。然而,對于一組具有隱式轉換關系的相關類型,標記它們屬于同一類別并選擇一種或兩種最常用的類型作為該類別的首選通常是非常有幫助的。特別是在將一種用戶定義的類型加入到一個現有的內建類別中(例如數字或字符串類別)時,category參數非常有用。自然也可以創建一個全新的、完全由用戶定義的類型所組成的類別。對于這類新類別,可以選擇任何非大寫字母的ASCII字符作為標識。

若用戶希望數據類型的列在默認情況下具有某個非空值,可以指定默認值。默認值可通過DEFAULT關鍵詞來指定(這可以被附加到特定列上的顯式DEFAULT子句覆蓋)。

要定義一種數據類型為數組類型,可使用ELEMENT關鍵詞來指明該數組的基本元素類型。例如,要定義一種基于4字節整數int4的數組類型,應指定ELEMENT = int4

為了指定分隔這種類型數組在外部表示中的值的定界符,delimiter可設置為特定字符。默認的定界符是逗號(,)。

說明

定界符與數組元素類型有關,而非數組類型本身。

如果collatable這一可選的布爾參數被設置為真,該種類型的列定義和表達式就可以通過使用COLLATE子句來攜帶排序規則信息。實施該類型操作的函數需要負責實際利用這些信息。僅僅將類型標記為可排序,并不意味著它們會自動使用這類信息。

數組類型

PolarDB中,一旦用戶定義了一種新的數據類型,系統會自動創建相應的數組類型。這個自動生成的數組類型的名稱是由原始元素類型的名稱前加一個下劃線來構成的。如果這樣組成的名稱長度超出了NAMEDATALEN字節的限制,則名稱會被自動截斷。如果截斷后的名稱與現有類型的名稱發生沖突,系統會嘗試其他的名稱,直至找到一個不會造成沖突的名字。

這種隱式創建的數組類型是變長的,它使用內建的輸入和輸出函數array_in以及array_out。這個數組類型將會跟隨其元素類型的所有權變動或模式變動而相應地進行更改。如果其元素類型被刪除,那么這個數組類型也會隨之被刪除。這樣的設計確保了類型系統的一致性和簡潔性,同時避免了用戶手動創建和管理數組類型所需的額外工作。

盡管在PolarDB中系統會自動創建與用戶定義類型對應的數組類型,ELEMENT選項的實際用途出現在一個特定場景中:當您創建的是一種定長類型,并且這種類型內部本質上是多個相同元素的數組時。假設您不僅希望為這種類型提供整體的操作,還想允許通過下標來直接訪問數組內的各個元素。例如,point類型內部包含兩個浮點數,通過point[0]point[1]可以直接訪問這兩個坐標值。

說明

這種通過下標訪問的功能僅適用于其內部結構確實為一系列定長字段的定長類型。而對于那些具有可變長度的類型,他們必須要有一個通用化的內部表達,這樣才能使用array_inarray_out函數來支持下標訪問。由于某些歷史遺留問題,定長數組類型的下標是從零開始的,這與變長數組類型從一開始的下標計數方式不同。

參數

參數名稱

說明

name

要創建的類型的名稱(可以被模式限定)。

attribute_name

組合類型的一個屬性(列)的名稱。

data_type

組合類型中一列的現有數據類型的名稱。

collation

與組合類型的某列或范圍類型相關聯的現有排序規則的名稱。

label

文本字符串,表示枚舉類型中某個特定值的文本標簽。在枚舉類型定義中,每個值都通過一個標簽進行唯一表示。

subtype

用于在范圍類型中指定范圍類型的元素類型的名稱。范圍類型代表此元素類型的值的范圍。

subtype_operator_class

范圍類型的元素類型所使用的B樹操作符類的名稱。

canonical_function

范圍類型的規范化函數名稱。

subtype_diff_function

差函數是用于計算范圍類型中兩個元素之間差異的函數名稱。

input_function

將數據從類型的外部文本表現形式轉換為數據庫內部使用的形式。

output_function

input_function相對應,用于將數據從類型的內部表現形式轉換為可供外部使用的文本表現形式。

receive_function

將數據從類型的外部二進制表現形式轉換為數據庫內部使用的形式。

send_function

將數據從類型的內部表現形式轉換為外部二進制表現形式。

type_modifier_input_function

將類型的修飾符數組轉換為內部形式的函數名。

type_modifier_output_function

將類型的修飾符的內部形式轉換為外部文本形式的函數名。

analyze_function

對應數據類型執行統計分析的指定函數名。

internallength

一個數值常量,用于指定新類型內部表示的字節長度,默認其長度是可變的。

alignment

該數據類型的存儲對齊要求。取值為:charint2int4double,默認值為int4

storage

確定數據類型的存儲策略。取值為:plainexternalextendedmain,默認值為plain

like_type

一個現有數據類型的名稱,它與新類型具有相同的內部表示。可以從這個類型復制internallengthpassedbyvaluealignmentstorage的值(除非在CREATE TYPE命令的其他部分已經有明確的指定來覆蓋)。

category

該數據類型的類別碼(一個ASCII字符),默認是表示用戶定義類型U。可以使用其他ASCII字符來創建自定義類別。

preferred

如果這種類型是其類別中的首選類型,則值為真,否則為假。默認值為假。在一個已有的類型類別中新增優先類型時需要十分謹慎,因為這可能引發意外的行為改變。

default

表示數據類型的默認值。如果未指定,默認為空。

element

如果創建的類型是數組,此處指定數組元素的類型。

delimiter

在由這個類型組成的數組中,用于分隔值的定界符。

collatable

如果這種類型的操作能夠使用排序規則信息,則值為真。默認為假。

說明

建議在命名類型和表時避免使用以下劃線開頭的名稱。雖然數據庫具有機制來修改自動生成的數組類型的名稱,以防止與用戶定義的名稱產生沖突,但仍然存在潛在的混淆風險。以下劃線開頭的名稱通常被保留用于數據庫系統自身生成的名稱,如數組類型名稱的約定,這些名稱是由基礎類型名稱加上前導下劃線構成的。因此,為了減少不必要的混淆并保持命名清晰一致,最好避免這種命名做法。

示例

創建一個組合類型,然后在隨后的函數定義中將其作為返回類型使用:

CREATE TYPE compfoo AS (f1 int, f2 text);

CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$
    SELECT fooid, fooname FROM foo
$$ LANGUAGE SQL;

創建一個新的組合類型的過程,并在創建后對這個類型的定義進行了更新:

CREATE TYPE compfoo AS (f1 int, f2 text);

CREATE OR REPLACE TYPE compfoo AS (f2 text, f1 int);

定義一個枚舉類型,并將其應用于新建表的定義中:

CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed');

CREATE TABLE bug (
    id serial,
    description text,
    status bug_status
);

創建一個范圍類型:

CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);

創建一個名為box的用戶定義的基本數據類型,并將其用作新表定義中的一列數據類型:

CREATE TYPE box;

CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ;
CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ;

CREATE TYPE box (
    INTERNALLENGTH = 16,
    INPUT = my_box_in_function,
    OUTPUT = my_box_out_function
);

CREATE TABLE myboxes (
    id integer,
    description box
);

如果box的內部結構是四個 float4元素的一個數組,則可以這樣定義:

CREATE TYPE box (
    INTERNALLENGTH = 16,
    INPUT = my_box_in_function,
    OUTPUT = my_box_out_function,
    ELEMENT = float4
);

創建一個大對象類型并且將它用在了一個表定義中:

CREATE TYPE bigobj (
    INPUT = lo_filein, OUTPUT = lo_fileout,
    INTERNALLENGTH = VARIABLE
);
CREATE TABLE big_objs (
    id integer,
    obj bigobj
);