Вставить в Redshift с Excel VBA - PullRequest
1 голос
/ 13 апреля 2020

У меня есть требование для загрузки данных из Excel в Redshift. Я получаю ошибки, потому что есть числовые столбцы c, и преобразование значений в каждой ячейке строки в массив становится строкой. Это нормально, за исключением числовых c столбцов, которым нужен ноль, а не ''.

Вот код.

Private Sub CommandButton1_Click()
Dim BCS As Worksheet

Set BCS = ThisWorkbook.Sheets(Sheet3.Name)
Sheetcolumns = "(fbn,region,site,finance_manager,phase_type,number_of_stories,phase_count,scenario_design_type," & _
               "op_build_schedule_handoff,weeks_until_handoff,standard_tke,car_total,qty_subcategory,value_subcategory," & _
               "po_qty,po_unit_cost,po_total,invoice_qty,invoice_unit_cost,invoice_total,percent_diff_invoice_v_po," & _
               "manual_qty_est,manual_unit_cost_est,manual_adj_est,manual_est_total,est_choice,final_est_qty,final_unit_cost_est," & _
               "final_adj_est,final_est_total,forecast_reduction_choice,forecast_reduction_percent,final_forecast," & _
               "po_v_manual_percent_diff,inv_v_manual_percent_diff,notes,snapshot_date)"
Set con = New ADODB.Connection

#If Mac Then
    'if Mac then use this driver
    CS = "Driver={Amazon Redshift};SERVER={<Redshift>};UID=<user>;PASSWORD=<ped>;DATABASE=<db>;PORT=8192"
#ElseIf Win64 Then
    CS64 = "Driver={Amazon Redshift (x64)};SERVER={<Redshift>};UID=<user>;PASSWORD=<password>;DATABASE=awscfpa;PORT=8192"
    con.Open CS64
#Else
    CS32 = "Driver={Amazon Redshift (x86)};SERVER={<Redshift>};UID=<user>;PASSWORD=<ped>;DATABASE=awscfpa;PORT=8192"
    con.Open CS32
#End If

For r = 2 To BCS.ListObjects(1).DataBodyRange.Rows.Count
    valuesArray = BCS.Range("A" & r & ":AJ" & r).Value
    insertValues = Join2D(valuesArray, "','")

    Sql = "INSERT INTO dcgs.bcs_output " & Sheetcolumns & "VALUES(" & "'" & insertValues & "'" & ",CURRENT_DATE)"
    con.Execute Sql
Next r

con.Close
Set con = Nothing



End Sub
Public Function Join2D(ByVal vArray As Variant, Optional ByVal sWordDelim As String = " ", Optional ByVal sLineDelim As String = vbNewLine) As String

    Dim i As Long, j As Long
    Dim aReturn() As String
    Dim aLine() As String

    ReDim aReturn(LBound(vArray, 1) To UBound(vArray, 1))
    ReDim aLine(LBound(vArray, 2) To UBound(vArray, 2))

    For i = LBound(vArray, 1) To UBound(vArray, 1)
        For j = LBound(vArray, 2) To UBound(vArray, 2)
            'Put the current line into a 1d array
            aLine(j) = vArray(i, j)
        Next j
        'Join the current line into a 1d array
        aReturn(i) = Join(aLine, sWordDelim)
    Next i

    Join2D = Join(aReturn, sLineDelim)

End Function

Join2D - это то, что я получил из предыдущего запроса , но в этом случае все было строкой. Есть ли способ изменить это, чтобы дать вывод, где, если элемент insertValues ​​'', он меняет его на Null? Я попытался для l oop с оператором if, чтобы попытаться изменить любой элемент с '' на Null, и он дал несоответствие типов.

Я также открыт для других способов передачи данных в Redshift которые не требуют вставки построчно, если это проще.

1 Ответ

0 голосов
/ 13 апреля 2020

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

Предполагая, что API вашей базы данных Excel является ADO, рассмотрите объект Command для параметризации. Это требует от вас .CreateParameter() вызовов для всех 36 полей (столбцы A-AJ) и явного определения типов данных. Пустые ячейки могут переводиться как NULL сущностей для вставки.

' PREPARED STATEMENT (NO DATA) WITH 36 PARAM PLACEDHOLERS
sql = "INSERT INTO dcgs.bcs_output (Col1, Col2, Col3, ..., Col37) " _
          & " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?,                   " _ 
          & "        ?, ?, ?, ?, ?, ?, ?, ?, ?,                   " _
          & "        ?, ?, ?, ?, ?, ?, ?, ?, ?,                   " _
          & "        ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_DATE)     "             

For r = 2 To BCS.ListObjects(1).DataBodyRange.Rows.Count
    ' CONFIGURE ADO COMMAND
    Set cmd = New ADODB.Command

    With cmd
        .ActiveConnection = conn
        .CommandText = sql
        .CommandType = adCmdText

        ' BIND ALL 36 PARAM VALUES
        .Parameters.Append .CreateParameter("param1", adInt, adParamInput, , BCS.Range("A" & r).Value)
        .Parameters.Append .CreateParameter("param2", adVarchar, adParamInput, , BCS.Range("B" & r).Value)
        ' ...
        .Parameters.Append .CreateParameter("param36", adXXXX, adParamInput, , BCS.Range("AJ" & r).Value)

        ' EXECUTE ACTION
        .Execute
    End With

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