Выполнение выражений SQL с использованием подключения к многопользовательской базе геоданных

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

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

Свойство

transactionAutoCommit

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

Свойства ArcSDESQLExecute

Методы

commitTransaction()

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

Примечание:

Закрепление также может произойти при разрыве соединения с многопользовательской базой геоданных. Проверьте документацию по конкретной СУБД, чтобы узнать, как каждая СУБД справляется с отключением во время транзакции.

execute(sql_statement)

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

rollbackTransaction()

Откатывает все операции DML, выполненные после предыдущего закрепления (commit).

startTransaction()

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

Методы ArcSDESQLExecute

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

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

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

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

См. справочное руководство по SQL вашей конкретной СУБД для получения помощи по написанию выражений 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)

В этом разделе
  1. Примеры