EGDB 接続を使用した SQL の実行

バージョン対応登録されていないテーブルを操作するときに、ジオプロセシング ツールを使用するよりも、SQL (Structured Query Language) を使用してデータベース内の表を検索した方が簡単な場合があります。ArcSDESQLExecute オブジェクトは、ほとんどの SQL ステートメントの実行をサポートし、これらのステートメントの結果を返します。このオブジェクトは、ステートメントがテーブルから行を返す場合にはリストのリストを返し、行を返さないステートメントの場合はステートメントの成功または失敗の指標 (成功の場合は True、失敗の場合は None) を返します。単一の行から単一の値を返すステートメントによって、適切なタイプの値が返されます (string、float など)。

注意:
  • ArcGIS ソフトウェア以外のものを使用してエンタープライズ ジオデータベースのシステム テーブルを変更することはできません。SQL を使用してこれらのシステム テーブルを直接編集すると、ジオデータベースを破損する可能性があります。
  • SQL を使用してバージョン対応登録されたデータを編集する場合は、必ずバージョン ビューから行う必要があります。
  • リレーショナル データベース管理システム (DBMS) のデータ タイプとテーブル フォーマットを使用して DBMS に実装されたジオデータベースの場合は、DBMS 独自の SQL を使用して、データベースに格納された情報を操作できます。
  • SQL によってジオデータベースの情報にアクセスすれば、ジオデータベースによって管理されるテーブル データに外部アプリケーションからアクセスできます。この外部アプリケーションは、非空間データベース アプリケーションであっても、ArcObjects 以外の環境で開発されたカスタムの空間アプリケーションであってもかまいません。ただし、ジオデータベースへの SQL アクセス時には、トポロジ、ネットワーク、テレイン、その他のクラスやワークスペースのエクステンションなど、ジオデータベースの機能は適用されないことに注意してください。
  • 一部のジオデータベース機能に必要なテーブル間の関係を維持するために、トリガーやストアド プロシージャなどの DBMS 機能を使用できる場合があります。一方で、これらの機能を考慮せずにデータベースに対して SQL コマンドを実行すると (たとえば、INSERT ステートメントを実行してビジネス テーブルにレコードを追加する)、ジオデータベース機能が適用されず、ジオデータベース内のデータ間の関係が破壊される可能性があります。
  • エンタープライズ ジオデータベースのオブジェクトにアクセスしたり、これらのオブジェクトを変更したりする前に、DBMS 内でジオデータベースのオブジェクトに対して SQL を使用する場合の注意点について、エンタープライズ ジオデータベースの資料をすべてお読みください。

プロパティ

transactionAutoCommit

自動コミット間隔。これは、指定された数のフィーチャが変更された後の中間コミットを実行するために使用できます。

ArcSDESQLExecute のプロパティ

メソッド

commitTransaction()

commitTransaction メソッドが呼び出されるまで DML ステートメントはコミットされません。

メモ:

エンタープライズ ジオデータベースへの接続が切断されたときにもコミットが行われます (トランザクション実行中に切断された場合の各 DBMS の対処方法については、DBMS のドキュメントをご参照ください)。

execute(sql_statement)

エンタープライズ ジオデータベース接続を経由してデータベースに SQL ステートメントを送信します。トランザクションの外部で execute を実行すると、SQL DML (INSERT、UPDATE、DELETE) ステートメントが実行された後でコミットが自動的に行われます。

rollbackTransaction()

前回コミット時の状態まで DML 操作をロールバックします。

startTransaction()

変更内容がデータベースにコミットされるタイミングを制御するには、execute を呼び出す前に startTransaction メソッドを呼び出します。これによってトランザクションが開始され、commitTransaction メソッドが呼び出されるまで DML ステートメントはコミットされません。

ArcSDESQLExecute メソッド

execute メソッドは、エンタープライズ ジオデータベース接続を経由してデータベースに SQL ステートメントを送信します。トランザクションの外部で execute を実行すると、SQL DML (INSERT、UPDATE、DELETE) ステートメントが実行された後でコミットが自動的に行われます。

