Datatypes

如何將 ID 類型等序列限制為 int64_t、uint64_t、int32_t 等 C 類型?

  • August 31, 2012

在 C99 中,我可以非常清楚整數類型的大小/域。

從 C 程序連接 SQL 數據庫(如 Oracle 或 Postgresql)時,我想創建一個與客戶端匹配的整數類型的表。

例如,為人工主鍵列之類的序列匹配 int64_t、uint64_t 或 uint32_t 等。

僅使用 NUMBER 將允許產生上溢/下溢或無法用客戶端語言表示的數據,對嗎?

如何正確定義這樣的列?

動機

你為什麼要這樣的事情?因為你想寫可靠的軟體。假設您設計了一個數據庫客戶端應用程序,並且假設您只需要少於 2^32 個 ID。因此,為了節省空間(例如使用客戶端數組等),您可以使用 uint32_t(或僅使用 int)。但為了安全起見,數據庫應該強制執行該限制,以便您的系統以明確定義、優雅和明顯的方式失敗(例如拒絕違反插入),以防 20 年後某些使用者想要插入大量 ID 或類似的東西。

數據庫系統

理想情況下,該解決方案應該可以在數據庫之間移植(畢竟,SQL 是一種國際標準)——但是一個特定於 Oracle/Postgres 的答案也會很有啟發性——通常如果你知道如何在一個數據庫系統上做到這一點,你可以在另一個文件中查找抽象概念。

類型與觸發器

它不必是僅類型的解決方案 - 觸發器是強制約束的其他機制也很好。我只是想像使用類型可能是一種方便的方式。

通過約束對 SQL 數據類型的域進行簡單的限制是最自然的方式。你有兩個選擇

  1. 向相關表的列添加約束
  2. 為您想要定制的每種數據類型創建一個域,以適應您給定的程式語言限制

第一個選項的範例如下所示

ALTER TABLE table_name 
 ADD CONSTRAINT constraint_name 
CHECK (column_name > -128 AND column_name < 127);

(根據需要更改表、約束和列名,並調整檢查邊界的範圍)

第二個選項是一個兩步過程。首先使用以下命令將一個新域添加到您的數據庫(在此範例中,域類型名為 c_byte8)

CREATE DOMAIN c_byte8 NUMERIC CONSTRAINT c_byte8_constraint
CHECK (VALUE > -128 AND VALUE < 127);

其次使用適當的類型創建表,例如 c_byte8 而不是 NUMERIC 作為屬性的類型。例如

CREATE TABLE test_table_1 (id NUMERIC, byte_value c_byte8);

請記住,第一個解決方案將要求您為已定義的每個屬性添加約束,或者您將在將來定義。它使您的 DB-create 腳本的可讀性降低,因為每次使用受限域時都會重複相同的約束條件。這種方法的第二個缺點是,當您將這些約束添加到現有架構時,您很容易錯過架構的某些列。

第一個解決方案的一個優點是您可以輕鬆擴展現有模式。

至於第二種方法,加號是一個更具可讀性的數據庫創建腳本,與正在執行的生產數據庫的表定義相同,但更改現有生產數據庫更加複雜。

引用自:https://dba.stackexchange.com/questions/22844