从Excel传递Null值到SQL

3
我将使用 VBA 脚本来更新 SQL 中的表格,目前看来它工作得很好。但是在处理空值时会有问题。由于 VBA 脚本会循环至第一列结束,因此工作表中的某些值为空,但在 SQL 中则被放置为零。
在 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

如果你能展示出你的实际代码,回答会更容易一些。 - Tim Williams
1
你使用的VBA是用来填充数据库的吗?一种方法是使用参数,仅在值非空时包含参数。 - enderland
@enderland,我在最后添加了VBA代码。谢谢! - eflores89
@eflores,不要告诉循环在单元格为空时终止,使用VBA查找最后一行。A列始终有数据吗?那么可以使用lastRow = cells(rows.count,1).end(xlup).row,然后用For iRowNo = 2 to lastRow循环替换Do循环。或者如果您不知道哪一列包含最后一行,请对所有列执行此操作并选择最高值。 - Acantud
我不知道那是否是一个真实的连接字符串,但你应该从代码示例中删除它。 - Kyle Hale
3个回答

0

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

DBNull.Value

0

我做过的一种方法是创建两个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

0

最好的方法是创建一个函数来检查单元格的值是否为空。当为空时,输出应该是"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函数,并且一直将列定义为可空的,则可以设置。如果数据类型是数字,则可能不想调用toSQL

这仍然不能防止SQL注入,您需要使用SQL命令。 - Jeremy Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接