Выполнение SQL с помощью подключения ArcSDE

Иногда, при работе с таблицами, не зарегистрированными как версионные, проще выполнить запрос к таблице в базе данных с помощью языка SQL, чем с помощью какого-либо из инструментов геообработки. Объект ArcSDESQLExecute поддерживает выполнение большинства SQL-инструкций и возвращает пользователю результаты этих инструкций. В случае, если инструкция возвращает строки из таблицы, объект возвращает список списков; для инструкций, не возвращающих строки, он возвращает признак успеха или ошибки инструкции (True для успеха, None для ошибки).

ВниманиеВнимание:
  • Системные таблицы ArcSDE и GDB не следует изменять другими средствами, кроме программного обеспечения ArcGIS. При редактировании данных системных таблиц напрямую с помощью SQL возможно их повреждение.
  • Редактирование версионных данных, выполняемое с помощью SQL, должно производиться только посредством версионных представлений.
  • Для баз геоданных, реализованных в системе управления реляционной базой данных (СУБД), с помощью типов данных и форматов таблиц СУБД для работы с информацией, хранимой в базе данных, может использоваться собственный SQL СУБД.
  • Доступ к информации в базе геоданных с помощью SQL позволяет внешним приложениям получать доступ к табличным данным, управляемым базой геоданных. Эти внешние приложения могут быть непространственными приложениями базы данных или пользовательскими пространственными приложениями, разработанными в среде, отличной от ArcObjects. Тем не менее, помните, что SQL-доступ к базе геоданных не учитывает такую функциональность базы геоданных, как топология, сети, наборы данных terrain и другие классы и расширения рабочего пространства.
  • Возможно использование объектов СУБД, таких как триггеры и хранимые процедуры, для поддержки связей между таблицами, которые требуются для определенной функциональности базы геоданных. Но выполнение SQL-команд в отношении базы данных без учета этой дополнительной функциональности — например использование инструкции INSERT для добавления записей в бизнес-таблицу — обходит функциональность базы геоданных и может повредить связи между данными в базе геоданных.
  • Прежде чем производить доступ к любому из объектов ArcSDE или GDB или изменять такой объект, прочтите всю документацию ArcSDE и базы геоданных по использованию SQL в отношении объектов ArcSDE и GDB в СУБД.

Свойство

transactionAutoCommit

Интервал автоподтверждения (autocommit). Его можно использовать для принудительного промежуточного подтверждения после изменения указанного количества объектов.

Свойства ArcSDESQLExecute

Методы

commitTransaction()

Никакие выражения DML не будут подтверждены, пока не будет вызван метод commitTransaction.

ПримечаниеПримечание:

Подтверждение также может производиться при отсоединении ArcSDE (см. в документации соответствующей СУБД сведения о том, как СУБД реагирует на отсоединение во время транзакции).

execute(sql_statement)

Отправляет SQL-инструкцию в базу данных через подключение ArcSDE. Если выполнение производится вне транзакции, подтверждение производится автоматически, сразу после выполнения инструкции SQL DML (INSERT, UPDATE, DELETE).

rollbackTransaction()

Откатывает любую операцию DML, выполненную после предыдущего подтверждения.

startTransaction()

Для контроля времени, когда изменения будут подтверждены в базе данных, вызовите метод startTransaction до вызова метода execute. Будет запущена транзакция, и никакие выражения DML не будут подтверждены, пока не будет вызван метод commitTransaction.

Методы ArcSDESQLExecute

Метод execute отправляет SQL-инструкцию в базу данных через подключение ArcSDE. Если выполнение производится вне транзакции, подтверждение производится автоматически, сразу после выполнения инструкции SQL DML (INSERT, UPDATE, DELETE).

ArcSDESQLExecute поддерживает модель транзакций ArcSDE. Транзакции являются свойством подключения ArcSDE и связывают операции таким образом, что целый набор изменений либо вносится, либо отвергается. Например, если набор участков обновляется в определенном порядке, с помощью транзакции можно определить начало и конец изменений, чтобы все изменения были внесены вместе. Если набор изменений не удалось успешно внести, отвергается вся транзакция целиком. Все транзакции завершаются при отключении пользователя. ArcSDESQLExecute использует для начала, подтверждения и отката транзакций предоставленные функции ArcSDE API.

При необходимости контроля времени, когда изменения будут подтверждены в базе данных, вызовите метод startTransaction до вызова метода execute. Будет запущена транзакция, и никакие выражения DML не будут подтверждены, пока не будет вызван метод commitTransaction. Подтверждение также может производиться при отсоединении ArcSDE (см. в документации соответствующей СУБД сведения о том, как СУБД реагирует на отсоединение во время транзакции). При работе с транзакцией также возможно откатить любую операцию DML, выполненную после предыдущего подтверждения.

Доступно свойство интервала автоподтверждения — transactionAutoCommit. Его можно использовать для принудительного промежуточного подтверждения после изменения указанного количества объектов.

Справку по написанию SQL-инструкций см. в справочнике по SQL конкретной СУБД.

Примеры

Выполнение списка SQL-инструкций
import arcpy
from arcpy import env
import sys

