# 5.5. 系統欄位

每一個表格都有幾個系統欄位，而它們是由資料庫系統預先定義好的，所以使用者在定義欄位名稱時，不能使用這些名字。（這些限制並不是因為它們是保留關鍵字，所以就算用引號括起來也不能使用。）但在一般使用時，你也不需要特別考慮這些欄位，只要瞭解會有這些欄位存在就好。

`oid`

每一個資料列會有一個 Object ID，不過這個欄位只有在建立表格時，加上 WITH OIDS 語法才能使用。或者也可以藉由參數 [default\_with\_oids](https://github.com/pgsql-tw/documents/tree/a096b206440e1ac8cdee57e1ae7a74730f0ee146/iii-server-administration/server-configuration/1913-version-and-platform-compatibility.md) 來切換使用。這個欄位的型別是 oid（和欄位名相同）。參閱 [8.18 節](https://github.com/pgsql-tw/documents/tree/a096b206440e1ac8cdee57e1ae7a74730f0ee146/ii-the-sql-language/data-types/818-object-identifier-types.md)瞭解詳細資訊。

`tableoid`

每個表格也有一個 ID 也會記錄在每一個資料列中。這個欄位特別方便在取得表格的繼承結構（參閱 [5.9 節](https://github.com/pgsql-tw/documents/tree/a096b206440e1ac8cdee57e1ae7a74730f0ee146/ii-the-sql-language/data-definition/59-inheritance.md)），如果沒有這個欄位的話，要去找出資料列的來源就會很麻煩。tableoid 可以參考 pg\_class 表格中的 oid 欄位，進一步取得表格的名稱。

`xmin`

這指的是資料列在插入資料的版本資訊。（每一個資料列的版本，都是一個獨立的資料狀態；每一次資料的更新，都會在邏輯層產生一個新的資料列版本。）

`cmin`

指令識別碼，會存在於新增資料的交易中。（從 0 開始）

`xmax`

刪除資料的交易版本資訊，如果是 0 的話，代表讓資料列不是刪除中的資料列版本。這通常是用來指出某個刪除的交易還未被完成，或某個刪除正在被回復。

`cmax`

指令識別碼，有數字的話表示一個刪除的交易指令，或是 0。

`ctid`

表示每一個資料列存在於該表格的實體位址。注意到的是，雖然 ctid 可以用來快速找到特定的資料列版本，但 ctid 是會改變的，如果有執行過 VACUUM FULL 的話。所以 ctid 如果要用於固定的資料定位的話，是不應該被考慮的選項。OID 或額外自訂序列數字，更適合用於分別邏輯上的資料列。

OID 是一個 32 位元的數字，以 cluster 為單位配發。在一個大型或長期使用的資料庫中，是有可能出現重覆的情況。所以，假設 OID 是唯一的識別是不正確的觀念，除非你還有搭配其他方法來確保唯一性。如果你需要識別表格中的資料列的話，使用序列數產生器是比較建議的作法。OID 也可以這樣用來得到一些額外的預防性功能：

* 唯一性的限制應該設定在 OID 欄位上，來確保每一個 OID 可以識別每一個資料列。當有唯一性限制存在的時候，對於已經存在的資料列就不會有重覆的 OID。（當然，這方法只能用於資料筆數在 40 億筆以下的表格。不過實務上的表格多數都少於這個數目，而且太多資料的話，效果也會變得很差。）
* OID 在多個表格間就不能假設為是唯一，你應該搭配 tableoid 來識別資料庫層級的唯一性。
* 當然，在建立表格時必須要加入 WITH OIDS 語法。在 PostgreSQL 8.1 之前，WITHOUT OIDS 是預設值。

交易識別碼也是 32 位元的數字。在一個長期運行的資料庫中，交易識別碼也可能會重覆。只要有適當的管理機制的話，這並不會是什麼嚴重的問題，詳情請參閱第 24 章。然而，長期來說（超過 10 億個交易），假定交易識別碼的唯一性是不明智的作法。

指令識別碼也是 32 位元的數字，其絕對上限是約 40 億個指令在一個交易當中，實務上這個限制並不會是問題。注意到這個限制是 SQL 指令數量的限制，而不是處理資料的限制。只有真正有改變資料庫內容的指令才會有指令識別碼。
