Выберите длинный текст из SQL с помощью Excel VBA. ADO возвращает символы мусора [дубликаты]

Я не могу понять, как получить длинный текст (> 8 КБ) из поля SQL Server, используя соединение ADODB через Excel VBA. Мой метод возвращает строку мусора.

Я могу успешно загрузить поле с длиной данных> 8 КБ, используя параметризованный запрос, как в следующем коде:

Public Sub TestLongParamUploadQuery()
    Dim conn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim param As ADODB.Parameter
    Dim rs As ADODB.Recordset

    Query = "INSERT INTO MYTABLE ([Long_Text], [Table_Index]) VALUES (?, ?);"
    Set conn = New ADODB.Connection
    conn.ConnectionString = connStr
    On Error GoTo connerror
    conn.Open
    Set cmd = New ADODB.Command
    With cmd
        .ActiveConnection = conn
        .CommandText = Query
        .CommandType = adCmdText
        Set Pm = .CreateParameter("long_text", adLongVarWChar, adParamInput, 20000)
        Pm.Value = Replace("THIS IS A REALLY LONG TEXT STRING " & Space(8000) & "THIS IS A REALLY LONG TEXT STRING", " ", ".")
        .Parameters.Append Pm

        Set Pm = .CreateParameter("table_index", adVarChar, adParamInput, 32)
        Pm.Value = "MYFAKERECORD"
        .Parameters.Append Pm
        Set rs = .Execute
    End With
connerror:
    If Err.Number <> 0 Then
        Msg = "Error # " & str(Err.Number) & " was generated by " _
        & Err.Source & Chr(13) & "Error Line: " & Erl & Chr(13) & Err.Description
        MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
    End If
    conn.Close
End Sub

Но когда я пытаюсь получить данные с помощью оператора SELECT, данные возвращаются искаженными.

Public Sub TestLongParamDownloadQuery()
    Dim conn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim param As ADODB.Parameter
    Dim rs As ADODB.Recordset
    Query = "SELECT * FROM MYTABLE WHERE Table_Index='MYFAKERECORD';"
    Set conn = New ADODB.Connection
    conn.ConnectionString = connStr
    On Error GoTo connerror
    conn.Open
    Set cmd = New ADODB.Command
    With cmd
        .ActiveConnection = conn
        .CommandText = Query
        .CommandType = adCmdText
    End With

    Set rs = cmd.Execute()

    Do Until rs.EOF = True
        For i = 0 To rs.Fields.Count - 1
            If Not IsNull(rs.Fields.Item(i)) Then
                Debug.Print ("field '" & rs.Fields(i).Name & "' length: " & Len(rs.Fields.Item(i)) & "; value: '" & rs.Fields.Item(i) & "'")
            End If
        Next
        rs.MoveNext
    Loop

connerror:
    If Err.Number <> 0 Then
        Msg = "Error # " & str(Err.Number) & " was generated by " _
        & Err.Source & Chr(13) & "Error Line: " & Erl & Chr(13) & Err.Description
        MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
    End If
    conn.Close
End Sub

Данные успешно попадают в базу данных. Я могу открыть и увидеть его в SQL Server Management Studio.

Тем не мение. Вывод Debug.Print из моей загрузки выглядит следующим образом

field 'Long_Text' length: 8067; value: '                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  MYFAKERECORD                                                                                                                             ?                  ?%0??       ?%0??       ?                  ?                  ?                  ?                  ?                                                                                                                                                                            






                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     '
field 'Table_Index' length: 12; value: 'MYFAKERECORD'

Обратите внимание, что длина кажется правильной. Это не просто проблема печати в непосредственном окне Excel VBA IDE. Когда я пишу данные в ячейку Excel с помощью макроса, ячейка содержит «``» после загрузки.

Я пробовал загружать с параметром для Unicode adLongVarWChar и открытым текстом adLongVarChar. Оба, кажется, правильно помещают данные в базу данных. Оба возвращаются как неработающий текст из инструкции select.

Как правильно загружать и запрашивать длинные тексты через adodb?

EDIT Я нашел этот поток, который отмечает фундаментальное ограничение, заключающееся в том, что ADO не может интерпретировать тип nvarchar(max). Предложенное решение преобразования переменной в nvarchar(20000) мне не подойдет, потому что верхний предел для CAST составляет 8000 символов. Как я могу перенести данные из поля БОЛЬШЕ 8 КБ в Excel VBA?


person deseosuho    schedule 15.06.2019    source источник
comment
Спасибо @GSerg! Это идеально. 2 часа гугления так и не наткнулся на эту тему. Спасибо.   -  person deseosuho    schedule 16.06.2019


Ответы (1)


Этот ответ был взят из сообщения Каковы ограничения для типов данных ADO?

Решение как есть:

  1. Введите нужные поля как text.
  2. Получить фактические данные из набора записей, используя string = rs.Fields(0).GetChunk(rs.Fields(0).ActualSize)

Включение в мой код выглядит так:

Public Sub TestLongParamDownloadQuery()
    Dim conn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim param As ADODB.Parameter
    Dim rs As ADODB.Recordset
    Query = "SELECT * FROM MYTABLE WHERE Table_Index='MYFAKERECORD';"
    Set conn = New ADODB.Connection
    conn.ConnectionString = connStr
    On Error GoTo connerror
    conn.Open
    Set cmd = New ADODB.Command
    With cmd
        .ActiveConnection = conn
        .CommandText = Query
        .CommandType = adCmdText
    End With

    Set rs = cmd.Execute()

    Do Until rs.EOF = True
        For i = 0 To rs.Fields.Count - 1
            If Not IsNull(rs.Fields.Item(i)) Then
                If rs.Fields.Item(i).Name = "Long_Text" Then
                    Debug.Print(rs.Fields(i).GetChunk(rs.Fields(i).ActualSize))
                End If
                Debug.Print ("field '" & rs.Fields(i).Name & "' length: " & Len(rs.Fields.Item(i)) & "; value: '" & rs.Fields.Item(i) & "'")
            End If
        Next
        rs.MoveNext
    Loop

connerror:
    If Err.Number <> 0 Then
        Msg = "Error # " & str(Err.Number) & " was generated by " _
        & Err.Source & Chr(13) & "Error Line: " & Erl & Chr(13) & Err.Description
        MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
    End If
    conn.Close
End Sub
person deseosuho    schedule 16.06.2019
comment
Кажется, вы не используете приведение в качестве текста в этом коде. - person GSerg; 16.06.2019