ArcSDESQLExecute はジオデータベースのトランザクション モデルをサポートします。トランザクションはエンタープライズ ジオデータベース接続およびバインド操作のプロパティで、一連の変更が全体としてまとめて記録または拒否されるようにするためのものです。たとえば、一連の土地区画を特定の順序で更新する場合は、トランザクションを使用して変更の開始と終了を定義することによって、すべての変更がまとめてポストされるようになります。一連の変更を正常に挿入できない場合は、トランザクション全体が拒否されます。ユーザーが接続を切断するとすべてのトランザクションが終了します。ArcSDESQLExecute は標準のエンタープライズ ジオデータベース API 関数を使用して、トランザクションを開始、コミット、およびロールバックします。

変更内容がデータベースにコミットされるタイミングを制御するには、execute を呼び出す前に startTransaction メソッドを呼び出します。これによってトランザクションが開始され、commitTransaction メソッドが呼び出されるまで DML ステートメントはコミットされません。エンタープライズ ジオデータベースへの接続が切断されたときにもコミットが行われます (トランザクション実行中に切断された場合の各 DBMS の対処方法については、DBMS のドキュメントをご参照ください)。トランザクション内では、DML 操作を前回コミット時の状態までロールバックすることも可能です。

自動コミット間隔のプロパティ transactionAutoCommit が提供されています。これは、指定された数のフィーチャが変更された後の中間コミットを実行するために使用できます。

SQL ステートメントの作成方法については、ご使用の DBMS の SQL リファレンス ガイドをご参照ください。

SQL ステートメントのリストを実行する
import sys
import arcpy
try:
    # Make data path relative
    arcpy.env.workspace = sys.path[0]
    # Two ways to create the object, which also creates the
    # connection to the enterprise geodatabase.
    # Using the first method, pass a set of strings containing
    # the connection properties:
    #   <serverName>, <portNumber>, <version>, <userName>, <password>
    #   arcpy.ArcSDESQLExecute("gpserver3","5151","#","toolbox","toolbox")
    # Using the second method pass the path to a valid connection file
    egdb_conn = arcpy.ArcSDESQLExecute(r"data\Connection to GPSERVER3.sde")
    # Get the SQL statements, separated by ; from a text string.
    sql_statement = arcpy.GetParameterAsText(0)
    sql_statement_list = sql_statement.split(";")
    print("+++++++++++++++++++++++++++++++++++++++++++++\n")
    # For each SQL statement passed in, execute it.
    for sql in sql_statement_list:
        print("Execute SQL Statement: {0}".format(sql))
        try:
            # Pass the SQL statement to the database.
            egdb_return = egdb_conn.execute(sql)
        except Exception as err:
            print(err)
            egdb_return = False
        # If the return value is a list (a list of lists), display
        # each list as a row from the table being queried.
        if isinstance(egdb_return, list):
            print("Number of rows returned by query: {0} rows".format(
                len(egdb_return)))
            for row in egdb_return:
                print(row)
            print("+++++++++++++++++++++++++++++++++++++++++++++\n")
        else:
            # If the return value was not a list, the statement was
            # most likely a DDL statement. Check its status.
            if egdb_return == True:
                print("SQL statement: {0} ran successfully.".format(sql))
            else:
                print("SQL statement: {0} FAILED.".format(sql))
            print("+++++++++++++++++++++++++++++++++++++++++++++\n")
except Exception as err:
    print(err)
