【问题标题】:Passing Nulls from Excel to SQL将空值从 Excel 传递到 SQL
【发布时间】:2014-05-15 21:16:26
【问题描述】:

我正在使用 VBA 脚本来更新 SQL 中的表,到目前为止它运行良好。问题在于处理空值时。因为 VBA 脚本循环直到第一列结束,所以一些值在工作表中为空,但它们在 sql.xml 中被放置为零。

在 Excel 中:

    Name     Last name      Age    
    daniel   mtz            22
    jose     mtz            25
    John     doe    

SQL 中的最终结果:

    Name     Last name      Age    
    daniel   mtz            22
    jose     mtz            25
    John     doe            0

关于如何告诉宏或 SQL 将它们读取为 null 而不是零的任何想法?

P.S,在 sql 中对每一列进行编程以将 null 放在相应的值中不是一种选择,因为这个表会不断变化,我可以填充所有列,或者只是一些,等等。

[更新] 这是 VBA 的代码:

Sub Macro_CargarSQL()

'VARIABLES
Dim conn As New ADODB.Connection
Dim iRowNo As Integer
'Column variables
Dim sname, slastname, sage As String

'CONECTION TO SERVER Y BD
conn.Open "Provider=SQLOLEDB;Data Source=Termxgesvsql07\vfsitesamn;Initial Catalog=DW_PLCO;Integrated Security=SSPI;"
'Import into SQL
With Sheets("test")
    'Start row 2
    iRowNo = 2
    'Delete previous
    conn.Execute "delete from table"

    'Loop for insert
    Do Until .Cells(iRowNo, 1) = ""
        sname = .Cells(iRowNo, 1)
        slastname = .Cells(iRowNo, 2)
        sage = .Cells(iRowNo, 3)

        conn.Execute "insert into dbo.table (name, lastname,age ) values ('" & sname & "', '" & slastname & "', '" & sage & "')"
        iRowNo = iRowNo + 1
    Loop
End With
conn.Close
Set conn = Nothing

End Sub

【问题讨论】:

  • 如果你显示你的实际代码更容易回答。
  • .... 您用来填充数据库的 VBA 是什么?一种方法是参数,并且仅在值为非空时才包含参数。
  • @enderland,我在最后添加了 VBA 代码。谢谢!
  • @eflores,而不是告诉循环在单元格为空时终止,而是使用 VBA 查找最后一行。 A 是否始终存在?然后执行 lastRow = cells(rows.count,1).end(xlup).row ,并用 For iRowNo = 2 to lastRow 循环替换您的 Do 循环。或者,如果您不知道哪一列将包含最后一行,只需对所有列执行此操作并选择最高值。
  • 我不知道这是否是一个真正的连接字符串,但你应该从代码示例中删除它。

标签: sql vba excel null


【解决方案1】:

我这样做的一种方法是创建两个 SQL 字符串并检查实际值。

您可以按以下方式执行此操作(通常,如果您有一个数组,因为您可以通过值/字段名编写迭代,这会容易得多)。

Do Until .Cells(iRowNo, 1) = ""
    sName = .Cells(iRowNo, 1)
    slastname = .Cells(iRowNo, 2)
    sage = .Cells(iRowNo, 3)

    Dim sqlStrStart As String
    Dim sqlStrValues As String
    Dim sqlStrFull As String

    sqlStrStart = "insert into dbo.table ("
    sqlStrValues = " values ("

    'build string dynamically (generally I do this using parameters, but this will work)
    If sName <> "" Then
        sqlStrStart = sqlStrStart + "name,"
        sqlStrValues = sqlStrValues + sName & ","
    End If
    If slastname <> "" Then
        sqlStrStart = sqlStrStart + "lastname,"
        sqlStrValues = sqlStrValues + slastname & ","
    End If
    If sName <> "" Then
        sqlStrStart = sqlStrStart + "age,"
        sqlStrValues = sqlStrValues + sage & ","
    End If

    'remove last comma
    sqlStrStart = Left(sqlStrStart, Len(sqlStrStart) - 1)
    sqlStrValues = Left(sqlStrValues, Len(sqlStrValues) - 1)

    'close parenthesis
    sqlStrStart = sqlStrStart & ")"
    sqlStrValues = sqlStrValues & ")"

    'combine
    sqlStrFull = sqlStrStart + sqlStrValues + ";"


    conn.Execute sqlStrFull
    iRowNo = iRowNo + 1
Loop

【讨论】:

    【解决方案2】:

    最好的方法是创建一个检查单元格值是否为空的函数。如果为空,则输出应为"null",但如果不是,则将值括在单引号之间。

    也可以使用此函数,以便您可以转义包含单引号的值(例如“O'Brien”)。否则,在您当前的代码中,您将遇到 SQL 错误。

    函数如下:

    Function toSQL(s)
      If s = "" Then toSQL = "null" Else toSQL = "'" & Replace(s, "'", "''") & "'"
    End Function
    

    下面是替换的插入语句:

    conn.Execute "insert into dbo.table (name, lastname,age ) values (" & toSQL(sname) & ", " & toSQL(slastname) & ", " & toSQL(sage) & ")"
    

    如果您始终如一地调用toSQL 函数,并且始终将SQL 数据库中的列定义为可为空,那么您将被设置。如果数据类型是数字,你可能不想调用toSQL

    【讨论】:

    • 这仍然不能防止 SQL 注入,您需要使用 SQL 命令。
    【解决方案3】:

    在 Excel VBA 中设置 null 值时使用它,并将其传递给 SQL 参数的值。

    DBNull.Value
    

    【讨论】:

      猜你喜欢
      • 2022-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 2014-01-08
      • 2016-11-12
      • 2019-08-14
      相关资源
      最近更新 更多