Spanner では、GoogleSQL データベースと PostgreSQL データベースの両方で NUMERIC データ型がサポートされています。
GoogleSQL NUMERIC
GoogleSQL の NUMERIC は、正確な数値を表現できるデータ型であり、精度が 38、スケールが 9 です。このページでは、クライアント ライブラリでの NUMERIC の表示方法の概要について説明します。
PostgreSQL NUMERIC
PostgreSQL の NUMERIC 型は、最大精度(合計桁数)が 147,455、最大スケール(小数点以下の桁数)が 16,383 の、任意の 10 進数値データ型です。
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 | カスタム PGNumeric | 
| Java | BigDecimal | カスタム型。PostgreSQL Java ライブラリの注意事項をご覧ください。 | 
| Node.js | Big | |
| PHP | カスタム Numeric | |
| Python | 10 進数 | カスタム アノテーションを含む 10 進数 | 
| Ruby | BigDecimal | 
C++、C#、PHP の 3 つのクライアント ライブラリには、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()
ミューテーション
ミューテーションを使用すると、数値型の列に次の値を書き込むことができます。
- 文字列 - Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to("1.23") .build()
- BigDecimal 型の値 - BigDecimal- Mutation .newInsertBuilder("MyTable") .set("PgNumericColumn") .to(new BigDecimal("1.23")) .build()- 整数- 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 ドライバでは、Java の BigDecimal 型を使用して NUMERIC がサポートされています。NUMERIC の使用例については、JDBC を GoogleSQL 言語データベースに接続するのコードサンプルをご覧ください。
クライアント ライブラリまたはドライバの作成時の NUMERIC の処理
NUMERIC 型は、google.protobuf.Value プロトコル内で 10 進表記または科学的記数法で文字列としてエンコードされます。このプロトコルは、読み取りか書き込みかに応じて、ResultSet、PartialResultSet、Mutation のいずれかとしてラップされます。ResultSetMetadata は NUMERIC TypeCode を使って、対応する値が NUMERIC として読み取られることを示します。
作成するクライアント ライブラリまたはドライバで NUMERIC を扱う際は、次の点に留意してください。
- ResultSet から - NUMERICを読み取るには:- TypeCode が - NUMERICの場合、google.protobuf.Value proto の string_value を読み取る
- その文字列を、対象言語の関連する型に変換する 
 
- Mutations を使用して - NUMERICを書き込むには、対象の型に応じて、文字列の表現を google.protobuf.Value proto の string_value として使用します。