

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Python 用 Amazon QLDB ドライバー
<a name="getting-started.python"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

台帳内のデータを操作するには、 AWS が提供するドライバーを使用して、Python アプリケーションから Amazon QLDB に接続できます。次のトピックでは、Python 用 QLDB ドライバーの使用を開始する方法について説明します。

**Topics**
+ [ドライバーに関するリソース](#getting-started.python.resources)
+ [前提条件](#getting-started.python.prereqs)
+ [インストール](#getting-started.python.install)
+ [クイックスタートチュートリアル](driver-quickstart-python.md)
+ [クックブックリファレンス](driver-cookbook-python.md)

## ドライバーに関するリソース
<a name="getting-started.python.resources"></a>

Python ドライバーでサポートされている機能の詳細については、以下のリソースを参照してください。
+ API リファレンス: [3.x](https://amazon-qldb-driver-python.readthedocs.io/en/latest/)、[2.x](https://amazon-qldb-driver-python.readthedocs.io/en/v2.0.2/)
+ [ドライバーのソースコード (GitHub)](https://github.com/awslabs/amazon-qldb-driver-python)
+ [サンプルアプリケーションのソースコード (GitHub)](https://github.com/aws-samples/amazon-qldb-dmv-sample-python)
+ [Amazon Ion コード例](ion.code-examples.md)

## 前提条件
<a name="getting-started.python.prereqs"></a>

Python 用 QLDB ドライバーの使用を開始する前に、次のことを行う必要があります。

1.  AWS 「」のセットアップ手順に従ってください[Amazon QLDB へのアクセス](accessing.md)。これには以下が含まれます。

   1. にサインアップします AWS。

   1. QLDB の適切なアクセス許可を持つユーザーを作成します。

   1. 開発に必要なプログラムへのアクセスを提供します。

1. [Python ダウンロードサイト](https://www.python.org/downloads/)から次のバージョンの Python のいずれかをインストールします。
   + **3.6 またはそれ以降** – Python v3 用の QLDB ドライバー
   + **3.4 またはそれ以降** – Python v2 用の QLDB ドライバー

1.  AWS 認証情報とデフォルトを設定します AWS リージョン。手順については、 AWS SDK for Python (Boto3) ドキュメントの[「クイックスタート](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration)」を参照してください。

   利用可能なリージョンの完全なリストについては、「AWS 全般のリファレンス」の「[Amazon QLDB エンドポイントとクォータ](https://docs.aws.amazon.com/general/latest/gr/qldb.html)」を参照してください。

次に、すべてのチュートリアル用のサンプルアプリケーションをダウンロードするか、Python プロジェクトにのみドライバーをインストールして短いコード例を実行できます。
+ QLDB ドライバーと を既存のプロジェクト AWS SDK for Python (Boto3) にインストールするには、「」に進みます[インストール](#getting-started.python.install)。
+ プロジェクトを設定し、台帳の基本的なデータトランザクションを示す短いコード例については、「[クイックスタートチュートリアル](driver-quickstart-python.md)」を参照してください。
+ チュートリアルのサンプルアプリケーション全体のデータプレーンと管理 API の両方のオペレーションを実行する詳細な例については、「[Python チュートリアル](getting-started.python.tutorial.md)」を参照してください。

## インストール
<a name="getting-started.python.install"></a>

QLDB は、以下のドライバーバージョンと Python の依存関係をサポートしています。


****  

| ドライバーバージョン | Python バージョン | ステータス | 最新リリース日 | 
| --- | --- | --- | --- | 
| [2.x](https://pypi.org/project/pyqldb/2.0.2/) | 3.4 以降 | 本番リリース | 2020 年 5 月 7 日 | 
| [3.x](https://pypi.org/project/pyqldb/) | 3.6 以降 | 本番リリース | 2021 年 10 月 28 日 | 

`pip` (Python のパッケージマネージャー) を使用して PyPI から QLDB ドライバーをインストールするには、コマンドラインで次のように入力します。

------
#### [ 3.x ]

```
pip install pyqldb
```

------
#### [ 2.x ]

```
pip install pyqldb==2.0.2
```

------

ドライバーをインストールすると、[AWS SDK for Python (Boto3)](https://aws.amazon.com/sdk-for-python) や [Amazon Ion](ion.md) パッケージなどの依存関係もインストールされます。

**ドライバーを使用して台帳に接続する**

その後、ドライバーをインポートし、それを使用して台帳に接続することができます。次の Python コード例は、指定した台帳名のセッションを作成する方法を示しています。

------
#### [ 3.x ]

```
from pyqldb.driver.qldb_driver import QldbDriver
qldb_driver = QldbDriver(ledger_name='testLedger')

for table in qldb_driver.list_tables():
    print(table)
```

------
#### [ 2.x ]

```
from pyqldb.driver.pooled_qldb_driver import PooledQldbDriver

qldb_driver = PooledQldbDriver(ledger_name='testLedger')
qldb_session = qldb_driver.get_session()

for table in qldb_session.list_tables():
    print(table)
```

------

台帳に対して基本的なデータトランザクションを実行する方法を示す短いコード例については、「[クックブックリファレンス](driver-cookbook-python.md)」を参照してください。

# Python 用 Amazon QLDB ドライバー — クイックスタートチュートリアル
<a name="driver-quickstart-python"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

このチュートリアルでは、Python 用 Amazon QLDB ドライバーの最新バージョンを使用して単純なアプリケーションを設定する方法について説明します。このガイドには、ドライバのインストール手順と、*作成、読み取り、更新、削除* (CRUD) の基本的なオペレーションを実行する短いコード例が含まれています。これらのオペレーションを完全なサンプルアプリケーションで実行する詳細な例については、「[Python チュートリアル](getting-started.python.tutorial.md)」を参照してください。

**Topics**
+ [前提条件](#driver-quickstart-python.prereqs)
+ [ステップ 1: プロジェクトを設定する](#driver-quickstart-python.step-1)
+ [ステップ 2: ドライバーを初期化する](#driver-quickstart-python.step-2)
+ [ステップ 3: テーブルとインデックスを作成する](#driver-quickstart-python.step-3)
+ [ステップ 4: ドキュメントを挿入する](#driver-quickstart-python.step-4)
+ [ステップ 5: ドキュメントにクエリを実行する](#driver-quickstart-python.step-5)
+ [ステップ 6: ドキュメントを更新する](#driver-quickstart-python.step-6)
+ [完全なアプリケーションの実行](#driver-quickstart-python.complete)

## 前提条件
<a name="driver-quickstart-python.prereqs"></a>

作業を始める前に、次の操作を実行してください。

1. Python ドライバー用の「[前提条件](getting-started.python.md#getting-started.python.prereqs)」を完了します (まだ完了していない場合)。これには、 へのサインアップ AWS、開発用のプログラムによるアクセスの許可、Python バージョン 3.6 以降のインストールが含まれます。

1. `quick-start` という名前の台帳を作成します。

   台帳の作成方法については、「[Amazon QLDB 台帳の基本的なオペレーション](ledger-management.basics.md)」、または「**コンソールの開始方法」の「[ステップ 1: 新しい台帳を作成する](getting-started-step-1.md)」を参照してください。

## ステップ 1: プロジェクトを設定する
<a name="driver-quickstart-python.step-1"></a>

まず、Python プロジェクトをセットアップします。

**注記**  
これらのセットアップ手順を自動化する機能を備えた IDE を使用する場合は、「[ステップ 2: ドライバーを初期化する](#driver-quickstart-python.step-2)」までスキップできます。

1. アプリケーション用のフォルダを作成します。

   ```
   $ mkdir myproject
   $ cd myproject
   ```

1. PyPI から Python 用 QLDB ドライバーをインストールするには、以下の `pip` コマンドを入力します。

   ```
   $ pip install pyqldb
   ```

   ドライバーをインストールすると、[AWS SDK for Python (Boto3)](https://aws.amazon.com/sdk-for-net) や [Amazon Ion](ion.md) パッケージなどの依存関係もインストールされます。

1. `app.py` という名前の新しいファイルを作成します。

   次に、以下のステップのコード例を段階的に追加し、いくつかの基本的な CRUD オペレーションを試します。または、ステップバイステップのチュートリアルをスキップして、代わりに[完全なアプリケーション](#driver-quickstart-python.complete)を実行することもできます。

## ステップ 2: ドライバーを初期化する
<a name="driver-quickstart-python.step-2"></a>

`quick-start` という名前の台帳に接続するドライバーのインスタンスを初期化します。以下のコードを `app.py` ファイルに追加します。

```
from pyqldb.config.retry_config import RetryConfig
from pyqldb.driver.qldb_driver import QldbDriver

# Configure retry limit to 3
retry_config = RetryConfig(retry_limit=3)

# Initialize the driver
print("Initializing the driver")
qldb_driver = QldbDriver("quick-start", retry_config=retry_config)
```

## ステップ 3: テーブルとインデックスを作成する
<a name="driver-quickstart-python.step-3"></a>

以下のコード例は、`CREATE TABLE` および `CREATE INDEX` ステートメントの実行方法を示しています。

以下のコードを追加して、`People` という名前のテーブルと、そのテーブルの `lastName` フィールドのインデックスを作成します。クエリのパフォーマンスを最適化し、[オプティミスティック同時実行制御 (OCC)](concurrency.md) 競合例外を制限するために、[インデックス](ql-reference.create-index.md)が必要です。

```
def create_table(transaction_executor):
    print("Creating a table")
    transaction_executor.execute_statement("Create TABLE People")

def create_index(transaction_executor):
    print("Creating an index")
    transaction_executor.execute_statement("CREATE INDEX ON People(lastName)")

# Create a table
qldb_driver.execute_lambda(lambda executor: create_table(executor))

# Create an index on the table
qldb_driver.execute_lambda(lambda executor: create_index(executor))
```

## ステップ 4: ドキュメントを挿入する
<a name="driver-quickstart-python.step-4"></a>

次のコード例は、`INSERT` ステートメントの実行方法を示しています。QLDB は [PartiQL](ql-reference.md) クエリ言語 (SQL 互換) と [Amazon Ion](ion.md) データ形式 (JSON のスーパーセット) をサポートします。

`People` テーブルにドキュメントを挿入する以下のコードを追加します。

```
def insert_documents(transaction_executor, arg_1):
    print("Inserting a document")
    transaction_executor.execute_statement("INSERT INTO People ?", arg_1)

# Insert a document
doc_1 = { 'firstName': "John",
          'lastName': "Doe",
          'age': 32,
        }

qldb_driver.execute_lambda(lambda x: insert_documents(x, doc_1))
```

この例では、疑問符 (`?`) を変数プレースホルダーとして使用して、ドキュメント情報をステートメントに渡します。`execute_statement` メソッドは、Amazon Ion 型と Python ネイティブ型の両方の値をサポートします。

**ヒント**  
1 つの [INSERT](ql-reference.insert.md) ステートメントを使用して複数のドキュメントを挿入するために、次のように型 [list](driver-working-with-ion.md#driver-ion-list) のパラメータをステートメントに渡すことができます。  

```
# people is a list
transaction_executor.execute_statement("INSERT INTO Person ?", people)
```
リストを渡すときには、変数プレースホルダー (`?`) を二重山括弧 (`<<...>>`) で囲まないでください。マニュアルの PartiQL ステートメントでは、二重山括弧は**バッグと呼ばれる順序付けされていないコレクションを表します。

## ステップ 5: ドキュメントにクエリを実行する
<a name="driver-quickstart-python.step-5"></a>

次のコード例は、`SELECT` ステートメントの実行方法を示しています。

`People` テーブルからドキュメントをクエリする以下のコードを追加します。

```
def read_documents(transaction_executor):
    print("Querying the table")
    cursor = transaction_executor.execute_statement("SELECT * FROM People WHERE lastName = ?", 'Doe')

    for doc in cursor:
        print(doc["firstName"])
        print(doc["lastName"])
        print(doc["age"])

# Query the table
qldb_driver.execute_lambda(lambda executor: read_documents(executor))
```

## ステップ 6: ドキュメントを更新する
<a name="driver-quickstart-python.step-6"></a>

次のコード例は、`UPDATE` ステートメントの実行方法を示しています。

1. `age` を `42` に更新して `People` テーブルのドキュメントを更新する以下のコードを追加します。

   ```
   def update_documents(transaction_executor, age, lastName):
       print("Updating the document")
       transaction_executor.execute_statement("UPDATE People SET age = ? WHERE lastName = ?", age, lastName)
   
   # Update the document
   age = 42
   lastName = 'Doe'
   
   qldb_driver.execute_lambda(lambda x: update_documents(x, age, lastName))
   ```

1. テーブルを再度クエリして、更新された値を確認します。

   ```
   # Query the updated document
   qldb_driver.execute_lambda(lambda executor: read_documents(executor))
   ```

1. アプリケーションを実行するには、プロジェクトディレクトリから以下のコマンドを入力します。

   ```
   $ python app.py
   ```

## 完全なアプリケーションの実行
<a name="driver-quickstart-python.complete"></a>

以下のコード例は、`app.py` アプリケーションの完全なバージョンです。上のステップを個別に実行する代わりに、このコード例を最初から最後までコピーして実行することもできます。このアプリケーションは、`quick-start` という名前の台帳に対するいくつかの基本的な CRUD オペレーションを実行します。

**注記**  
このコードを実行する前に、`quick-start` 台帳に `People` という名前のアクティブなテーブルが存在しないことを確認してください。

```
from pyqldb.config.retry_config import RetryConfig
from pyqldb.driver.qldb_driver import QldbDriver

def create_table(transaction_executor):
    print("Creating a table")
    transaction_executor.execute_statement("CREATE TABLE People")

def create_index(transaction_executor):
    print("Creating an index")
    transaction_executor.execute_statement("CREATE INDEX ON People(lastName)")

def insert_documents(transaction_executor, arg_1):
    print("Inserting a document")
    transaction_executor.execute_statement("INSERT INTO People ?", arg_1)

def read_documents(transaction_executor):
    print("Querying the table")
    cursor = transaction_executor.execute_statement("SELECT * FROM People WHERE lastName = ?", 'Doe')
                                                                                                                                          
    for doc in cursor:
        print(doc["firstName"])
        print(doc["lastName"])
        print(doc["age"])

def update_documents(transaction_executor, age, lastName):
    print("Updating the document")
    transaction_executor.execute_statement("UPDATE People SET age = ? WHERE lastName = ?", age, lastName)

# Configure retry limit to 3
retry_config = RetryConfig(retry_limit=3)

# Initialize the driver
print("Initializing the driver")
qldb_driver = QldbDriver("quick-start", retry_config=retry_config)

# Create a table
qldb_driver.execute_lambda(lambda executor: create_table(executor))

# Create an index on the table
qldb_driver.execute_lambda(lambda executor: create_index(executor))

# Insert a document
doc_1 = { 'firstName': "John",
          'lastName': "Doe",
          'age': 32,
        }

qldb_driver.execute_lambda(lambda x: insert_documents(x, doc_1))

# Query the table
qldb_driver.execute_lambda(lambda executor: read_documents(executor))

# Update the document
age = 42
lastName = 'Doe'

qldb_driver.execute_lambda(lambda x: update_documents(x, age, lastName))

# Query the table for the updated document
qldb_driver.execute_lambda(lambda executor: read_documents(executor))
```

完全なアプリケーションを実行するには、プロジェクトディレクトリから以下のコマンドを入力します。

```
$ python app.py
```

# Python 用 Amazon QLDB ドライバー — クックブックリファレンス
<a name="driver-cookbook-python"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

このリファレンスガイドでは、Python 用 Amazon QLDB ドライバーの一般的なユースケースについて説明します。Python コード例を提供し、ドライバーを使用して**作成、読み取り、更新、および削除 (CRUD) の基本的なオペレーションを実行する方法を説明しています。Amazon Ion データを処理するためのコード例も含まれています。さらに、このガイドでは、トランザクションをべき等にし、一意性の制約を実装するためのベストプラクティスを取り上げています。

**注記**  
該当する場合、一部のユースケースでは、サポートされているメジャーバージョンの Python 用 QLDB ドライバーに対して異なるコード例があります。

**Contents**
+ [ドライバーのインポート](#cookbook-python.importing)
+ [ドライバーのインスタンス化](#cookbook-python.instantiating)
+ [CRUD オペレーション](#cookbook-python.crud)
  + [テーブルの作成](#cookbook-python.crud.creating-tables)
  + [インデックスの作成](#cookbook-python.crud.creating-indexes)
  + [ドキュメントの読み取り](#cookbook-python.crud.reading)
    + [クエリパラメータの使用](#cookbook-python.reading-using-params)
  + [ドキュメントの挿入](#cookbook-python.crud.inserting)
    + [1 つのステートメントで複数のドキュメントの挿入](#cookbook-python.crud.inserting.multiple)
  + [ドキュメントの更新](#cookbook-python.crud.updating)
  + [ドキュメントの削除](#cookbook-python.crud.deleting)
  + [トランザクションで複数のステートメントの実行](#cookbook-python.crud.multi-statement)
  + [再試行ロジック](#cookbook-python.crud.retry-logic)
  + [一意性制約の実装](#cookbook-python.crud.uniqueness-constraints)
+ [Amazon Ion の操作](#cookbook-python.ion)
  + [Ion モジュールのインポート](#cookbook-python.ion.import)
  + [Ion 型の作成](#cookbook-python.ion.creating-types)
  + [Ion バイナリダンプの取得](#cookbook-python.ion.getting-binary)
  + [Ion テキストダンプの取得](#cookbook-python.ion.getting-text)

## ドライバーのインポート
<a name="cookbook-python.importing"></a>

次のコード例では、ドライバーをインポートします。

------
#### [ 3.x ]

```
from pyqldb.driver.qldb_driver import QldbDriver
import amazon.ion.simpleion as simpleion
```

------
#### [ 2.x ]

```
from pyqldb.driver.pooled_qldb_driver import PooledQldbDriver
import amazon.ion.simpleion as simpleion
```

------

**注記**  
この例では、Amazon Ion パッケージ (`amazon.ion.simpleion`) もインポートします。このリファレンスでいくつかのデータオペレーションを実行するときに Ion データを処理するには、このパッケージが必要です。詳細については、「[Amazon Ion の操作](#cookbook-python.ion)」を参照してください。

## ドライバーのインスタンス化
<a name="cookbook-python.instantiating"></a>

次のコード例は、デフォルト設定を使用して指定された台帳名に接続するドライバーのインスタンスを作成します。

------
#### [ 3.x ]

```
qldb_driver = QldbDriver(ledger_name='vehicle-registration')
```

------
#### [ 2.x ]

```
qldb_driver = PooledQldbDriver(ledger_name='vehicle-registration')
```

------

## CRUD オペレーション
<a name="cookbook-python.crud"></a>

QLDB は**作成、読み取り、更新、および削除 (CRUD) オペレーションをトランザクションの一部として実行します。

**警告**  
ベストプラクティスとして、書き込みトランザクションを厳密にべき等にしてください。

**トランザクションをべき等にする**

再試行の場合に予期しない結果を避けるために、書き込みトランザクションをべき等にすることをお勧めします。トランザクションは、複数回実行して毎回同じ結果を生成できる場合、*idempotent* です。

例えば、`Person` という名前のテーブルにドキュメントを挿入するトランザクションについて考えてみます。トランザクションは、まずドキュメントがテーブル内に既に存在するかどうかをチェックする必要があります。このチェックを行わないと、テーブルに重複するドキュメントができる可能性があります。

QLDB がサーバー側でトランザクションを正常にコミットできるが、レスポンスを待機中にクライアントはタイムアウトするとします。トランザクションがべき等でない場合、再試行時に同じドキュメントが複数回挿入される可能性があります。

**インデックスを使用してテーブル全体のスキャンを回避する**

インデックス付きフィールドまたはドキュメント ID で**等価演算子を使用する `WHERE` 述語句でステートメントを実行する (例: `WHERE indexedField = 123` または `WHERE indexedField IN (456, 789)`) こともお勧めします。このインデックス付きのルックアップがない場合、QLDB はテーブルスキャンを実行する必要があり、トランザクションタイムアウトや**オプティミスティック同時実行制御 (OCC) 競合が発生する可能性があります。

OCC の詳細については、「[Amazon QLDB 同時実行モデル](concurrency.md)」を参照してください。

**暗黙的に作成されたトランザクション**

[pyqldb.driver.qldb\$1driver.execute\$1lambda](https://amazon-qldb-driver-python.readthedocs.io/en/stable/reference/driver/qldb_driver.html#pyqldb.driver.qldb_driver.QldbDriver.execute_lambda) メソッドは、[pyqldb.execution.executor.Executor](https://amazon-qldb-driver-python.readthedocs.io/en/stable/reference/execution/executor.html#pyqldb.execution.executor.Executor) のインスタンスを受け取る Lambda 関数を受け入れます。これを使用してステートメントを実行できます。`Executor` のインスタンスは、暗黙的に作成されたトランザクションをラップします。

Lambda 関数内でステートメントを実行するには、トランザクションエグゼキューターの [execute statement](https://amazon-qldb-driver-python.readthedocs.io/en/stable/reference/execution/executor.html#pyqldb.execution.executor.Executor.execute_statement) メソッドを使用します。ドライバーは、Lambda 関数が戻ったときに暗黙的にトランザクションをコミットします。

**注記**  
`execute_statement` メソッドは、Amazon Ion 型と Python ネイティブ型の両方をサポートします。Python ネイティブ型を引数として `execute_statement` に渡すと、ドライバーが `amazon.ion.simpleion` モジュールを使用して Ion 型に変換します (指定された Python データ型の変換がサポートされている場合)。サポートされているデータ型と変換ルールについては、[simpleion のソースコード](https://ion-python.readthedocs.io/en/latest/_modules/amazon/ion/simpleion.html)を参照してください。

次のセクションでは、基本的な CRUD オペレーションの実行、カスタム再試行ロジックの指定、一意性制約の実装方法について説明します。

**Contents**
+ [テーブルの作成](#cookbook-python.crud.creating-tables)
+ [インデックスの作成](#cookbook-python.crud.creating-indexes)
+ [ドキュメントの読み取り](#cookbook-python.crud.reading)
  + [クエリパラメータの使用](#cookbook-python.reading-using-params)
+ [ドキュメントの挿入](#cookbook-python.crud.inserting)
  + [1 つのステートメントで複数のドキュメントの挿入](#cookbook-python.crud.inserting.multiple)
+ [ドキュメントの更新](#cookbook-python.crud.updating)
+ [ドキュメントの削除](#cookbook-python.crud.deleting)
+ [トランザクションで複数のステートメントの実行](#cookbook-python.crud.multi-statement)
+ [再試行ロジック](#cookbook-python.crud.retry-logic)
+ [一意性制約の実装](#cookbook-python.crud.uniqueness-constraints)

### テーブルの作成
<a name="cookbook-python.crud.creating-tables"></a>

```
def create_table(transaction_executor):
    transaction_executor.execute_statement("CREATE TABLE Person")

qldb_driver.execute_lambda(lambda executor: create_table(executor))
```

### インデックスの作成
<a name="cookbook-python.crud.creating-indexes"></a>

```
def create_index(transaction_executor):
    transaction_executor.execute_statement("CREATE INDEX ON Person(GovId)")

qldb_driver.execute_lambda(lambda executor: create_index(executor))
```

### ドキュメントの読み取り
<a name="cookbook-python.crud.reading"></a>

```
# Assumes that Person table has documents as follows:
# { "GovId": "TOYENC486FH", "FirstName": "Brent" }

def read_documents(transaction_executor):
    cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'")

    for doc in cursor:
        print(doc["GovId"]) # prints TOYENC486FH
        print(doc["FirstName"]) # prints Brent

qldb_driver.execute_lambda(lambda executor: read_documents(executor))
```

#### クエリパラメータの使用
<a name="cookbook-python.reading-using-params"></a>

次のコード例では、ネイティブ型のクエリパラメータを使用します。

```
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH')
```

次のコード例では、Ion 型のクエリパラメータを使用します。

```
name = ion.loads('Brent')
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE FirstName = ?", name)
```

次のコード例では、複数のクエリパラメータを使用します。

```
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", 'TOYENC486FH', "Brent")
```

次のコード例では、クエリパラメータのリストを使用します。

```
gov_ids = ['TOYENC486FH','ROEE1','YH844']
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId IN (?,?,?)", *gov_ids)
```

**注記**  
インデックス付きルックアップなしでクエリを実行すると、完全なテーブルスキャンが呼び出されます。この例では、`GovId` フィールドで[インデックス](ql-reference.create-index.md)を使用して、パフォーマンスを最適化することをお勧めします。`GovId` でインデックスをオンにしないと、クエリのレイテンシーが大きくなり、OCC 競合例外やトランザクションタイムアウトが発生する可能性があります。

### ドキュメントの挿入
<a name="cookbook-python.crud.inserting"></a>

次のコード例では、ネイティブデータ型を挿入します。

```
def insert_documents(transaction_executor, arg_1):
    # Check if doc with GovId:TOYENC486FH exists
    # This is critical to make this transaction idempotent
    cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH')
    # Check if there is any record in the cursor
    first_record = next(cursor, None)

    if first_record:
        # Record already exists, no need to insert
        pass
    else:
        transaction_executor.execute_statement("INSERT INTO Person ?", arg_1)

doc_1 = { 'FirstName': "Brent",
          'GovId': 'TOYENC486FH',
        }

qldb_driver.execute_lambda(lambda executor: insert_documents(executor, doc_1))
```

次のコード例では、Ion データ型を挿入します。

```
def insert_documents(transaction_executor, arg_1):
    # Check if doc with GovId:TOYENC486FH exists
    # This is critical to make this transaction idempotent
    cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH')
    # Check if there is any record in the cursor
    first_record = next(cursor, None)

    if first_record:
        # Record already exists, no need to insert
        pass
    else:
        transaction_executor.execute_statement("INSERT INTO Person ?", arg_1)

doc_1 = { 'FirstName': 'Brent',
          'GovId': 'TOYENC486FH',
        }

# create a sample Ion doc
ion_doc_1 = simpleion.loads(simpleion.dumps(doc_1)))

qldb_driver.execute_lambda(lambda executor: insert_documents(executor, ion_doc_1))
```

このトランザクションは、ドキュメントを `Person` テーブルに挿入します。挿入する前に、まずドキュメントがテーブル内に既に存在しているかどうかをチェックします。**このチェックにより、トランザクションは本質的にべき等になります。**このトランザクションを複数回実行しても、意図しない副作用は発生しません。

**注記**  
この例では、`GovId` フィールドでインデックスを使用して、パフォーマンスを最適化することをお勧めします。`GovId` でインデックスをオンにしないと、ステートメントのレイテンシーが大きくなり、OCC 競合例外やトランザクションタイムアウトが発生する可能性があります。

#### 1 つのステートメントで複数のドキュメントの挿入
<a name="cookbook-python.crud.inserting.multiple"></a>

1 つの [INSERT](ql-reference.insert.md) ステートメントを使用して複数のドキュメントを挿入するために、次のように型 [list](driver-working-with-ion.md#driver-ion-list) のパラメータをステートメントに渡すことができます。

```
# people is a list
transaction_executor.execute_statement("INSERT INTO Person ?", people)
```

リストを渡すときには、変数プレースホルダー (`?`) を二重山括弧 (`<<...>>`) で囲まないでください。マニュアルの PartiQL ステートメントでは、二重山括弧は**バッグと呼ばれる順序付けされていないコレクションを表します。

### ドキュメントの更新
<a name="cookbook-python.crud.updating"></a>

次のコード例では、ネイティブデータ型を使用します。

```
def update_documents(transaction_executor, gov_id, name):
    transaction_executor.execute_statement("UPDATE Person SET FirstName = ?  WHERE GovId = ?", name, gov_id)

gov_id = 'TOYENC486FH'
name = 'John'

qldb_driver.execute_lambda(lambda executor: update_documents(executor, gov_id, name))
```

次のコード例では、Ion データ型を使用します。

```
def update_documents(transaction_executor, gov_id, name):
    transaction_executor.execute_statement("UPDATE Person SET FirstName = ? WHERE GovId = ?", name, gov_id)

# Ion datatypes
gov_id = simpleion.loads('TOYENC486FH')
name = simpleion.loads('John')

qldb_driver.execute_lambda(lambda executor: update_documents(executor, gov_id, name))
```

**注記**  
この例では、`GovId` フィールドでインデックスを使用して、パフォーマンスを最適化することをお勧めします。`GovId` でインデックスをオンにしないと、ステートメントのレイテンシーが大きくなり、OCC 競合例外やトランザクションタイムアウトが発生する可能性があります。

### ドキュメントの削除
<a name="cookbook-python.crud.deleting"></a>

次のコード例では、ネイティブデータ型を使用します。

```
def delete_documents(transaction_executor, gov_id):
    cursor = transaction_executor.execute_statement("DELETE FROM Person WHERE GovId = ?", gov_id)

gov_id = 'TOYENC486FH'

qldb_driver.execute_lambda(lambda executor: delete_documents(executor, gov_id))
```

次のコード例では、Ion データ型を使用します。

```
def delete_documents(transaction_executor, gov_id):
    cursor = transaction_executor.execute_statement("DELETE FROM Person WHERE GovId = ?", gov_id)

# Ion datatypes
gov_id = simpleion.loads('TOYENC486FH')

qldb_driver.execute_lambda(lambda executor: delete_documents(executor, gov_id))
```

**注記**  
この例では、`GovId` フィールドでインデックスを使用して、パフォーマンスを最適化することをお勧めします。`GovId` でインデックスをオンにしないと、ステートメントのレイテンシーが大きくなり、OCC 競合例外やトランザクションタイムアウトが発生する可能性があります。

### トランザクションで複数のステートメントの実行
<a name="cookbook-python.crud.multi-statement"></a>

```
# This code snippet is intentionally trivial. In reality you wouldn't do this because you'd
# set your UPDATE to filter on vin and insured, and check if you updated something or not.

def do_insure_car(transaction_executor, vin):
    cursor = transaction_executor.execute_statement(
        "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", vin)
    first_record = next(cursor, None)
    if first_record:
        transaction_executor.execute_statement(
            "UPDATE Vehicles SET insured = TRUE WHERE vin = ?", vin)
        return True
    else:
        return False

def insure_car(qldb_driver, vin_to_insure):
    return qldb_driver.execute_lambda(
        lambda executor: do_insure_car(executor, vin_to_insure))
```

### 再試行ロジック
<a name="cookbook-python.crud.retry-logic"></a>

ドライバーの `execute_lambda` メソッドには、再試行可能な例外 (タイムアウトや OCC 競合など) が発生した場合にトランザクションを再試行する組み込みの再試行メカニズムがあります。

------
#### [ 3.x ]

再試行の最大数とバックオフ戦略を設定できます。

デフォルトの再試行制限は `4` であり、デフォルトのバックオフ戦略は `10` ミリ秒のベースを使用する[エクスポネンシャルバックオフとジッター](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)です。再試行設定は、[pyqldb.config.retry\$1config.RetryConfig](https://amazon-qldb-driver-python.readthedocs.io/en/stable/reference/config/retry_config.html#pyqldb.config.retry_config.RetryConfig) のインスタンスを使用して、ドライバーインスタンスごとおよびトランザクションごとに設定できます。

次のコード例では、ドライバーのインスタンスのカスタム再試行制限とカスタムバックオフ戦略を使用して再試行ロジックを指定します。

```
from pyqldb.config.retry_config import RetryConfig
from pyqldb.driver.qldb_driver import QldbDriver

# Configuring retry limit to 2
retry_config = RetryConfig(retry_limit=2)
qldb_driver = QldbDriver("test-ledger", retry_config=retry_config)

# Configuring a custom backoff which increases delay by 1s for each attempt.
def custom_backoff(retry_attempt, error, transaction_id):
    return 1000 * retry_attempt

retry_config_custom_backoff = RetryConfig(retry_limit=2, custom_backoff=custom_backoff)
qldb_driver = QldbDriver("test-ledger", retry_config=retry_config_custom_backoff)
```

次のコード例では、特定の Lambda 実行のカスタム再試行制限とカスタムバックオフ戦略を使用して再試行ロジックを指定します。`execute_lambda` のこの設定は、ドライバーインスタンスに設定された再試行ロジックを上書きします。

```
from pyqldb.config.retry_config import RetryConfig
from pyqldb.driver.qldb_driver import QldbDriver

# Configuring retry limit to 2
retry_config_1 = RetryConfig(retry_limit=4)
qldb_driver = QldbDriver("test-ledger", retry_config=retry_config_1)

# Configuring a custom backoff which increases delay by 1s for each attempt.
def custom_backoff(retry_attempt, error, transaction_id):
    return 1000 * retry_attempt

retry_config_2 = RetryConfig(retry_limit=2, custom_backoff=custom_backoff)

# The config `retry_config_1` will be overriden by `retry_config_2`
qldb_driver.execute_lambda(lambda txn: txn.execute_statement("CREATE TABLE Person"), retry_config_2)
```

------
#### [ 2.x ]

再試行の最大数は設定可能です。再試行制限を設定するには、`PooledQldbDriver` の初期化時に `retry_limit` プロパティを設定します。

デフォルトの再試行制限回数は `4` です。

------

### 一意性制約の実装
<a name="cookbook-python.crud.uniqueness-constraints"></a>

QLDB はユニークインデックスをサポートしていませんが、この動作をアプリケーションに実装できます。

`Person` テーブル内の `GovId` フィールドに対して一意性制約を実装するとします。これを行うには、以下を実行するトランザクションを記述します。

1. テーブルに指定された `GovId` を持つ既存のドキュメントがないことをアサートします。

1. アサーションに合格した場合は、ドキュメントを挿入します。

競合するトランザクションが同時にアサーションに合格すると、一方のトランザクションだけが正常にコミットされます。もう一方のトランザクションは OCC 競合例外で失敗します。

次のコード例は、この一意性制約ロジックを実装する方法を示しています。

```
def insert_documents(transaction_executor, gov_id, document):
    # Check if doc with GovId = gov_id exists
    cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", gov_id)
    # Check if there is any record in the cursor
    first_record = next(cursor, None)

    if first_record:
        # Record already exists, no need to insert
        pass
    else:
        transaction_executor.execute_statement("INSERT INTO Person ?", document)

qldb_driver.execute_lambda(lambda executor: insert_documents(executor, gov_id, document))
```

**注記**  
この例では、`GovId` フィールドでインデックスを使用して、パフォーマンスを最適化することをお勧めします。`GovId` でインデックスをオンにしないと、ステートメントのレイテンシーが大きくなり、OCC 競合例外やトランザクションタイムアウトが発生する可能性があります。

## Amazon Ion の操作
<a name="cookbook-python.ion"></a>

以下のセクションでは、Amazon Ion モジュールを使用して Ion データを処理する方法について説明します。

**Contents**
+ [Ion モジュールのインポート](#cookbook-python.ion.import)
+ [Ion 型の作成](#cookbook-python.ion.creating-types)
+ [Ion バイナリダンプの取得](#cookbook-python.ion.getting-binary)
+ [Ion テキストダンプの取得](#cookbook-python.ion.getting-text)

### Ion モジュールのインポート
<a name="cookbook-python.ion.import"></a>

```
import amazon.ion.simpleion as simpleion
```

### Ion 型の作成
<a name="cookbook-python.ion.creating-types"></a>

次のコード例では、Ion テキストから Ion オブジェクトを作成します。

```
ion_text = '{GovId: "TOYENC486FH", FirstName: "Brent"}'
ion_obj = simpleion.loads(ion_text)

print(ion_obj['GovId']) # prints TOYENC486FH
print(ion_obj['Name']) # prints Brent
```

次のコード例では、Python `dict` から Ion オブジェクトを作成します。

```
a_dict = { 'GovId': 'TOYENC486FH',
           'FirstName': "Brent"
         }
ion_obj = simpleion.loads(simpleion.dumps(a_dict))

print(ion_obj['GovId']) # prints TOYENC486FH
print(ion_obj['FirstName']) # prints Brent
```

### Ion バイナリダンプの取得
<a name="cookbook-python.ion.getting-binary"></a>

```
# ion_obj is an Ion struct
print(simpleion.dumps(ion_obj)) # b'\xe0\x01\x00\xea\xee\x97\x81\x83\xde\x93\x87\xbe\x90\x85GovId\x89FirstName\xde\x94\x8a\x8bTOYENC486FH\x8b\x85Brent'
```

### Ion テキストダンプの取得
<a name="cookbook-python.ion.getting-text"></a>

```
# ion_obj is an Ion struct
print(simpleion.dumps(ion_obj, binary=False)) # prints $ion_1_0 {GovId:'TOYENC486FH',FirstName:"Brent"}
```

Ion の操作方法の詳細については、GitHub で [Amazon Ion のドキュメント](http://amzn.github.io/ion-docs/)を参照してください。QLDB で Ion を操作するコード例については、「[Amazon QLDB で Amazon Ion のデータ型を操作する](driver-working-with-ion.md)」を参照してください。