Домой / Интересное / Vba запросы sql. Выполнить запрос из Access через Excel Query в VBA. Исходные данные для примеров

Vba запросы sql. Выполнить запрос из Access через Excel Query в VBA. Исходные данные для примеров

С помощью макрокоманды ОткрытьЗапрос в базах данных Access можно открывать запросы на выборку и перекрестные запросы в режиме таблицы, в Конструкторе или в режиме предварительного просмотра. Это действие запускает запрос на изменение. Вы также можете выбрать режим ввода данных для запроса.

Примечание: Данная макрокоманда доступна только в среде базы данных Access (MDB или ACCDB). Если вы используете среду проекта Access (ADP), см. макрокоманды ОткрытьПредставление , ОткрытьСохраненнуюПроцедуру и ОткрытьФункцию . Макрокоманда ОткрытьЗапрос недоступна в веб-приложениях Access.

Настройка

Макрокоманда ОткрытьЗапрос имеет следующие аргументы:

Аргумент макрокоманды

Описание

Имя запроса

Имя открываемого запроса. Выберите имя в раскрывающемся списке. Это обязательный аргумент.

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

Представление, в котором будет открываться запрос. Выберите в поле Вид значение Таблица , Конструктор , Предварительный просмотр , Сводная таблица или Сводная диаграмма . По умолчанию используется Таблица .

Примечание: Представления "Сводная таблица" и "Сводная диаграмма" недоступны в версиях Access, начиная с Access 2013.

Режим данных

Режим ввода данных для запроса. Этот параметр относится только к запросам, открытым в режиме таблицы. Выберите Добавить (пользователи смогут добавлять новые записи, но не изменять существующие), Изменить (пользователи смогут изменять существующие записи, а также добавлять новые) или Только для чтения (пользователи смогут только просматривать записи). По умолчанию используется значение Изменить .

Примечания

Если для аргумента Вид задано значение Таблица , Access отображает результирующий набор, если используется запрос на выборку, перекрестный запрос, запрос на объединение или запрос к серверу, свойство ReturnsRecords которого имеет значение Да . Если это запрос на изменение, запрос определения данных или запрос к серверу, для свойства ReturnsRecords которого задано значение Нет , запрос выполняется.

Макрокоманда ОткрытьЗапрос аналогична двойному щелчку запроса в области навигации или его щелчку правой кнопкой мыши в области навигации и выбору представления. При использовании макрокоманды можно выбрать дополнительные параметры.

Советы

    Вы можете перетащить запрос из области навигации в окно конструктора макросов. При этом будет автоматически создана макрокоманда ОткрытьЗапрос , которая открывает запрос в режиме таблицы.

    Если переключиться в Конструктор, когда открыт запрос, значение аргумента Режим данных удаляется. Этот параметр не будет действовать, даже если пользователь вернется в режим таблицы.

    Если вы не хотите отображать системные сообщения, которые обычно появляются при выполнении запросов на изменение (в них говорится о том, что это запрос на изменение, и указано количество записей, на которые он влияет), вы можете отключить их с помощью макрокоманды ЗадатьПредупреждение .

Чтобы выполнить макрокоманду ОткрытьЗапрос в модуле Visual Basic для приложений (VBA), используйте метод ОткрытьЗапрос объекта DoCmd .

Эй, я только что-то узнали, как поместить мои заявления SQL в VBA (или по крайней мере их выписывать), но я не знаю, как получить возвращенные данные?

У меня есть несколько форм (диаграмма формы), основанные на запросах, которые я запускать довольно регулярные параметры против, просто изменяя временные рамки (например, топ-10 продаж за месяц своего рода вещи). Тогда у меня есть процедуры, которые автоматически передают объект диаграммы в презентации PowerPoint. Так что я все эти запросы предварительно построены (например, 63), и диаграмма формы, чтобы соответствовать (ну да.... 63... я знаю, что это плохо), а затем все эти вещи созданы на «открыто/закрыть»событие, приводящее к следующему (его, как моей самой лучшей попытка быть хаком.... или домино; в зависимости от того вы предпочитаете).

