Почему этот SQL-запрос работает в конструкторе запросов, а не в VBA для Access? - PullRequest
0 голосов
/ 16 января 2019

Когда я выполняю следующие два запроса в Create> Query один за другим, они работают отлично. Когда я пытаюсь выполнить запросы в VBA, работает только первый (invoiceline).

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

При нажатии кнопки этот запрос выполняется правильно

buttonOne_Click ()

Const adOpenStatic = 3
Const adLockOptimistic = 3


Dim oConnection
Dim oRecordset
Dim sMsg
Dim sConnectString
Dim sSQL
sConnectString = "DSN=Quickbooks Data;OLE DB Services=-2;"

sSQL = "INSERT INTO InvoiceLine (InvoiceLineItemRefListID, InvoiceLineDesc, InvoiceLineRate, InvoiceLineAmount, InvoiceLineSalesTaxCodeRefListID, FQSaveToCache) VALUES ('80002436-1519061496', 'Building permit 1', 1.00000, 1.00, '80000001-1478562826', 1)"

Set oConnection = CreateObject("ADODB.Connection")
Set oRecordset = CreateObject("ADODB.Recordset")
oConnection.Open sConnectString
oConnection.Execute (sSQL)
sMsg = sMsg & "Invoice details were gathered!"
MsgBox sMsg

End Sub

Этот сбой с ошибкой

buttonTwo_Click ()

Const adOpenStatic = 3
Const adLockOptimistic = 3


Dim oConnection
Dim oRecordset
Dim sMsg
Dim sConnectString
Dim sSQL




sConnectString = "DSN=Quickbooks Data;OLE DB Services=-2;"

sSQL = "INSERT INTO Invoice (CustomerRefListID, ARAccountRefListID, TxnDate, RefNumber, BillAddressAddr1, BillAddressAddr2, BillAddressCity, BillAddressState, BillAddressPostalCode, BillAddressCountry, IsPending, TermsRefListID, DueDate, ShipDate, ItemSalesTaxRefListID, Memo, IsToBePrinted, CustomerSalesTaxCodeRefListID) VALUES ('800001F6-1482536280', '8000001E-1478562986', #9/23/2020#, '1', 'Brad Lamb', '1921 Appleseed Lane', 'Bayshore', 'CA', '94326', 'USA', 0, '80000002-1478562832', #10/31/2020#, #10/01/2020#, '8000295C-1541711590', 'Memo Test', 0, '80000001-1478562826')"


Set oConnection = CreateObject("ADODB.Connection")
Set oRecordset = CreateObject("ADODB.Recordset")
oConnection.Open sConnectString
oConnection.Execute (sSQL)
sMsg = sMsg & "Invoice was Sent to QuickBooks"
MsgBox sMsg

End Sub

Второй полагается на завершение первого, еще раз оба запроса отлично работают в конструкторе запросов в Microsoft Access, но второй сбой при запуске в VBA SQL в макросе или процедуре.

Это ошибка, которую я вижу:

Ошибка времени выполнения '-2147217900 (80040e14)':

[QODBC] [синтаксическая ошибка sql] Ожидаемый лексический элемент не найден: =)

UPDATE

Я пробовал все это без удачи, есть другие предложения?

01.10.2005

2005-01-10

01/10/2005

2005/01/10

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Как прокомментировал и опубликовал @Minty, ваши даты являются проблемой

  • При выполнении запросов в графическом интерфейсе MS Access, например, с помощью Query Designer, вы получаете доступ к диалекту Access SQL.
  • При подключении через ODBC-драйвер к внешней базе данных вы подчиняетесь диалекту SQL подключаемой базы данных, в данном случае Quickbooks.

Нет двух одинаковых диалектов SQL, но большинство пытается соответствовать стандартам ANSI. Следовательно, одни и те же запросы могут завершаться ошибкой между Query Designer и VBA.

MS Access

Даты доступа MS, если они отправлены буквально, должны быть заключены в хэштеги, #:

