You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何SQLite数据库无法更新合并后的表格数据?

问题分析与解决方案

我来帮你拆解下为啥合并后的数据没法写入SQLite,咱们一步步定位问题并解决:

核心问题点

1. 语法错误导致代码无法正常执行

你在构建CREATE TABLE的SQL语句时,If i < iMax Then代码块缺少了End If,这会直接引发编译错误,后续的表创建和数据合并逻辑根本没法正常跑起来。

2. 无主键导致DataAdapter无法识别新增行

SQLiteDataAdapter需要通过主键(或唯一约束)来区分数据行的状态(新增/修改/删除),你的两个DataTable都没有主键,Merge之后DataAdapter无法判断哪些是需要插入的新行,自然不会提交数据。

3. Merge后的行状态未标记为新增

默认情况下,Merge操作会把合并进来的行的RowState设为Unchanged,而DataAdapter只会处理Added/Modified/Deleted状态的行,这些未标记的行就会被忽略。

4. 未配置DataAdapter的Insert命令

你只创建了SQLiteDataAdapter,但没有为它配置Insert命令,也没有用SQLiteCommandBuilder自动生成命令,导致DataAdapter不知道该如何把数据插入数据库。


修复后的完整代码

我标记了所有关键修改点,你可以直接替换测试:

Private Sub cmdImportFile_Click(sender As Object, e As EventArgs) Handles cmdImportFile.Click
    Dim bHeaders As Boolean = chkHeaders.CheckState
    Dim oFile As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(txtFilePath.Text)
    Dim da As SQLite.SQLiteDataAdapter
    Dim ds As New DataSet
    Dim dt2 As New DataTable
    Try
        Dim XLConn As System.Data.OleDb.OleDbConnection
        Dim DtSet As New System.Data.DataSet
        Dim XLDataAdapter As System.Data.OleDb.OleDbDataAdapter
        'Create connection to selected XLSX workbook, Sheet1
        XLConn = New System.Data.OleDb.OleDbConnection _
        ("provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & oFile.FullName & "; Extended Properties=""Excel 12.0 Xml;HDR=" & bHeaders & "; IMEX=1"";")
        XLDataAdapter = New System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", XLConn)
        'Open and fill dataset to table 'XLSheet'
        XLDataAdapter.Fill(DtSet, "XLSheet")
        XLConn.Close()
        'Setup DataTable object
        Dim dt As DataTable = DtSet.Tables("XLSheet")
        'Connect to SQLite
        Dim sAppPath As String = Application.StartupPath
        'When debugging, this changes the AppPath value to remove the \bin\Debug portion of the AppPath
        If Debugger.IsAttached Then
            sAppPath = sAppPath.Replace("\bin\Debug", "")
        End If ' 补充缺失的End If
        Dim connString As String = "Data Source = " & sAppPath & "\biodata.db;version=3;"
        Dim conn As New SQLiteConnection(connString) ' 补充conn的声明
        conn.Open()
        'Drop Existing "XLImport" table
        Dim cmd As SQLiteCommand
        Dim sDROPSQL As String = "DROP TABLE IF EXISTS XLImport;"
        cmd = conn.CreateCommand()
        cmd.CommandText = sDROPSQL
        cmd.ExecuteNonQuery() ' DDL操作改用ExecuteNonQuery,不需要返回结果集
        cmd.Dispose()
        'Build dynamic SQL string for CREATE TABLE based on imported XLS file
        Dim iMax As Integer = dt.Columns.Count
        Dim i As Integer = 1
        ' 新增自增主键,让DataAdapter能唯一识别行
        Dim sSQL As String = "CREATE TABLE XLImport(ID INTEGER PRIMARY KEY AUTOINCREMENT, "
        For Each c As DataColumn In dt.Columns
            Debug.Print(c.DataType.ToString)
            sSQL = sSQL & "[" & c.ColumnName & "] " & ConvertXLDataTypeToSQLite(c.DataType.ToString)
            If i < iMax Then
                sSQL = sSQL & ","
                i = i + 1
            End If ' 补充缺失的End If
        Next
        sSQL = sSQL & ");"
        'Create Table "XLImport" from Dynamic SQL Statement
        cmd = conn.CreateCommand
        cmd.CommandText = sSQL
        cmd.ExecuteNonQuery() ' 执行DDL
        cmd.Dispose()
        'Query empty XLImport table
        cmd = conn.CreateCommand
        cmd.CommandText = "SELECT * FROM XLImport"
        da = New SQLiteDataAdapter(cmd.CommandText, conn)
        ' 添加CommandBuilder自动生成Insert/Update/Delete命令
        Dim cb As New SQLiteCommandBuilder(da)
        'Fill Dataset table "XLImport"
        da.Fill(ds, "XLImport")
        'Create DataTable object for 'XLImport'
        dt2 = ds.Tables("XLImport")
        'Merge the two dataTables - 配置参数处理状态和架构
        dt2.Merge(dt, False, MissingSchemaAction.Ignore)
        ' 将合并进来的行标记为Added,确保DataAdapter执行插入
        For Each row As DataRow In dt2.Rows
            If row.RowState = DataRowState.Unchanged Then
                row.SetAdded()
            End If
        Next
        ' 提交数据到数据库
        da.Update(ds.Tables("XLImport"))
        MessageBox.Show("数据导入成功!")
    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
End Sub

Private Function ConvertXLDataTypeToSQLite(sDataType As String) As String
    Dim sNewDataType As String
    Select Case sDataType
        Case "System.Int64", "System.Int16", "System.Byte", "System.Byte[]", "System.Int32", "System.UInt16", "System.Boolean", "System.Single"
            sNewDataType = "INTEGER" ' SQLite标准整数类型
        Case "System.Double"
            sNewDataType = "REAL" ' SQLite标准浮点类型
        Case "System.String"
            sNewDataType = "TEXT" ' SQLite用TEXT自动适配长度,比VARCHAR更灵活
        Case "System.DateTime"
            sNewDataType = "TEXT" ' 推荐用ISO8601格式文本存储日期,兼容性更好
        Case "System.GUID"
            sNewDataType = "TEXT" ' GUID存文本更易读,也可选择BLOB
        Case "System.Decimal"
            sNewDataType = "NUMERIC" ' SQLite支持高精度数值存储
        Case Else
            sNewDataType = "TEXT" ' 未知类型默认用TEXT,避免报错
    End Select
    Return sNewDataType
End Function

关键修改说明

  1. 修复语法错误:补充了两处缺失的End If,确保代码能正常编译执行。
  2. 添加自增主键:给XLImport表新增ID INTEGER PRIMARY KEY AUTOINCREMENT,让DataAdapter能唯一识别每一行。
  3. 引入SQLiteCommandBuilder:自动生成Insert命令,省去手动编写动态SQL的麻烦。
  4. 修正行状态:Merge后将所有Unchanged状态的行标记为Added,确保DataAdapter会处理这些新行。
  5. 优化数据类型映射:调整为SQLite更标准的数据类型,避免兼容性问题。
  6. 替换执行方法:DDL操作改用ExecuteNonQuery,更符合操作逻辑。

这样修改后,合并的数据应该就能正常写入SQLite数据库了。

内容的提问来源于stack exchange,提问作者The Special

火山引擎 最新活动