Вопрос

Я хочу выполнить список запросов к базе данных Access, используя DAO.Метод «Database.Execute()» кажется подходящим для этого с замечанием, что он может выполнять только «запросы действий», то есть запросы, которые не возвращают набор результатов (Справочник MSDN).Для запросов, возвращающих записи, можно использовать «Database.OpenRecordset()».Оба метода генерируют исключения, если передается неправильный тип запроса.

Имея в списке как запросы действий, так и запросы выбора, как я могу заранее решить, какие записи будут возвращать, а какие нет?

Это было полезно?

Решение 3

Вдохновленный ответом @ HansUp, я немного больше изучил структуру QueryDef, предоставляемую интерфейсом DAO. Структура имеет тип "Тип" свойство, которое я могу использовать для различения различных типов запросов ( MSDN ) , Я закончил со следующей реализацией:

function TAccessDatabase.SQLExec(AName, AQuery: String): Integer;
var
  I: Integer;
  QDef: QueryDef;
  QDefExists: Boolean;
begin
  Result := 0;

  // Lookup querydef in the database
  QDefExists := False;
  for I := 0 to DB.QueryDefs.Count - 1 do
  begin
    QDef := DB.QueryDefs[I];
    if QDef.Name = AName then
    begin
      QDefExists := True;
      break; //-->
    end;
  end;

  // Create query def if it doesn't exists
  if not QDefExists then
  begin
    QDef := DB.CreateQueryDef(AName, AQuery);
    // Refresh is required to get the correct QDef.Type_
    DB.QueryDefs.Refresh;
  end;

  // Execute the query only if it is not a SELECT
  if QDef.Type_ <> dbQSelect then
  begin
    db.Execute(AQuery, dbInconsistent);
    Result := DB.RecordsAffected;
  end;
end;

Спасибо всем за полезные ответы и замечания.

Другие советы

Обратите внимание, что метод ADO Execute можно использовать независимо от того, возвращает ли запрос набор результатов.

Но действительно ли вы хотите выполнить все «запросы»?Что, если они содержат SQL DDL?Предположим, вы создали PROCEDURE используя этот код SQL DDL:

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

Access поддерживает скрытую системную таблицу MSysObjects, которая включает в себя поле (Flags), в котором хранится значение, указывающее тип запроса. Вы можете попробовать следующую функцию с каждым из имен запросов из вашего списка и использовать возвращаемое значение, чтобы определить, использовать ли Database.Execute () или Database.OpenRecordset ()

Функция требует разрешения на чтение для MSysObjects. Я слышал сообщения о том, что некоторым пользователям Access 2007 отказано в разрешении читать MSysObjects. Однако я не сталкивался с этой проблемой в Access 2007.

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

Единственным протестированным DDL-запросом был DROP TABLE (Flags = 96).

Также учтите, что не все " SELECT ... FROM ... " запросы - это выборочные запросы для вашей цели (возвращение набора записей). Запрос, такой как " SELECT fields INTO newtable FROM oldtable; " не возвращает записи, и пользовательский интерфейс Access классифицирует его как запрос Make Table.

Public Function QueryType(ByVal pQueryName As String) As String
    Dim lngFlags As Long
    Dim strType As String
    Dim strCriteria As String

    strCriteria = "[Name] = """ & pQueryName & """ And [Type] = 5"
    lngFlags = DLookup("Flags", "MSysObjects", strCriteria)

    Select Case lngFlags
    Case 0
        strType = "Select"
    Case 16
        strType = "Crosstab"
    Case 32
        strType = "Delete"
    Case 48
        strType = "Update"
    Case 64
        strType = "Append"
    Case 80
        strType = "Make Table"
    Case 96
        strType = "Drop Table"
    Case 128
        strType = "Union"
    Case Else
        strType = "Flags " & CStr(lngFlags) & " unrecognized"
    End Select

    QueryType = strType
End Function

Почему бы вам не поймать выброшенное исключение и не проанализировать его?

У вас есть какой-нибудь способ использовать инструкцию beginTrans / Rollback? Затем вы можете отправить свою команду SQL, собрать ошибки, а затем откатить транзакции, оставив базу данных без изменений.

Как насчет использования соединения ADO, несколько умнее, чем соединение ADO, где соединение содержит коллекцию «ошибок» и возвращает некоторые другие данные, например количество затронутых записей?

Эта информация относится к типу запроса.Так:

  • Все запросы, выполняющие ВЫБИРАТЬ ...ОТ ... являются выбрать запросы
  • Все ВСТАВЛЯТЬ, ОБНОВЛЯТЬ, УДАЛИТЬ являются запросы действий

Вам просто нужно проверить текст команды sql-запроса, чтобы посмотреть, начинается ли он с любого из приведенных выше ключевых слов, и действовать соответствующим образом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top