INSERT INTO Invoice (CustomerRefListID, ARAccountRefListID, TxnDate, RefNumber,
                     BillAddressAddr1, BillAddressAddr2, BillAddressCity, BillAddressState, 
                     BillAddressPostalCode, BillAddressCountry, IsPending, TermsRefListID, 
                     DueDate, ShipDate, ItemSalesTaxRefListID, [Memo], IsToBePrinted, 
                     CustomerSalesTaxCodeRefListID) 
VALUES ('800001F6-1482536280', '8000001E-1478562986', #9/23/2020#, '1', 'Brad Lamb', 
        '1921 Appleseed Lane', 'Bayshore', 'CA', '94326', 'USA', 0, '80000002-1478562832', 
         #10/31/2020#, #10/01/2020#, '8000295C-1541711590', 
         'Memo Test', 0, '80000001-1478562826')

В качестве альтернативы используйте CDate() для преобразования строки в дату:

INSERT INTO Invoice (CustomerRefListID, ARAccountRefListID, TxnDate, RefNumber,
                     BillAddressAddr1, BillAddressAddr2, BillAddressCity, BillAddressState, 
                     BillAddressPostalCode, BillAddressCountry, IsPending, TermsRefListID, 
                     DueDate, ShipDate, ItemSalesTaxRefListID, [Memo], IsToBePrinted, 
                     CustomerSalesTaxCodeRefListID) 
VALUES ('800001F6-1482536280', '8000001E-1478562986', CDate('9/23/2020'), '1', 'Brad Lamb', 
        '1921 Appleseed Lane', 'Bayshore', 'CA', '94326', 'USA', 0, '80000002-1478562832', 
        CDate('10/31/2020'), CDate('10/01/2020'), '8000295C-1541711590', 
        'Memo Test', 0, '80000001-1478562826')

Quickbooks ODBC

В Quickbooks вы должны придерживаться требования даты {d 'YYYY-MM-DD'} или функциональной формы fncqbDate(). Однако документация по этим методам редко встречается и может варьироваться в зависимости от версии драйвера ODBC.

sql = "INSERT INTO Invoice (CustomerRefListID, ARAccountRefListID, TxnDate, RefNumber, " _
       & "                  BillAddressAddr1, BillAddressAddr2, BillAddressCity,  " _
       & "                  BillAddressState, BillAddressPostalCode, BillAddressCountry,  " _
       & "                  IsPending, TermsRefListID, DueDate, ShipDate,  " _
       & "                  ItemSalesTaxRefListID, [Memo], IsToBePrinted,  " _
       & "                  CustomerSalesTaxCodeRefListID)  " _
       & " VALUES ('800001F6-1482536280', '8000001E-1478562986', {d '2020-09-23'}, '1',  " _
       & "         'Brad Lamb', '1921 Appleseed Lane', 'Bayshore', 'CA', '94326', 'USA', 0,  " _ 
       & "         '80000002-1478562832', {d '2020-10-31'}, {d '2020-10-01'},  " _
       & "         '8000295C-1541711590', 'Memo Test', 0, '80000001-1478562826')"

Параметрирование

С учетом вышесказанного, даже если вышеприведенное не работает, это еще одна веская причина для параметризации, отраслевой стандарт программирования для любого прикладного уровня, такого как VBA, для запуска SQL. Параметризация облегчает сопоставление типов данных между клиентом и сервером без необходимости заключать в кавычки или другие символические замыкания. ADO поддерживает параметры с помощью метода CreateParameter внутри объекта Command ADO (не для набора записей ADO).

' PREPARED STATEMENT WITH PLACEHOLDERS (NO LITERAL DATA)
sql = "INSERT INTO Invoice (CustomerRefListID, ARAccountRefListID, TxnDate, RefNumber, " _
       & "                  BillAddressAddr1, BillAddressAddr2, BillAddressCity,  " _
       & "                  BillAddressState, BillAddressPostalCode, BillAddressCountry,  " _
       & "                  IsPending, TermsRefListID, DueDate, ShipDate,  " _
       & "                  ItemSalesTaxRefListID, [Memo], IsToBePrinted,  " _
       & "                  CustomerSalesTaxCodeRefListID)  " _
       & " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?," _ 
       & "         ?, ?, ?, ?, ?, ?, ?, ?, ?)"