Так что я пытался узнать, как использовать операторы SQL в VBA, так что в конце концов, я могу сделать все это там (я, возможно, нужно сохранить все эти диаграммы формы, но я не знаю, потому что я, очевидно, не хватает понимания).

Так в стороне от вопроса, что я спросил наверху, кто может дать совет? Спасибо

6 ответов

10

Это немного устаревшей, так что вы можете захотеть, чтобы захватить книга на эту тему . Но, вот тонна доступ к ресурсам и немного учебники и примеры также. Но, в принципе...

Dim dbs As Database Dim rs As Recordset Dim strSQL As String Set dbs = CurrentDb strSQL = "your query here Set rs = dbs.OpenRecordset(strSQL) If Not (rs.EOF And rs.BOF) Then rs.MoveFirst "get results using rs.Fields() Else "Use results

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

Rs.MoveFirst Do While Not rs.EOF "do something like rs("SomeFieldName") rs.MoveNext Loop

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

Использование параметризованных QueryDef и вызывать его из VBA.
Запрос проще проектировать... легко testable..and легко доступны с помощью VBA или формы.

Dim qd as querydef set qd = currentdb.querydefs!myquerydef qd.parameters!parm1=val1

или qd.execute

Dim rs as recordset set rs = qd.openrecordset()

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

Так что константный или построить строку для вашего SQL заявление, и поп-музыки в вашем продезинфицировать, NON SQL ИНЖЕКЦИЕЙ строку в качестве аргумента:)

StrSQL = "SELECT * FROM Customer WHERE ID = " & EnsureParamIsNotSQLInjection(customerID)

Затем вызвать функцию/к югу от где вам нужно, чтобы получить данные/набор записей/выполнить инструкцию. Создав несколько доступа к данным функциям/подлодки, где вы можете просто запустить оператор UPDATE или извлекаемую одно значение, или извлечь полномасштабные записи.

Ключевым моментом здесь является, чтобы эти функции все живущие в одном месте и использовать их повсюду. Вот пример в VBScript.

Sub DoStuff(strSQL) Set adoCon = Server.CreateObject("ADODB.Connection") strConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("db\Database.mdb") "strConnString = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("db\Database.mdb") adoCon.Open strConnString Set rsMain = Server.CreateObject("ADODB.Recordset") rsMain.Open strSQL, adoCon Do While NOT rsMain.EOF customerName = rsMain("CustomerName") "silly example RsMain.MoveNext Loop rsMain.Close Set adoCon = Nothing End Sub

Другой способ сделать это, что, кажется, никто не упомянул, чтобы связать ваш график с одной сохраненной QueryDef, а затем во время выполнения, перепишем QueryDef. Теперь, я не рекомендую изменять сохраненные QueryDefs для большинства контекстов, поскольку она вызывает фронтального раздувание и, как правило, даже не нужно (в большинстве контекстов, где вы используете сохраненный QueryDef могут быть отфильтрованы в той или иной, в том контексте, в котором они используются, например, в качестве одной из форм RecordSource, вы просто передать один аргумент в DoCmd.OpenForm).

Графики разные, так как SQL вождения графики не могут быть изменены во время выполнения.

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

PARAMETERS !! Long;

Если вы используете ссылки формы, это важно, что вы делаете это, потому что с Access 2002 на, то Jet Expression Service не всегда корректно обрабатывает их, когда элементы управления Null. Определение их в качестве параметров выпрямляет эту проблему (которая не присутствовала перед тем Access XP).

Одна из ситуаций, в которых вы должны переписать QueryDef для графа, если вы хотите, чтобы позволить пользователю выбрать N в заявлении TOP N SQL. Другими словами, если вы хотите, чтобы иметь возможность выбрать ТОП 5 или ТОП 10 или ТОП 20, вам придется изменить сохраненный QueryDef, так как N не может быть параметризованы.