トランザクションを使用した条件付き更新
# WARNING - DO NOT USE ON VERSIONED TABLES OR FEATURE CLASSES.
#   DO NOT USE ON ANY enterprise geodatabase SYSTEM TABLES.
#   DOING SO MAY RESULT IN DATA CORRUPTION.
import sys
import arcpy
try:
    # Make data path relative (not relevant unless data is moved
    # here and paths modified)
    arcpy.env.workspace = sys.path[0]
    # Column name:value that should be in the record.
    sql_values = {"STREET_NAM": "'EUREKA'"}
    # Value that is incorrect if found in the above column.
    bad_val = "'EREKA'"
    #List of tables to look in for the bad value.
    tables = ["streetaddresses_blkA", "streetaddresses_blkB",
              "streetaddresses_blkC"]
    # Two ways to create the object, which also creates the connection
    # to the enterprise geodatabase.
    # Using the first method, pass a set of strings containing the
    #   connection properties:
    #   <serverName>, <portNumber>, <version>, <userName>, <password>
    egdb_conn = arcpy.ArcSDESQLExecute("gpserver3", "5151", "#",
                                      "toolbox", "toolbox")
    # Using the second method pass the path to a valid enterprise geodatabase connection file
    #   arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde")
    for tbl in tables:
        print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
        for col, val in list(sql_values.items()):
            print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
            # Check for the incorrect value in the column for the
            # specific rows. If the table contains the incorrect value,
            # correct it using the update SQL statement.
            print("Analyzing table {0} for bad data: "
                  "Column:{1} Value: {2}".format(tbl, col, bad_val))
            try:
                sql = "select OBJECTID,{0} from {1} where {0} = {2}".format(
                      col, tbl, bad_val)
                print("Attempt to execute SQL Statement: {0}".format(sql))
                egdb_return = egdb_conn.execute(sql)
            except Exception as err:
                print(err)
                egdb_return = False
            if isinstance(egdb_return, list):
                if len(egdb_return) > 0:
                    print("Identified {0} rows with incorrect data. Starting "
                          "transaction for update.".format(len(egdb_return)))
                    # Start the transaction
                    egdb_conn.startTransaction()
                    print("Transaction started...")
                    # Perform the update
                    try:
                        sql = "update {0} set {1}={2} where {1} = {3}".format(
                              tbl, col, val, bad_val)
                        print("Changing bad value: {0} to the good value: "
                              "{1} using update statement:\n {2}".format(
                              bad_val, val, sql))
                        egdb_return = egdb_conn.execute(sql)
                    except Exception as err:
                        print(err)
                        egdb_return = False
                    # If the update completed successfully, commit the
                    # changes.  If not, rollback.
                    if egdb_return == True:
                        print("Update statement: \n"
                              "{0} ran successfully.".format(sql))
                        # Commit the changes
                        egdb_conn.commitTransaction()
                        print("Committed Transaction")
                        # List the changes.
                        try:
                            print("Displaying updated rows for "
                                  "visual inspection.")
                            sql = "select OBJECTID" + \
                                  ",{0} from {1} where {0} = {2}".format(
                                  col, tbl, val)
                            print("Executing SQL Statement: \n{0}".format(sql))
                            egdb_return = egdb_conn.execute(sql)
                        except Exception as err:
                            print(err)
                            egdb_return = False
                        if isinstance(egdb_return, list):
                            print("{0} rows".format(len(egdb_return)))
                            for row in egdb_return:
                                print(row)
                            print("++++++++++++++++++++++++++++++++++++++++\n")
                        else:
                            if egdb_return == True:
                                print("SQL statement: \n{0}\n"
                                      "ran successfully.".format(sql))
                            else:
                                print("SQL statement: \n{0}\n"
                                      "FAILED.".format(sql))
                            print("++++++++++++++++++++++++++++++++++++++++\n")
                        print("++++++++++++++++++++++++++++++++++++++++\n")
                    else:
                        print("SQL statement: \n{0}\nFAILED. "
                              "Rolling back all changes.".format(sql))
                        # Rollback changes
                        egdb_conn.rollbackTransaction()
                        print("Rolled back any changes.")
                        print("++++++++++++++++++++++++++++++++++++++++\n")
            else:
                print "No records required updating."
    # Disconnect and exit
    del egdb_conn
    print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
except Exception as err:
    print(err)

このトピックの内容