try:
    # Make data path relative
    #
    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>
    #   sdeConn = arcpy.ArcSDESQLExecute("gpserver3","5151","#","toolbox","toolbox")
    #   Using the second method pass the path to a valid ArcSDE connection file
    #
    sdeConn = arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde")
    
    # Get the SQL statements, separated by ; from a text string.
    #
    SQLStatement = arcpy.GetParameterAsText(0)
    SQLStatementList = SQLStatement.split(";")
    
    print "+++++++++++++++++++++++++++++++++++++++++++++\n"

    # For each SQL statement passed in, execute it.
    #
    for sql in SQLStatementList:
        print "Execute SQL Statement: " + sql
        try:
            # Pass the SQL statement to the database.
            #
            sdeReturn = sdeConn.execute(sql)
        except Exception, ErrorDesc:
            print ErrorDesc
            sdeReturn = 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(sdeReturn, list):
            print "Number of rows returned by query: " + str(len(sdeReturn)), "rows"
            for row in sdeReturn:
                print row
            print "+++++++++++++++++++++++++++++++++++++++++++++\n"
        else:
            # If the return value was not a list, the statement was most likely a DDL statment. 
            #   Check its status.
            if sdeReturn == True:
                print "SQL statement: " + sql + " ran sucessfully."
                print "+++++++++++++++++++++++++++++++++++++++++++++\n"
            else:
                print "SQL statement: " + sql + " FAILED."
                print "+++++++++++++++++++++++++++++++++++++++++++++\n"
                
except Exception, ErrorDesc:
    print Exception, ErrorDesc
except:
    print "Problem executing SQL."
Обновление при определенных условиях с помощью транзакции
# 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 arcpy
from arcpy import env
import sys

try:
    # Make data path relative (not relevant unless data is moved here and paths modified)
    #
    env.workspace = sys.path[0]

    #Column name:value that should be in the record.
    #
    SQLvalues = {"STREET_NAM":"'EUREKA'"}

    #Value that is incorrect if found in the above column.
    #
    badVal = "'EREKA'"

    #List of tables to look in for the bad value.
    #
    tableList = ["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>
    #
    sdeConn = arcpy.ArcSDESQLExecute("gpserver3","5151","#","toolbox","toolbox")

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

    for tbl in tableList:
        print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
        for col, val in SQLvalues.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 " + tbl + " for bad data: Column:" + col + " Value: " + badVal
            try:
                sql = "select OBJECTID," + col + " from " + tbl + " where " + col + " = " + badVal
                print "Attempt to execute SQL Statement: " + sql
                sdeReturn = sdeConn.execute(sql)
            except Exception, ErrorDesc:
                print ErrorDesc
                sdeReturn = False
            if isinstance(sdeReturn, list):
                if len(sdeReturn) > 0:
                    print "Identified " + str(len(sdeReturn)) + " rows with incorrect data. Starting transaction for update."
                    # Start the transaction
                    #
                    sdeConn.startTransaction()
                    print "Transaction started....."
                    # Perform the update
                    #
                    try:
                        sql = "update " + tbl + " set " + col + "=" + str(val) + " where " + col + " = " + badVal
                        print "Changing bad value: " + badVal + " to the good value: " + val + " using update statement:\n " + sql
                        sdeReturn = sdeConn.execute(sql)
                    except Exception, ErrorDesc:
                        print ErrorDesc
                        sdeReturn = False

                    # If the update completed sucessfully, commit the changes.  If not, rollback.
                    #
                    if sdeReturn == True:
                        print "Update statement: \n" + sql + " ran successfully."
                        # Commit the changes
                        #
                        sdeConn.commitTransaction()
                        print "Commited Transaction"

                        # List the changes.
                        #
                        try:
                            print "Displaying updated rows for visual inspection."
                            sql = "select OBJECTID," + col + " from " + tbl + " where " + col + " = " + val
                            print "Executing SQL Statement: \n" + sql
                            sdeReturn = sdeConn.execute(sql)
                        except Exception, ErrorDesc:
                            print ErrorDesc
                            sdeReturn = False
                        if isinstance(sdeReturn, list):
                            print len(sdeReturn), "rows"
                            for row in sdeReturn:
                                print row
                            print "+++++++++++++++++++++++++++++++++++++++++++++\n"
                        else:
                            if sdeReturn == True:
                                print "SQL statement: \n" + sql + "\nran successfully."
                                print "+++++++++++++++++++++++++++++++++++++++++++++\n"
                            else:
                                print "SQL statement: \n" + sql + "\nFAILED."
                                print "+++++++++++++++++++++++++++++++++++++++++++++\n"

                        print "+++++++++++++++++++++++++++++++++++++++++++++\n"
                    else:
                        print "SQL statement: \n" + sql + "\nFAILED.  Rolling back all changes."
                        # Rollback changes
                        #
                        sdeConn.rollbackTransaction()
                        print "Rolled back any changes."
                        print "+++++++++++++++++++++++++++++++++++++++++++++\n"
            else:
                print "No records required updating."
            
    # Disconnect and exit
    del sdeConn
    print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

except Exception, ErrorDesc:
    print Exception, ErrorDesc
except:
    print "Problem executing SQL."

Связанные темы

9/11/2013