Как диагностировать синтаксическую ошибку из параметризованного запроса SQL Server в VBA ADODB - PullRequest
0 голосов
/ 05 января 2019

Я использую VBA adodb для записи INSERT операторов в SQL Server на основе содержимого строки Excel.

Я использую параметризованные запросы, поэтому мой код VBA имеет следующую форму:

sqlStatement = "INSERT INTO dbo.mytable (" & Join(insertElement(0), ", ") & ") VALUES (" & Join(insertElement(2), ", ") & ")"
Set cm = New ADODB.Command

With cm
      Debug.Print (sqlStatement)
            .ActiveConnection = conn
            .CommandText = sqlStatement
            .CommandType = adCmdText
             For Each e In insertElement(1)
                Set Pm = .CreateParameter(, adVarChar, 3, 1024, e)
                .Parameters.Append Pm
             Next e
             Set rs = .Execute
        End With

, где insertElement(0) - это массив имен полей, ... (1) - это массив значений, а ... (2) - массив заполнителей ? для поддержки параметризации

Когда я запускаю этот код, я получаю сообщение об ошибке

[Microsoft] [Драйвер ODBC 13 для SQL Server] [SQL Server] Неверный синтаксис рядом с «Выходными данными»

Однако, когда я запрашиваю текст sqlStatement, нигде в выражении нет «Вывода». Текст имеет вид:

INSERT INTO dbo.mytable ([my_field_1],[my_field_2],[somefieldshaveweirdcharslike+#], ...) VALUES (?, ?, ?, ...) 

Итак, если я не предоставляю команду «Вывод» напрямую и не могу непосредственно увидеть оператор, потому что он обрабатывается на стороне сервера, как я могу диагностировать синтаксис?

Ответы [ 2 ]

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

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

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

В моем случае основная проблема была связана с использованием типа параметра adodb adNumeric для десятичных значений. Я переключил тип параметра на adDecimal, а затем установил значения NumericScale и Precision для отдельных объектов параметров. Структура кода vba выглядит примерно так:

            For Each p In paramArr
                If p(1) = adVarChar Then
                    Set Pm = .CreateParameter(, p(1), 1, Len(p(2)), p(2))
                Else
                    Set Pm = .CreateParameter(, p(1), 1, , p(2))
                End If
                If p(1) = adDecimal Then
                    Pm.NumericScale = 3
                    Pm.Precision = 13
                End If
                .Parameters.Append Pm
            Next p
0 голосов
/ 06 января 2019

Вы должны иметь возможность просто построить оператор SQL, повторяя массив и конкатенируя значения любым удобным для вас способом, вместо того, чтобы пытаться вставить несколько параметров в группу вопросительных знаков. Примерно так (я предполагаю, что insertElement на самом деле является двумерным массивом, а не коллекцией; если это действительно коллекция, вам нужно сделать что-то похожее с For Each):

sqlStatement = "INSERT INTO dbo.mytable (" & Join(insertElement(0), ", ") & ") VALUES ("
Set cm = New ADODB.Command

With cm
    .ActiveConnection = conn
    .CommandType = adCmdText
    Dim aCount As Integer
    aCount = Ubound(insertElement(1))
    For i = 0 To aCount - 1
        sqlStatement = sqlStatement & "'" & insertElement(1,i) & "'" & _
        Iif(i <> aCount - 1, ",", "")
    Next
    .CommandText = sqlStatement
    Set rs = .Execute
End With

Все это говорит о том, что если вы хотите получить более глубокое понимание того, где происходит ваша ошибка, вы можете попробовать повторить объект *1007* Коллекция ошибок объекта. Поскольку попытка использовать соединение может привести к нескольким ошибкам, устранение неполадок может быть довольно сложным, просто используя объект Err.

Наконец, было бы лучше настроить оператор INSERT в хранимой процедуре на стороне сервера и таким образом передать значения в качестве параметров, если только у вас нет причин беспокоиться о внедрении атак.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...