<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 8.16\. 復合類型 _復合類型_表示一行或者一條記錄的結構; 它實際上只是一個字段名和它們的數據類型的列表。PostgreSQL 允許像簡單數據類型那樣使用復合類型。比如,一個表的某個字段可以聲明為一個復合類型。 ## 8.16.1\. 聲明復合類型 下面是兩個定義復合類型的簡單例子: ``` CREATE TYPE complex AS ( r double precision, i double precision ); CREATE TYPE inventory_item AS ( name text, supplier_id integer, price numeric ); ``` 語法類似于`CREATE TABLE`,只是這里只可以聲明字段名字和類型; 目前不能聲明約束(比如`NOT NULL`)。請注意`AS`關鍵字是很重要的; 沒有它,系統會認為這是一個不同的`CREATE TYPE`命令, 因此你會看到奇怪的語法錯誤。 定義了類型,我們就可以用它創建表: ``` CREATE TABLE on_hand ( item inventory_item, count integer ); INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000); ``` 或者函數: ``` CREATE FUNCTION price_extension(inventory_item, integer) RETURNS numeric AS 'SELECT $1.price * $2' LANGUAGE SQL; SELECT price_extension(item, 10) FROM on_hand; ``` 在你創建表的時候,也會自動創建一個復合類型,名字與表名字相同, 表示該表的行類型。比如,如果我們說過: ``` CREATE TABLE inventory_item ( name text, supplier_id integer REFERENCES suppliers, price numeric CHECK (price > 0) ); ``` 那么,和前面相同的`inventory_item`復合類型也會作為副產品創建, 并且可以和上面一樣使用。不過,需要注意當前實現的一個重要限制: 因為現在還沒有對復合類型實現約束,所以在表定義中顯示的約束_并不適用_ 于表之外的復合類型值。(一個部分繞開的辦法是使用域類型作為復合類型的成員。) ## 8.16.2\. 復合類型值輸入 要以文本常量書寫復合類型值,在圓括弧里包圍字段值并且用逗號分隔他們。 你可以在任何字段值周圍放上雙引號,如果值本身包含逗號或者圓括弧, 你必須用雙引號括起(更多細節見下面)。因此,復合類型常量的一般格式如下: ``` '( _val1_ , _val2_ , ... )' ``` 一個例子是: ``` '("fuzzy dice",42,1.99)' ``` 如果`inventory_item`類型在前面已經定義了,那么這是一個合法的數值。 要讓一個字段值是 NULL ,那么在列表里它的位置上不要寫任何字符。比如, 下面這個常量在第三個字段聲明一個 NULL : ``` '("fuzzy dice",42,)' ``` 如果你想要一個空字符串,而不是 NULL ,寫一對雙引號: ``` '("",42,)' ``` 這里的第一個字段是一個非 NULL 的空字符串,第三個字段是 NULL (這些常量實際上只是我們在[Section 4.1.2.7](#calibre_link-788) 討論的一般類型常量的一個特殊例子。這些常量一開始只是當作字符串, 然后傳遞給復合類型輸入轉換器。一個明確的類型聲明可能是必須的。) 我們也可以用`ROW`表達式語法來構造復合類型值。 在大多數場合下,這種方法都比用字符串文本的語法更簡單,因為你不用操心多重引號。 我們已經在上面使用了這種方法了: ``` ROW('fuzzy dice', 42, 1.99) ROW('', 42, NULL) ``` 只要你在表達式里有超過一個字段,那么關鍵字 ROW 就實際上是可選的, 所以可以簡化為: ``` ('fuzzy dice', 42, 1.99) ('', 42, NULL) ``` `ROW`表達式語法在[Section 4.2.13](#calibre_link-1524)里有更詳細的討論。 ## 8.16.3\. 訪問復合類型 要訪問復合類型字段的一個域,我們寫出一個點以及域的名字, 非常類似從一個表名字里選出一個字段。實際上,因為實在太像從表名字中選取字段, 所以我們經常需要用圓括弧來避免分析器混淆。比如,你可能需要從`on_hand` 例子表中選取一些子域,像下面這樣: ``` SELECT item.name FROM on_hand WHERE item.price > 9.99; ``` 這樣將不能工作,因為根據 SQL 語法,`item`是從一個表名字選取的, 而不是一個字段名字。你必須像下面這樣寫: ``` SELECT (item).name FROM on_hand WHERE (item).price > 9.99; ``` 或者如果你也需要使用表名字(比如,在一個多表查詢里),那么這么寫: ``` SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99; ``` 現在圓括弧對象正確地解析為一個指向`item`字段的引用,然后就可以從中選取子域。 類似的語法問題適用于在任何地點從一個復合類型值中查詢一個域。比如, 要從一個返回復合類型值的函數中只選取一個字段,你需要寫像下面這樣的東西: ``` SELECT (my_func(...)).field FROM ... ``` 如果沒有額外的圓括弧,會產生一個語法錯誤。 ## 8.16.4\. 修改復合類型 下面是一些插入和更新復合類型字段的正確語法。首先,插入或者更新整個字段: ``` INSERT INTO mytab (complex_col) VALUES((1.1,2.2)); UPDATE mytab SET complex_col = ROW(1.1,2.2) WHERE ...; ``` 第一個例子省略了`ROW`,第二個使用它;兩種方法都行。 我們可以更新一個復合字段的獨立子域: ``` UPDATE mytab SET complex_col.r = (complex_col).r + 1 WHERE ...; ``` 請注意,這里我們不需要(實際上是不能)在`SET`后面出現的字段名周圍放上圓括弧, 但是我們在等號右邊的表達式里引用同一個字段的時候卻需要圓括弧。 我們也可以聲明子域是`INSERT`的目標: ``` INSERT INTO mytab (complex_col.r, complex_col.i) VALUES(1.1, 2.2); ``` 如果我們沒有為字段的所有子域提供數值,那么剩下的子域將用 NULL 填充。 ## 8.16.5\. 復合類型輸入和輸出語法 一個復合類型的文本表現形式包含那些根據獨立的子域類型各自 I/O 轉換規則解析的項, 加上一些表明這是復合結構的修飾。這些修飾由整個數值周圍的圓括弧(`(` 和 `)`)加上相鄰域之間的逗號(`,`)組成。圓括弧外面的空白被忽略, 但是在圓括弧里面,它被當作子域數值的一部分,根據對該子域數據類型的輸入轉換規則, 這些空白可能有用,也可能沒用。比如,在: ``` '( 42)' ``` 里,如果子域類型是整數,那么空白將被忽略,但是如果是文本,那么就不會忽略。 如前面顯示的那樣,在給一個復合類型寫數值的時候,你可以在獨立的子域數值周圍用雙引號包圍。 如果子域數值會導致復合數值分析器產生歧義,那么你_必須_這么做。 特別是子域包含圓括弧、逗號、雙引號或反斜杠的場合。要想在雙引號括起來的復合字段值里面放雙引號或反斜杠, 那么你需要在它前面放一個反斜杠。(同樣,在一個雙引號括起的子域數值里面的一對雙引號表示一個雙引號字符, 就像 SQL 字符串文本的單引號規則一樣。)另外, 你可以避免引用和用反斜杠逃逸的方法保護所有可能會當作復合類型語法的數據字符。 一個完全空的子域數值(在逗號或者逗號與圓括弧之間沒有字符)表示一個 NULL 。 要寫一個空字符串,而不是一個 NULL ,寫`""`。 假如子域數值是空字符串或者包含圓括弧、逗號、雙引號、反斜杠、空白, 復合類型輸出程序會在子域數值周圍放上雙引號。(這么處理空白不是必須的, 但是可以增強易讀性。)在一個子域數值里面嵌入的雙引號和反斜杠將會寫成兩份。 > **Note:** 請注意你寫的任何 SQL 命令都首先被當作字符串文本解析,然后才當作復合類型。 這就加倍了你需要的反斜杠數目(假設使用逃逸字符串的語法)。比如, 要插入一個包含雙引號和一個反斜杠的`text`子域到一個復合類型數值里,你需要寫: > > ``` > INSERT ... VALUES (E'("\\"\\\\")'); > ``` > > 字符串文本處理器先去掉一層反斜杠,這樣到達復合類型分析器的東西將變成`("\"\\")`。 接著,該字符串傳遞給`text`數據類型的輸入過程,變成 `"\`。 (如果我們使用的數據類型對反斜杠也有特殊待遇,比如`bytea`, 那么我們可能需要在命令里放多達八個反斜杠以獲取在存儲的復合類型子域中有一個反斜杠。) 美元符界定(參閱[Section 4.1.2.4](#calibre_link-736))可以用于避免雙份反斜杠的問題。 > **Tip:** 在 SQL 命令里寫復合類型值的時候,`ROW`構造器語法通常比復合文本語法更容易使用。 在`ROW`里,獨立的子域數值的寫法和并非作為復合類型的成員書寫的方法一樣。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看