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

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

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

プロパティ

transactionAutoCommit

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

ArcSDESQLExecute のプロパティ

メソッド

commitTransaction()

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

注意注意:

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

execute(sql_statement)

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

rollbackTransaction()

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

startTransaction()

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

ArcSDESQLExecute メソッド

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

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

変更内容がデータベースにコミットされるタイミングを制御するには、execute を呼び出す前に startTransaction メソッドを呼び出します。これによってトランザクションが開始され、commitTransaction メソッドが呼び出されるまで DML ステートメントはコミットされません。ArcSDE への接続が切断されたときにもコミットが行われます(トランザクション実行中に切断された場合の各 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 ArcSDE.
    # 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 ArcSDE connection file
    sde_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.
            sde_return = sde_conn.execute(sql)
        except Exception as err:
            print(err)
            sde_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(sde_return, list):
            print("Number of rows returned by query: {0} rows".format(
                len(sde_return)))
            for row in sde_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 sde_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 ArcSDE or GDB 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 ArcSDE.
    # Using the first method, pass a set of strings containing the
    #   connection properties:
    #   <serverName>, <portNumber>, <version>, <userName>, <password>
    sde_conn = arcpy.ArcSDESQLExecute("gpserver3", "5151", "#",
                                      "toolbox", "toolbox")

    # Using the second method pass the path to a valid ArcSDE connection file
    #   arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde")

    for tbl in tables:
        print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
        for col, val in 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))
                sde_return = sde_conn.execute(sql)
            except Exception as err:
                print(err)
                sde_return = False

            if isinstance(sde_return, list):
                if len(sde_return) > 0:
                    print("Identified {0} rows with incorrect data. Starting "
                          "transaction for update.".format(len(sde_return)))
                    # Start the transaction
                    sde_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))
                        sde_return = sde_conn.execute(sql)
                    except Exception as err:
                        print(err)
                        sde_return = False

                    # If the update completed successfully, commit the
                    # changes.  If not, rollback.
                    if sde_return == True:
                        print("Update statement: \n"
                              "{0} ran successfully.".format(sql))
                        # Commit the changes
                        sde_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))
                            sde_return = sde_conn.execute(sql)
                        except Exception as err:
                            print(err)
                            sde_return = False

                        if isinstance(sde_return, list):
                            print("{0} rows".format(len(sde_return)))
                            for row in sde_return:
                                print(row)
                            print("++++++++++++++++++++++++++++++++++++++++\n")
                        else:
                            if sde_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
                        sde_conn.rollbackTransaction()
                        print("Rolled back any changes.")
                        print("++++++++++++++++++++++++++++++++++++++++\n")
            else:
                print "No records required updating."

    # Disconnect and exit
    del sde_conn
    print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")

except Exception as err:
    print(err)

関連トピック

5/10/2014