Microsoft Access VBA для редактирования SQL-запросов - PullRequest
2 голосов
/ 12 февраля 2010

У меня есть база данных Access с одним запросом. В настоящее время я могу скопировать запрос через VBA, используя DoCmd.CopyObject. Тем не менее, мне нужно иметь возможность редактировать SQL в каждом экземпляре запроса в отдельности. Однако все примеры, которые я видел, включают набор записей, который я не использую.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 12 февраля 2010

Я все время так делаю! Я использовал VBA для перезаписи запросов Access, а также запросов, которые «проходят» в базу данных MySQL. Переписывание запроса в VBA зависит от того, насколько сложным вы хотите стать.

Я всегда использовал DAO, , который является более старой технологией (см. Комментарии ниже для пояснения по DAO против ADO), но в этом случае это работает для меня. Вам нужно будет добавить ссылку на DAO в VBA, выбрав Инструменты> Ссылки, а затем добавьте «Библиотека объектов Microsoft DAO 3.6».

Вы можете написать процедуру, которая выглядит следующим образом:

Sub RewriteQuerySQL(strQueryName As String, strParameter As String)
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Set db = CurrentDb()
    Set qdf = db.QueryDefs(strQueryName)

    qdf.SQL = "SELECT [Table].Field1, [Table].Field2 " & vbCrLf & _
              "FROM [Table] " & vbCrLf & _
              "WHERE ([Table].Field1 = " & chr(34) & strParameter & chr(34) & ");"
End Sub

Приведенный выше код изменит SQL для запроса, который вы задаете с помощью SQL-запроса в коде VBA с strParameter, встроенным в SQL-запрос.

Вот еще один способ сделать это. Это код, который я использовал в приложении для отчетов о продажах, чтобы переписать запрос, основанный на номере продавца:

Sub rewriteAccountsBySalesRepSortSQL(lngSalesRep As Long)
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strSQL As String
    Dim strOriginal As String
    Dim strReplacePart As String
    Dim strSQLReplace As String
    Dim lngLocSalesperson As Long
    Dim lngLocMyRoundUp As Long
    Dim lngLocParen As Long
    Dim lngLocEndParen As Long

    Set db = CurrentDb()
    Set qdf = db.QueryDefs("qryS Accounts by Sales Rep Sorted by Diff DESC")
    strSQL = qdf.SQL

    lngLocSalesperson = InStr(strSQL, "Salesperson1)=")
    lngLocEndParen = InStr(lngLocSalesperson + 14, strSQL, ")")
    strOriginal = Mid(strSQL, lngLocSalesperson, lngLocEndParen - lngLocSalesperson)
    'lngLocParen = InStrRev(strSQL, "(", lngLocSalesperson)

    strReplacePart = "Salesperson1)=" & lngSalesRep

    strSQLReplace = Replace(strSQL, strOriginal, strReplacePart)
    qdf.SQL = strSQLReplace
End Sub

Вместо того, чтобы выписывать весь запрос, код просто находит текущий номер торгового представителя и заменяет его новым номером. Я на самом деле предпочитаю последний метод. Последний метод использовался для отправки запроса непосредственно в MySQL, поэтому синтаксис с запросом Access может немного отличаться.

2 голосов
/ 12 февраля 2010

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

Вопрос, похоже, предполагает, что запросы в Access должны быть сохранены. Они не Вы можете выполнить любую произвольную строку SQL в любое время, либо в коде, либо (для не-DML SQL) в качестве источника записей формы или отчета. Строки SQL могут создаваться на лету и назначаться по мере необходимости во время выполнения - единственное преимущество сохраненного QueryDef - это необходимость его использования в нескольких местах.

Сохраненный QueryDef в основном совпадает с VIEW в базах данных сервера.

Если у QueryDef есть параметры, это эквивалентно простой ХРАНЕННОЙ ПРОЦЕДУРЕ (т. Е. Без кода, например, ветвление IF / THEN или CASE SELECT).

Если вы хотите реализовать SQL как VIEW в базе данных сервера, сохраните его как QueryDef в Access. Если вы сделаете это как SPROC в своей базе данных сервера, реализуйте его как запрос сохраненного параметра.

Но прежде всего определите, нужно ли его вообще сохранять.

Что бы это ни стоило, я профессионально программирую в Access с 1996 года, и я обычно не сохраняю много запросов, и особенно не сохраняю критерии в запросах. Критерии специфичны для контекста времени выполнения и должны предоставляться во время выполнения, а не сохраняться в QueryDef. Я использую сохраненные QueryDef для сложного SQL, который мне нужно использовать повторно, или для определения «представлений» (особенно тех, которые имеют сложные объединения), которые используются в нескольких местах приложения.

Оригинальный вопрос не определяет контекст, в котором необходимо изменение критериев, поэтому действительно невозможно предложить лучший подход. Это тот случай, когда я ошибся в вопросе об исключении надлежащего обсуждения, поскольку в нем предлагается конкретное РЕШЕНИЕ и спрашивается, как его реализовать, вместо того, чтобы описывать ПРОБЛЕМУ и запрашивать диапазон выполнимых решений. Чтобы сделать последнее, нам нужно знать о контексте (является ли SQL DML или SELECT? Используется ли он в коде или как источник записей для формы или отчета? И т. Д.), Но здесь этого совершенно не хватает поэтому полный спектр решений никогда не будет предложен.

1 голос
/ 12 февраля 2010

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

Затем, используя метод CopyObject, сделайте копию запроса, как вы это сделали. Используйте объект Catalog (вам нужно будет ссылаться на ADO Ext). Затем вы можете просто изменить SQL копии, как показано ниже. В зависимости от вашего запроса это может быть представление или процедура, но запрос выбора должен быть указан как представление.

Dim catDB As ADOX.Catalog
Dim cmd As ADODB.Command
Dim sQueryName As String
Dim sSQL As String

Set cn = CurrentProject.Connection
Set catDB = New ADOX.Catalog

catDB.ActiveConnection = cn
DoCmd.CopyObject , "Query1_c", acQuery, "Query1"
sQueryName = "Query1_c"
sSQL = "SELECT a,b,c FROM Table1"

Set cmd = New ADODB.Command
Set cmd = catDB.Views(sQueryName).Command
cmd.CommandText = sSQL
Set catDB.Views(sQueryName).Command = cmd

Set catDB = Nothing
cn.Close
...