Ausführen von SQL mit einer ArcSDE-Verbindung

Bei nicht versionierten Tabellen empfiehlt sich in vielen Fällen die Abfrage einer Tabelle in einer Datenbank per SQL (Structured Query Language) anstatt mit einem Geoverarbeitungswerkzeug. Das ArcSDESQLExecute-Objekt unterstützt die meisten SQL-Anweisungen und gibt die Ergebnisse dieser Anweisungen an die Benutzer zurück. Bei Anweisungen, die Tabellenzeilen zurückgeben, liefert das Objekt eine Listenauflistung. Bei Anweisungen, die keine Zeilen zurückgeben, zeigt das Objekt an, ob die Anweisung erfolgreich war (True) oder fehlgeschlagen ist (None). Anweisungen, die einen einzigen Wert aus einer einzigen Zeile zurückgeben, geben diesen Wert als entsprechenden Typ (string, float) aus.

AchtungAchtung:
  • ArcSDE- und GDB-Systemtabellen dürfen nur mit der ArcGIS-Software geändert werden. Diese Systemtabellen können beschädigt werden, wenn sie direkt mit SQL bearbeitet werden.
  • Die Bearbeitung versionierter Daten per SQL sollte nur über versionierte Sichten erfolgen.
  • Bei Geodatabases, die in einem relationalen Datenbankmanagementsystem (DBMS) mit DBMS-Datentypen und -Tabellenformaten implementiert sind, können Sie die SQL des DBMS nutzen, um mit den in der Datenbank gespeicherten Informationen zu arbeiten.
  • Erfolgt der Zugriff auf die Informationen in einer Geodatabase über SQL, können externe Anwendungen auf die Tabellendaten zugreifen, die von der Geodatabase verwaltet werden. Bei diesen externen Anwendungen kann es sich um nicht räumliche Datenbankanwendungen oder benutzerdefinierte räumliche Anwendungen handeln, die in einer anderen Umgebung als ArcObjects entwickelt wurden. Wenn Sie über SQL auf die Geodatabase zugreifen, stehen jedoch nicht alle Geodatabase-Funktionen zur Verfügung, zum Beispiel Topologie, Netzwerke, Terrains oder andere Klassen- bzw. Workspace-Erweiterungen.
  • DBMS-Funktionen wie Trigger und gespeicherte Prozeduren können u. U. zur Verwaltung von Beziehungen zwischen Tabellen verwendet werden, die für bestimmte Geodatabase-Funktionen erforderlich sind. Wenn Sie jedoch die SQL-Befehle in der Datenbank ausführen, ohne diese zusätzliche Funktionalität zu berücksichtigen (z. B. beim Einfügen von Datensätzen in eine Business-Tabelle mit einer INSERT-Anweisung), wird die Geodatabase-Funktionalität umgangen und die Beziehungen zwischen den Daten in der Geodatabase können beschädigt werden.
  • Lesen Sie möglichst in der ArcSDE- und Geodatabase-Dokumentation alle Informationen zur Verwendung von SQL bei ArcSDE- bzw. GDB-Objekten im DBMS, bevor Sie auf ArcSDE- oder GDB-Objekte zugreifen bzw. diese bearbeiten.

Eigenschaft

transactionAutoCommit

Das autocommit-Intervall. Sie können mit dieser Eigenschaft festlegen, dass nach der Bearbeitung einer bestimmten Anzahl von Features jeweils ein COMMIT durchgeführt wird.

ArcSDESQLExecute-Eigenschaften

Methoden

commitTransaction()

Es werden keine DML-Anweisungen übernommen, bevor die commitTransaction-Methode aufgerufen wird.

HinweisHinweis:

Ein COMMIT kann jedoch auch auftreten, wenn die Verbindung mit ArcSDE beendet wird. (Die DBMS-Dokumentation enthält Informationen dazu, wie einzelne DBMS mit einer Verbindungsunterbrechung während einer Transaktion umgehen.)

execute(sql_statement)

Sendet die SQL-Anweisung über eine ArcSDE-Verbindung an die Datenbank. Falls "execute" außerhalb einer Transaktion ausgeführt wird, findet automatisch ein COMMIT statt, sobald die SQL-DML-Anweisung (INSERT, UPDATE, DELETE) ausgeführt wurde.

rollbackTransaction()

Alle DML-Vorgänge werden bis zum letzten COMMIT rückgängig gemacht.

startTransaction()

Um zu steuern, wann die Änderungen in die Datenbank übernommen werden, rufen Sie die Methode startTransaction vor der Methode "execute" auf. Hierdurch wird die Transaktion gestartet und alle DML-Anweisungen werden erst übernommen, wenn die Methode commitTransaction aufgerufen wird.

ArcSDESQLExecute-Methoden

Die execute-Methode sendet die SQL-Anweisung über eine ArcSDE-Verbindung an die Datenbank. Falls "execute" außerhalb einer Transaktion ausgeführt wird, findet automatisch ein COMMIT statt, sobald die SQL-DML-Anweisung (INSERT, UPDATE, DELETE) ausgeführt wurde.

"ArcSDESQLExecute" unterstützt das ArcSDE-Transaktionsmodell. Transaktionen sind eine Eigenschaft der ArcSDE-Verbindung und binden Vorgänge, sodass ganze Änderungssätze in ihrer Gesamtheit erfasst oder abgelehnt werden. Wenn etwa eine Gruppe von Flurstücken in einer bestimmten Reihenfolge aktualisiert wird, können Sie mit einer Transaktion den Anfang und das Ende der Änderungen festlegen, sodass alle Änderungen zusammen zurückgeschrieben werden. Falls ein Änderungssatz nicht eingefügt werden kann, wird die gesamte Transaktion abgelehnt. Alle Transaktionen werden beendet, wenn die Verbindung unterbrochen wird. ArcSDESQLExecute verwendet die bereitgestellten ArcSDE-API-Funktionen, um Transaktionen zu starten, zu übernehmen und rückgängig zu machen.

Falls Sie steuern möchten, wann die Änderungen in die Datenbank übernommen werden, rufen Sie die Methode startTransaction vor der Methode "Execute" auf. Hierdurch wird die Transaktion gestartet und alle DML-Anweisungen werden erst übernommen, wenn die Methode commitTransaction aufgerufen wird. Ein COMMIT kann jedoch auch auftreten, wenn die Verbindung mit ArcSDE beendet wird. (Die DBMS-Dokumentation enthält Informationen dazu, wie einzelne DBMS mit einer Verbindungsunterbrechung während einer Transaktion umgehen.) Innerhalb einer Transaktion können alle DML-Vorgänge bis zum vorherigen COMMIT rückgängig gemacht werden.

transactionAutoCommit steht als Eigenschaft für das Intervall zwischen automatischen COMMITS zur Verfügung. Sie können mit dieser Eigenschaft festlegen, dass nach der Bearbeitung einer bestimmten Anzahl von Features jeweils ein COMMIT durchgeführt wird.

Informationen zum Schreiben von SQL-Anweisungen finden Sie in Ihrem spezifischen DBMS-SQL-Referenzhandbuch.

Beispiele

Ausführen einer Liste von SQL-Anweisungen
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)
Bedingte Aktualisierung mit einer Transaktion
# 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)

Verwandte Themen

5/9/2014