' OPEN CONNECTION
Set oConnection = CreateObject("ADODB.Connection")   
oConnection.Open sConnectString

' INITIALIZE AND RUN COMMAND
Set oCmd = CreateObject("ADODB.Command")              ' NEW ADO OBJECT
With oCmd
   .ActiveConnection = oConnection
   .CommandText = sql
   .CommandType = adCmdText

   ' BIND PARAMETERS
   .Parameters.Append .CreateParameter("pm1", adVarChar, adParamInput, ,"800001F6-1482536280")
   .Parameters.Append .CreateParameter("pm2", adVarChar, adParamInput, ,"8000001E-1478562986") 
   .Parameters.Append .CreateParameter("pm3", adDate, adParamInput, , CDate("9/23/2020"), 
   .Parameters.Append .CreateParameter("pm4", adVarChar, adParamInput, ,"1") 
   .Parameters.Append .CreateParameter("pm5", adVarChar, adParamInput, ,"Brad Lamb")
   .Parameters.Append .CreateParameter("pm6", adVarChar, adParamInput, ,"1921 Appleseed Lane")
   .Parameters.Append .CreateParameter("pm7", adVarChar, adParamInput, ,"Bayshore")
   .Parameters.Append .CreateParameter("pm8", adVarChar, adParamInput, ,"CA")
   .Parameters.Append .CreateParameter("pm9", adVarChar, adParamInput, ,"94326")
   .Parameters.Append .CreateParameter("pm10", adVarChar, adParamInput, ,"USA")
   .Parameters.Append .CreateParameter("pm11", adInteger, adParamInput, , 0)
   .Parameters.Append .CreateParameter("pm12", adVarChar, adParamInput, ,"80000002-1478562832")
   .Parameters.Append .CreateParameter("pm13", adDate, adParamInput, , CDate("10/31/2020"))
   .Parameters.Append .CreateParameter("pm14", adDate, adParamInput, , CDate("10/01/2020")) 
   .Parameters.Append .CreateParameter("pm15", adVarChar, adParamInput, ,"8000295C-1541711590")
   .Parameters.Append .CreateParameter("pm16", adVarChar, adParamInput, ,"Memo Test")
   .Parameters.Append .CreateParameter("pm17", adInteger, adParamInput, ,0)
   .Parameters.Append .CreateParameter("pm18", adVarChar, adParamInput, ,"80000001-1478562826")

   ' RUN PARAMETERIZED QUERY
   .Execute
End With

oConnection.Close
Set oCmd = Nothing: Set oConnection = Nothing
0 голосов
/ 17 января 2019

Если это приложение Access, я бы рекомендовал вместо того, чтобы переписывать запрос в код sql / vba, вместо этого использовать другой подход: оставить рабочий запрос в качестве объекта запроса и вместо этого использовать vba для его запуска:

DoCmd.OpenQuery "QueryName"

Это имеет преимущество в том, что этот объект запроса существует в области навигации, так что вы можете запускать его вручную для тестирования - без необходимости запуска какого-либо vba. Это гораздо более простая стратегия отладки.

0 голосов
/ 16 января 2019

Прочитайте здесь https://support.flexquarters.com/esupport/index.php?/Knowledgebase/Article/View/2638/44/qodbc-desktop-troubleshooting---how-to-use-date-and-dateadd-function-in-qodbc

Правильный формат: {d 'ГГГГ-ММ-ДД'} Существует функция, позволяющая сделать дату правильной строкой;

Функция:

Function fncqbDate(myDate As Date) As String
myDate = Nz(myDate, Now)
fncqbDate = "{d '" & Year(myDate) & "-" & Right("00" & Month(myDate), 2) & "-" & Right("00" & Day(myDate), 2) & "'}"
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...