Аксесс позволяет создавать программно строки SQL-запросов, а также строки, служащие значениями свойств форм, отчетов и т.д., параметров функций и т.д., которые тоже должны соответствовать синтаксису SQL. При этом надо помнить, что входящие в такую строку константы должны быть тоже оформлены по правилам SQL, а именно:

  • в числах десятичным разделителем должна быть точка,
  • строки должны быть заключены в кавычки или апострофы (а кавычки или апострофы соответственно внутри строки удвоены),
  • даты должны быть заключены в решетки и написаны по американскому формату (mm/dd/yyyy) с дробной чертой в качестве разделителя.

    Если это нарушить, то возможны следующие эффекты:

  • число вида 10,5 с запятой вместо точки будет воспринято как список из двух чисел 10 и 5, что приведет к какому-нибудь несоответствию в количестве полей,
  • строка вида Vasya без кавычек и апострофов будет воспринята как имя поля, если такое поле есть, или как имя параметра, который тут же будет запрошен,
  • дата вида 1/2/2010 или 1-2-2010 без решеток будет воспринята как арифметическое выражение (с делением и вычитанием соответственно),
  • дата вида 1.2.2010 будет воспринята как дробное число с двумя десятичными точками и приведет к ошибке,
  • дата с решетками, но не по американскому формату будет воспринята как дата, но другая (день и месяц будут переставлены).

    Ниже в каждом разделе приведен пример строки SQL, которая должна получиться при ее программном создании, а затем код VBA, который ее создает. Еще ниже дана очень полезная рекомендация.

    1. Использование чисел

    SELECT * FROM Table WHERE (((Table .Quanty)=12 .197 ));
    VBA v1

    Dim q As Single q = 12 .197 strSQL = "SELECT * " _ & "FROM Table " _ & "WHERE (((Table.Quanty)=" & q & "));"
    VBA v2

    Dim q As String q = "12,197" strSQL = "SELECT * " _ & "FROM Table " _ & "WHERE (((Table.Quanty)=" & Str (q) & "));"
    Примечание:

  • VBA v1 - для целых чисел. Для дробных чисел это частный случай, только когда системным разделителем является точка.
  • VBA v2 - более правильный вариант, т.к. в классическом программировании допускается соединять только строки со строками, тогда как VBA v1 использует неявное преобразование типов, хотя нареканий на этот способ для целых чисел не было. (Пример приведён для случая, когда системным разделителем является запятая.)
  • Иногда также используют для преобразования функцию CStr(), но она не всегда применима, т.к. возвращает число в виде строки, где оно записывается через системный разделитель, тогда как SQL в качестве разделителя воспринимает только точку.
  • NB! При использовании нетипичных системных разделителей вышеприведённые примеры могут не работать, в этих случаях надо программно заменять системный разделитель на точку. Ниже приводится функция, возвращающая системный разделитель.
    Function GetDecimalSeparator() As String GetDecimalSeparator = Format (0 #, "." ) End Function Также следует учесть, что в этом случае некоторые стандартные действия Access могут не работать.

    2. Использование строк

    SELECT * FROM Table WHERE (((Table .Name)="All" ));
    VBA v1

    Dim q As String q = "All" strSQL = "SELECT * " _ & "FROM Table " _ & "WHERE (((Table.Quanty)=" "" & DoubleQuote(q) & "" "));"
    VBA v2

    Dim q As String q = "All" strSQL = "SELECT * " _ & "FROM Table " _ & "WHERE (((Table.Quanty)="" & DoubleApostrophe(q) & "" ));"
    Примечание:

  • VBA v1 : DoubleQuote() - функция, удваивающая кавычки .

    Пример:
    условие выборки:
    a"a"s SQL:
    WHERE field="a""a"s " VBA:
    strWhere = "WHERE field="" " & "a""""a"s " & """ "

  • VBA v2: : DoubleApostrophe() - функция, удваивающая апострофы .

    Пример:
    условие выборки:
    a"a"s SQL:
    WHERE field="a"a""s " VBA:
    strWhere = "WHERE field=" " & "a""a""s " & "" "

  • Упомянутые выше функции DoubleQuote и DoubleApostrophe - это НЕ встроенные функции Аксесса, а пользовательские функции, реализация которых оставляется на усмотрение программиста. В частности, в Аксессе версий 2000 и выше можно для этой цели использовать встроенную функцию Replace, а в 97 и ниже - вот такую функцию:

    Public Function Replace97(StrMain As String , StrFind As String , StrZam As String ) As String On Error GoTo err Dim pos As Long If StrFind = "" Then GoTo err If StrMain = "" Then Replace97 = StrZam: Exit Function Do Until InStr(1 , StrMain, StrFind) = 0 pos = InStr(1 , StrMain, StrFind) StrMain = mid (StrMain, 1 , pos - 1 ) & StrZam & mid (StrMain, pos + Len(StrFind), Len(StrMain)) Loop Replace97 = StrMain Exit Function err: Replace97 = StrMain End Function
    3. Использование дат

    SELECT * FROM Table WHERE (((Table .TimeOpen)=#3 /31 /2003 11 :17 :19 #));
    VBA

    Dim q As Date q = Now strSQL = "SELECT * " _ & "FROM Table " _ & "WHERE (((Table.TimeOpen)=#" & Format (q, "mm\/dd\/yy hh\:mm\:ss" ) & "#));"
    Примечание:

  • Microsoft JET SQL оперирует датами в американском формате, т.е. именно в вышеуказанном виде Месяц/День/Год.
  • Не пропустите символы # (он обрамляет всю константу типа дата-время) и \ (он предохраняет / и : от их замены в соответствии с региональными настройками, что имеет обыкновение делать функция Format и что мешает правильной работе команды SQL).
  • Рекомендуется почитать здесь: о способах хранения даты/времени.
  • NB! Не стоит пользоваться преобразованием даты в Integer (или Long), т.к. в Access"е и в SQL Server"е одной и той же дате соответствуют разные числа и при сравнении можно получить неожиданный результат.

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

  • Данный урок посвящен SQL запросам к базе данных на VBA Access . Мы рассмотрим, как на VBA осуществляется запросы INSERT, UPDATE, DELETE к базе данных, а также научимся получать конкретное значение из запроса SELECT.

    Те, кто программируют на VBA Access и работая при этом с базой данных SQL сервера, очень часто сталкиваются с такой простой и нужной задачей как посыл SQL запроса к базе данных, будь то INSERT, UPDATE или простой SQL запрос SELECT . А так как мы начинающие программисты мы тоже должны уметь это делать, поэтому сегодня займемся именно этим.

    Мы уже затрагивали тему получения данных с SQL сервера, где как раз на VBA писали код для получения этих данных, например в статье про Выгрузку данных в текстовый файл из MSSql 2008 или также немного затрагивали в материале Выгрузка данных из Access в шаблон Word и Excel , но так или иначе там мы рассматривали это поверхностно, а сегодня предлагаю поговорить об этом чуть более подробней.

    Примечание! Все примеры ниже рассмотрены с использованием ADP проекта Access 2003 и базы данных MSSql 2008. Если Вы не знаете что вообще такое ADP проект то это мы рассматривали в материале Как создать и настроить ADP проект Access

    Исходные данные для примеров

    Допустим, у нас есть таблица test_table, которая будет содержать номера и названия месяцев в году (запросы выполнены с использованием Management Studio )

    CREATE TABLE .( NOT NULL, (50) NULL) ON GO

    Как я уже сказал, мы будем использовать ADP проект, настроенный на работу с MS SQL 2008, в котором я создал тестовую форму и добавил кнопку start с подписью «Выполнить» , которая нам понадобится для тестирования нашего кода, т.е. весь код мы будем писать в обработчике события «Нажатие кнопки ».

    Запросы к базе INSERT, UPDATE, DELETE на VBA

    Чтобы долго не тянуть сразу приступим, допустим, нам нужно добавить строку в нашу тестовую таблицу (код прокомментирован )/

    Private Sub start_Click() "Объявляем переменную для хранения строки запроса Dim sql_query As String "Записываем в нее нужный нам запрос sql_query = "INSERT INTO test_table (id, name_mon) VALUES ("6", "Июнь")" "Выполняем его DoCmd.RunSQL sql_query End Sub

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

    Как видим, данные вставились.

    Для того чтобы удалить одну строку пишем вот такой код.

    Private Sub start_Click() "Объявляем переменную для хранения строки запроса Dim sql_query As String "Записываем в нее запрос на удаление sql_query = "DELETE test_table WHERE id = 6" "Выполняем его DoCmd.RunSQL sql_query End Sub

    Если мы проверим, то увидим, что нужная строка удалилась.

    Для обновления данных записываем в переменную sql_query запрос update, надеюсь, смысл понятен.

    Запрос SELECT к базе на VBA

    Здесь дела обстоят чуть интересней, чем с остальными конструкциями SQL.

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

    Private Sub start_Click() "Объявляем переменные "Для набора записей из базы Dim RS As ADODB.Recordset "Строка запроса Dim sql_query As String "Строка для вывода итоговых данных в сообщении Dim str As String "Создаем новый объект для записей set RS = New ADODB.Recordset "Строка запроса sql_query = "SELECT id, name_mon FROM test_table" "Выполняем запрос с использованием текущих настроек подключения проекта RS.open sql_query, CurrentProject.Connection, adOpenDynamic, adLockOptimistic "Циклом перебираем записи While Not (RS.EOF) "Заполняем переменную для вывода сообщения str = str & RS.Fields("id") & "-" & RS.Fields("name_mon") & vbnewline "переход к следующей записи RS.MoveNext Wend "Вывод сообщения msgbox str End Sub

    Здесь мы уже используем циклы VBA Access для того чтобы перебрать все значения в нашем наборе записей.

    Но, достаточно часто бывает необходимо получить не все значения из набора записей, а всего лишь одно, например, название месяца по его коду. И для этого использовать цикл как-то накладно, поэтому мы можем просто написать запрос, который вернет всего одно значение и обращаться именно к нему, например, получим название месяца по коду 5

    Private Sub start_Click() "Объявляем переменные "Для набора записей из базы Dim RS As ADODB.Recordset "Строка запроса Dim sql_query As String "Строка для вывода итогового значения Dim str As String "Создаем новый объект для записей set RS = New ADODB.Recordset "Строка запроса sql_query = "SELECT name_mon FROM test_table WHERE id = 5" "Выполняем запрос с использованием текущих настроек подключения проекта RS.open sql_query, CurrentProject.Connection, adOpenDynamic, adLockOptimistic "Получаем наше значение str = RS.Fields(0) msgbox str End Sub

    Для универсальности здесь мы уже обратились не по имени ячейки, а по ее индексу, т.е. 0, а это самое первое значение в Recordset , в итоге мы получили значение «Май» .

    Как видите, все достаточно просто. Если Вам достаточно часто требуется получать конкретное значение из базы (как в последнем примере ), то рекомендую вывести весь код в отдельную функцию (Как написать функцию на VBA Access 2003) с одним входящим параметром, например, код месяца (если рассматривать наш пример ) и просто, где необходимо вывести это значение, вызывать нужную нам функцию с нужным параметром и все, этим мы значительно уменьшим код VBA и улучшим восприятие нашей программы.

    На сегодня это все. Удачи!