我是 SQLite 新手,在使用 VB 编写的搜索例程时遇到问题。我有一个存储人员的表(姓名、出生日期、地址、电话号码、描述等)。我的搜索例程创建一个虚拟表(使用 fts5 模块),它具有与我的 Person 表相同的列。
假设用户想按性别和描述进行搜索。我通过找到性别匹配的每个人来开始搜索。然后我将把搜索结果放入一个虚拟表中,然后可以在该表中搜索具有匹配描述的任何人。
我有它创建虚拟表并找到具有匹配性别的每个人的位置,但我无法将这些搜索结果放入虚拟表中。我想我可以逐列复制数据,但认为可能有更简单的方法?
以下是我的代码。
Try
'opens the database connection
If (OpenDBConn() = False) Then
Exit Sub
End If
sqliteExecCmd = GlobalVar.dbConn.CreateCommand()
sqliteExecCmd.CommandText = "**THE COMMAND THAT FINDS EVERYONE BASED ON INITIAL SEARCH**"
sqliteReader = sqliteExecCmd.ExecuteReader()
sqliteExecCmd.Dispose() 'disposes of read command after it has been used
Using sqliteReader
While sqliteReader.Read
'THIS IS WHERE I NEED TO PLACE ANY LOCATED RECORD(S) INTO THE VIRTUAL TABLE
End While
End Using
sqliteReader.Close() 'closes reader
Catch ex As Exception
'closes connection if it is left open
If (GlobalVar.dbConn.State = ConnectionState.Open) Then
CloseDBConn() 'closes the db connection
End If
DisplayError(ex.ToString, "SearchNoc")
End Try
CloseDBConn() 'closes the db connection
实际上,在少数情况下,您将并且需要查询/过滤您“已经”从 SQLite 中提取的数据。
但是,.net 中的任何简单查询几乎总是可以作为“内存中”表返回,并且您可以过滤这些结果。然而,在大多数情况下,最好对数据库重新查询。通过索引,您通常可以获得更好的性能,并且最终使用更少的内存。
所以,拿一份简单的酒店清单。我可能想按城市搜索,然后可能按酒店名称搜索(通配符 - 以字母开头)。
那么,说出这个简单的形式:
因此,在上面,我们提取了第一个数据集(城市)。
然后,我们想要过滤更多。
但是,我没有对第一次数据拉取进行过滤,因为它确实没有多大帮助。
所以,背后的代码如下所示:
Private Sub cmdSearch_Click(sender As Object, e As EventArgs) Handles cmdSearch.Click
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description FROM tblHotels
WHERE City Like @City And HotelName like @Hotel
ORDER BY HotelName"
Dim cmdSQL As New SQLite.SQLiteCommand(strSQL)
cmdSQL.Parameters.Add("@City", DbType.String).Value = txtCity.Text & "%"
cmdSQL.Parameters.Add("@Hotel", DbType.String).Value = txtHotel.Text & "%"
DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
DataGridView1.DataSource = MyRstP(cmdSQL)
End Sub
Public Function MyRstP(cmdSQL As SQLite.SQLiteCommand) As DataTable
Dim rstData As New DataTable
Using con As New SQLite.SQLiteConnection(My.Settings.Hotels)
cmdSQL.Connection = con
Using (cmdSQL)
con.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
现在,在上面,我只是使用了通配符(以开头),例如匹配。
但是,我想我可以重写上面的内容,并说拉取 City 的数据表,然后根据第二个条件过滤数据表 = HotelName。
如前所述,在大多数情况下,这不值得麻烦,并且使用高速数据库索引,然后再次访问数据库引擎以获得第二个条件不仅是一个很好的方法,而且经常推荐。
但是,让我们更改代码以按城市拉取,然后根据数据表中的结果进行过滤(数据表是内存中的表,对于这种情况相当方便)。
所以,现在代码变成了这样:
Dim rstData As DataTable
Private Sub cmdSearch_Click(sender As Object, e As EventArgs) Handles cmdSearch.Click
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description FROM tblHotels
WHERE City Like @City
ORDER BY HotelName"
Dim cmdSQL As New SQLite.SQLiteCommand(strSQL)
cmdSQL.Parameters.Add("@City", DbType.String).Value = txtCity.Text & "%"
DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
rstData = MyRstP(cmdSQL)
DataGridView1.DataSource = rstData
End Sub
Private Sub cmdFilter_Click(sender As Object, e As EventArgs) Handles cmdFilter.Click
rstData.DefaultView.RowFilter = $"[HotelName] Like '{txtHotel.Text}%'"
End Sub
Public Function MyRstP(cmdSQL As SQLite.SQLiteCommand) As DataTable
Dim rstData As New DataTable
Using con As New SQLite.SQLiteConnection(My.Settings.Hotels)
cmdSQL.Connection = con
Using (cmdSQL)
con.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
因此,请注意我们如何将数据表的范围限定到表单,从而针对该数据表进行过滤,并且不要再次重新拉取数据。
所以表格现在看起来像这样:
因此,可以根据我们首先从数据库中提取的数据表进行过滤。然而,在实践中,通常最好只是从数据库中重新提取并针对数据库进行过滤,因为查询系统可以使用索引,而针对内存表(数据表对象)的过滤不使用索引。