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 として使用します。