如何將 ID 類型等序列限制為 int64_t、uint64_t、int32_t 等 C 類型?
在 C99 中,我可以非常清楚整數類型的大小/域。
從 C 程序連接 SQL 數據庫(如 Oracle 或 Postgresql)時,我想創建一個與客戶端匹配的整數類型的表。
例如,為人工主鍵列之類的序列匹配 int64_t、uint64_t 或 uint32_t 等。
僅使用 NUMBER 將允許產生上溢/下溢或無法用客戶端語言表示的數據,對嗎?
如何正確定義這樣的列?
動機
你為什麼要這樣的事情?因為你想寫可靠的軟體。假設您設計了一個數據庫客戶端應用程序,並且假設您只需要少於 2^32 個 ID。因此,為了節省空間(例如使用客戶端數組等),您可以使用 uint32_t(或僅使用 int)。但為了安全起見,數據庫應該強制執行該限制,以便您的系統以明確定義、優雅和明顯的方式失敗(例如拒絕違反插入),以防 20 年後某些使用者想要插入大量 ID 或類似的東西。
數據庫系統
理想情況下,該解決方案應該可以在數據庫之間移植(畢竟,SQL 是一種國際標準)——但是一個特定於 Oracle/Postgres 的答案也會很有啟發性——通常如果你知道如何在一個數據庫系統上做到這一點,你可以在另一個文件中查找抽象概念。
類型與觸發器
它不必是僅類型的解決方案 - 觸發器是強制約束的其他機制也很好。我只是想像使用類型可能是一種方便的方式。
通過約束對 SQL 數據類型的域進行簡單的限制是最自然的方式。你有兩個選擇
- 向相關表的列添加約束
- 為您想要定制的每種數據類型創建一個域,以適應您給定的程式語言限制
第一個選項的範例如下所示
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 腳本的可讀性降低,因為每次使用受限域時都會重複相同的約束條件。這種方法的第二個缺點是,當您將這些約束添加到現有架構時,您很容易錯過架構的某些列。
第一個解決方案的一個優點是您可以輕鬆擴展現有模式。
至於第二種方法,加號是一個更具可讀性的數據庫創建腳本,與正在執行的生產數據庫的表定義相同,但更改現有生產數據庫更加複雜。