Spanner 在 GoogleSQL 和 PostgreSQL 資料庫中都支援 NUMERIC 資料類型。
GoogleSQL NUMERIC
GoogleSQL NUMERIC 是精確數值資料類型,可表示精確數值,有效位數為 38,小數位數為 9。本頁面概述用戶端程式庫中 NUMERIC 的表示方式。
PostgreSQL NUMERIC
PostgreSQL NUMERIC 類型是任意小數精確度的數值資料類型,最大精確度 (總位數) 為 147,455,最大比例 (小數點右側的位數) 為 16,383。
Spanner DDL 不支援為 PostgreSQL NUMERIC 欄指定有效位數和小數位數。不過,您可以在 DML 陳述式中將數值轉換為固定精確度值。例如:
update t1 set numeric_column = (numeric_column*0.8)::numeric(5,2);
型別 DECIMAL 是 NUMERIC 的別名。
指定主鍵、外鍵或次要索引時,無法使用 PostgreSQL NUMERIC 欄。
以各用戶端程式庫語言表示 NUMERIC
為維持 NUMERIC 值的準確度,每個 Spanner 用戶端程式庫都會以用戶端程式庫語言的適當資料類型儲存這些值。下表列出各支援語言中對應 NUMERIC 的資料類型。
| 語言 | GoogleSQL | PostgreSQL | 
|---|---|---|
| C++ | spanner::Numeric | |
| C# | SpannerNumeric | |
| Go | big.Rat | Custom PGNumeric | 
| Java | BigDecimal | 自訂類型。請參閱 PostgreSQL Java 程式庫附註。 | 
| Node.js | Big | |
| PHP | 自訂數字 | |
| Python | 十進位 | 附帶自訂註解的十進位 | 
| Ruby | BigDecimal | 
C++、C# 和 PHP 這三個用戶端程式庫各自實作了自訂型別,用來代表 Spanner SQL 的 NUMERIC 型別。其他所有程式庫都會使用現有型別。
C++ 用戶端程式庫 spanner::Numeric 物件不支援算術運算。請改為將所含數字轉換為所選的 C++ 物件。
舉例來說,您可以將數字擷取為字串,這樣就能以完整精確度呈現數字,不會遺失任何資料。不過,如果您事先知道該數字符合條件,例如在 std:int64_t 或 double 的範圍內,則可以將該值存取為該類型。
PostgreSQL Java 程式庫注意事項
Spanner Java 用戶端程式庫會使用自訂 Value.pgNumeric 型別儲存 PostgreSQL NUMERIC 值。
寫入 NUMERIC 資料欄
寫入 PostgreSQL 資料表的 NUMERIC 資料欄時,系統支援多種型別。
- 數值 - INSERT INTO Table (id, PgNumericColumn) VALUES (1, 1.23)
- 整數 - INSERT INTO Table (id, PgNumericColumn) VALUES (1, 1)
- 雙打 - INSERT INTO Table (id, PgNumericColumn) VALUES (1, 1.23::float8)
- 未輸入型別的常值 - INSERT INTO Table (id, PgNumericColumn) VALUES (1, 'NaN')
參數化查詢
使用參數化查詢時,請以 $<index> 指定參數,其中 <index> 表示參數位置。然後使用 p<index> 繫結參數。例如,INSERT INTO MyTable (PgNumericColumn) VALUES ($1) 的參數為 p1。
Java 用戶端程式庫支援下列類型做為參數化值:
- 自訂 - Value.pgNumeric- Statement .newBuilder("INSERT INTO MyTable (PgNumericColumn) VALUES ($1), ($2)") .bind("p1") .to(Value.pgNumeric("1.23")) .bind("p2") .to(Value.pgNumeric("NaN")) .build()
- 雙打 - Statement .newBuilder("INSERT INTO MyTable (PgNumericColumn) VALUES ($1), ($2)") .bind("p1") .to(1.23D) .bind("p2") .to(Double.NaN) .build()
- 整數 - Statement .newBuilder("INSERT INTO MyTable (PgNumericColumn) VALUES ($1)") .bind("p1") .to(1) .build()
- 長 - Statement .newBuilder("INSERT INTO MyTable (PgNumericColumn) VALUES ($1)") .bind("p1") .to(1L) .build()
異動
使用 Mutations 時,可將下列值寫入數值型別的資料欄:
- 字串 - Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to("1.23") .build()
- BigDecimal 類型的值 - BigDecimals- Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to(new BigDecimal("1.23")) .build()- Ints- Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to(1) .build()- 長- Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to(1L) .build()
- 呼叫 Value.pgNumeric 後取得的值 - Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to(Value.pgNumeric("1.23")) .build()
從 NUMERIC 資料欄擷取資料
如要取得 ResultSet 數字資料欄中儲存的值,請使用 ResultSet.getString() 或 ResultSet.getValue()。
- 字串 - resultSet.getString("PgNumericColumn")
- 自訂值 - Value pgNumeric = resultSet.getValue("PgNumericColumn"); pgNumeric.getString(); // get underlying value as a String pgNumeric.getNumeric(); // get underlying value as a BigDecimal pgNumeric.getFloat64(); // get underlying value as aDouble
新增 NUMERIC 資料欄
以下範例顯示如何使用 Spanner 用戶端程式庫,將 NUMERIC 資料欄新增至名為 Venues 的資料表。
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
更新 NUMERIC 資料
以下範例顯示如何使用 Spanner 用戶端程式庫更新 NUMERIC 資料。
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
查詢 NUMERIC 資料
以下範例顯示如何使用 Spanner 用戶端程式庫查詢 NUMERIC 資料。
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Spanner JDBC 驅動程式支援 NUMERIC,使用 Java BigDecimal 型別。如需 NUMERIC 的使用範例,請參閱「透過 JDBC 連線至 GoogleSQL 方言資料庫」中的程式碼範例。
建立用戶端程式庫或驅動程式時處理 NUMERIC
NUMERIC 類型會編碼為 google.protobuf.Value Proto 中的十進位或科學記號字串。這個 proto 會包裝成 ResultSet、PartialResultSet 或 Mutation,視讀取或寫入作業而定。ResultSetMetadata 會使用 NUMERIC
TypeCode,指出對應值應讀取為 NUMERIC。
在您建立的用戶端程式庫或驅動程式中使用 NUMERIC 時,請遵守下列指引。
- 如要從 ResultSet 讀取 - NUMERIC,請執行下列操作:- 當 TypeCode 為 - NUMERIC時,請從 google.protobuf.Value proto 讀取 string_value
- 將該字串轉換為指定語言的相關型別 
 
- 如要使用突變寫入 - NUMERIC,請在提供相關型別時,使用字串表示法做為 google.protobuf.Value Proto 中的 string_value。