从 2 个不同的数据库(MySQL 和 SQL)在 Listview 中插入值
Posted
技术标签:
【中文标题】从 2 个不同的数据库(MySQL 和 SQL)在 Listview 中插入值【英文标题】:Insert Values in Listview from 2 different DataBases (MySQL and SQL) 【发布时间】:2021-05-10 15:39:50 【问题描述】:我正在使用 2 个不同的数据库,一个是 SQL 服务器,另一个是 mysql。
我正在尝试交叉它们之间的数据。 2 DB 有一个共同的产品参考。但两者都使用非常不同的数据。
例如,在 Mysql 中,我有简单的数据,如描述、价格、类型...。 在 SQL 中,我使用了最后价格、折扣、条形码.... 但是有些产品在两个数据库中都没有数据,所以它们必须在某些字段中保持为空。 我必须将这些数据交叉到 ListView 中。
到目前为止我有这个代码:
Private Sub button_search_Click(sender As Object, e As EventArgs) Handles button_search.Click
'--------------------------------MySQL
Call connect()
Dim marca_prod As String
Dim fam_prod As String
Dim tipo_prod As String
Dim sql As String
rs = New ADODB.Recordset
If type_1.Checked Then
tipo_prod = "1"
ElseIf type_2.Checked Then
tipo_prod = "2"
Else
tipo_prod = ""
End If
If proc_desc.Checked Then
sql = "SELECT p.referencia AS Referencia, p.descricao AS Descrição, p.tipo AS Tipo, f.nome_familia AS Familia, m.nome_marca AS Marca FROM ((produtos AS p INNER JOIN familias AS f ON p.Id_familia = f.Id_familia) INNER JOIN marcas AS m ON p.Id_marca = m.Id_marca) WHERE p.descricao LIKE '%" & Prod_input.Text & "%' AND p.tipo LIKE '" & tipo_prod & "%' "
ElseIf proc_ref.Checked Then
sql = "SELECT p.referencia AS Referencia, p.descricao AS Descrição, p.tipo AS Tipo, f.nome_familia AS Familia, m.nome_marca AS Marca FROM ((produtos AS p INNER JOIN familias AS f ON p.Id_familia = f.Id_familia) INNER JOIN marcas AS m ON p.Id_marca = m.Id_marca) WHERE p.referencia LIKE '%" & Prod_input.Text & "%' AND p.tipo LIKE '" & tipo_prod & "%' "
Else
sql = "SELECT p.referencia AS Referencia, p.descricao AS Descrição, p.tipo AS Tipo, f.nome_familia AS Familia, m.nome_marca AS Marca FROM ((produtos AS p INNER JOIN familias AS f ON p.Id_familia = f.Id_familia) INNER JOIN marcas AS m ON p.Id_marca = m.Id_marca) WHERE (p.referencia LIKE '%" & Prod_input.Text & "%' OR p.descricao LIKE '%" & Prod_input.Text & "%') AND p.tipo LIKE '" & tipo_prod & "%' "
End If
rs.Open(sql, conn)
query_results.Items.Clear()
While Not rs.EOF
Dim lv As New ListViewItem
lv = query_results.Items.Add(rs.Fields(0).Value)
lv.SubItems.Add(rs.Fields(1).Value)
lv.SubItems.Add(rs.Fields(2).Value)
lv.SubItems.Add(rs.Fields(3).Value)
lv.SubItems.Add(rs.Fields(4).Value)
rs.MoveNext()
End While
'-----------------------------SQL
Dim myDBCnn As SqlConnection
Dim myDBCmd As SqlCommand
Dim myDBReader As SqlDataReader
myDBCnn = New SqlConnection("************")
myDBCnn.Open()
Dim MystrQ As String
Dim i = 0
While Not rs.EOF
MystrQ = "Select stock, epcult, epcpond FROM st WHERE ref ='" & rs.Fields(0).Value & "'"
myDBCmd = New SqlCommand(MystrQ, myDBCnn)
myDBReader = myDBCmd.ExecuteReader
While myDBReader.Read
Dim lv As New ListViewItem
lv = query_results.Items.Add(myDBReader.Item(5))
lv.SubItems.Add(myDBReader.Item(6))
lv.SubItems.Add(myDBReader.Item(7))
End While
End While
myDBReader.Close()
myDBCmd.Dispose()
myDBCnn.Close()
If query_results.Items.Count = 0 Then
MsgBox("Não foram encontrados registos para os parametros selecionados!")
End If
count_label.Text = query_results.Items.Count
End Sub
目前我在最后的 myDBReader.Close() 中遇到错误 -> “对象引用未设置为对象的实例” 但我认为其他代码不正确。 我能做什么?
【问题讨论】:
【参考方案1】:我将数据访问代码与用户界面代码分开。这将使您的应用程序更易于维护。数据库函数是传递值,因此它们不依赖于值的来源。用户界面不依赖于数据的来源。它可以是文本文件、Web 服务或任何类型的数据库。
我抛弃了 ADODB 和记录集,它们是非常古老的技术,直接使用了 ADO.net。这将需要 MySql 提供程序的导入。
Imports MySql.Data.MySqlClient
即使出现错误,Using...End Using
块也会处理关闭和释放数据库对象。
始终使用参数。 从不连接字符串来构建 sql 语句。我不得不猜测参数的数据类型。检查您的数据库并根据需要调整代码。
Private ConStrMySql As String = "Your connection string"
Private ConStrSql As String = "Your connection string"
Private Sub button_search_Click(sender As Object, e As EventArgs) Handles button_search.Click
Dim tipo_prod As String
If type_1.Checked Then
tipo_prod = "1"
ElseIf type_2.Checked Then
tipo_prod = "2"
Else
tipo_prod = ""
End If
Dim dt = GetMySqlData(proc_desc.Checked, proc_ref.Checked, Prod_input.Text, tipo_prod)
query_results.Items.Clear()
For Each row As DataRow In dt.Rows
Dim lv As New ListViewItem
lv.Text = row(0).ToString
lv.SubItems.Add(row(1).ToString)
lv.SubItems.Add(row(2).ToString)
lv.SubItems.Add(row(3).ToString)
lv.SubItems.Add(row(4).ToString)
Dim dt2 = GetSqlData(row(0).ToString)
lv.SubItems.Add(dt2.Rows(0)(0).ToString)
lv.SubItems.Add(dt2.Rows(0)(1).ToString)
lv.SubItems.Add(dt2.Rows(0)(2).ToString)
query_results.Items.Add(lv)
Next
If query_results.Items.Count = 0 Then
MsgBox("Não foram encontrados registos para os parametros selecionados!")
End If
count_label.Text = query_results.Items.Count.ToString
End Sub
Private Function GetMySqlData(ProcDesc As Boolean, ProcRef As Boolean, ProdInput As String, tipo As String) As DataTable
Dim sql = "SELECT p.referencia AS Referencia, p.descricao AS Descrição, p.tipo AS Tipo, f.nome_familia AS Familia, m.nome_marca AS Marca FROM ((produtos AS p INNER JOIN familias AS f ON p.Id_familia = f.Id_familia) INNER JOIN marcas AS m ON p.Id_marca = m.Id_marca) "
If ProcDesc Then
sql &= "WHERE p.descricao Like @Prod AND p.tipo LIKE @Type;"
ElseIf ProcRef Then
sql &= "WHERE p.referencia LIKE @Prod AND p.tipo LIKE @Type;"
Else
sql &= "WHERE (p.referencia LIKE @Prod OR p.descricao LIKE @Prod) AND p.tipo LIKE @Type;"
End If
Dim dt As New DataTable
Using conn As New MySqlConnection(ConStrMySql),
cmd As New MySqlCommand(sql, conn)
cmd.Parameters.Add("@Prod", MySqlDbType.VarChar).Value = "%" & ProdInput & "%"
cmd.Parameters.Add("@Type", MySqlDbType.VarChar).Value = tipo & "%"
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Function GetSqlData(Ref As String) As DataTable
Dim dt As New DataTable
Using conn As New SqlConnection(ConStrSql),
cmd As New SqlCommand("Select stock, epcult, epcpond FROM st WHERE ref = @Ref", conn)
cmd.Parameters.Add("@Ref", SqlDbType.VarChar).Value = Ref
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
编辑
要使tipo 成为Int16(vb.net 中的短),您需要做的不仅仅是更改参数的数据类型。
更正tipo_prod的值设置。
Dim tipo_prod As Short
If type_1.Checked Then
tipo_prod = 1
ElseIf type_2.Checked Then
tipo_prod = 2
Else
tipo_prod = 0
End If
更正MySql函数的签名。
Private Function GetMySqlData(ProcDesc As Boolean, ProcRef As Boolean, ProdInput As String, tipo As Short) As DataTable
更正sql语句。一个数字“喜欢”另一个数字可能意味着什么?
If ProcDesc Then
sql &= "WHERE p.descricao Like @Prod AND p.tipo = @Type;"
ElseIf ProcRef Then
sql &= "WHERE p.referencia LIKE @Prod AND p.tipo = @Type;"
Else
sql &= "WHERE (p.referencia LIKE @Prod OR p.descricao LIKE @Prod) AND p.tipo = @Type;"
End If
你检查过你在 Workbench 和 SSMS 中的 sql 语法吗?
编辑 2
如果 SQL Server 数据库中没有匹配的数据,则忽略它。
For Each row As DataRow In dt.Rows
Dim lv As New ListViewItem
lv.Text = row(0).ToString
lv.SubItems.Add(row(1).ToString)
lv.SubItems.Add(row(2).ToString)
lv.SubItems.Add(row(3).ToString)
lv.SubItems.Add(row(4).ToString)
Dim dt2 = GetSqlData(row(0).ToString)
If dt2.Rows.Count > 0 Then
lv.SubItems.Add(dt2.Rows(0)(0).ToString)
lv.SubItems.Add(dt2.Rows(0)(1).ToString)
lv.SubItems.Add(dt2.Rows(0)(2).ToString)
End If
query_results.Items.Add(lv)
Next
【讨论】:
您好,谢谢您的详细解答。我在Using reader = cmd.ExecuteReader
中收到错误,因为输入字符串的格式不正确。我知道你警告过我数据库中的数据类型,所以我将 ProdInput 设为 Varchar,将 Tipo 设为 Int16。在数据库中,它们分别是 varchar 和 Integer。我更改了代码中的所有数据类型以匹配,但我得到了同样的错误。我认为问题在于 SQL 字符串没有得到@Prod 和@Type 的值,它们按照我写的那样去,所以没有价值。
所以问题出在我的脚本上,但我更正了问题。但是,当 sql DB 中不存在产品时,我该如何处理?因为我得到了一个错误。
@Rwolf27 我在 EDIT 中处理了您的第一条评论。第二条评论见EDIT 2。以上是关于从 2 个不同的数据库(MySQL 和 SQL)在 Listview 中插入值的主要内容,如果未能解决你的问题,请参考以下文章
是否可以从具有 SQL 和 mySql 中的数据库的内部连接中获取不同数据库的信息?
mysql:只用一条sql语句,如何查出一个表里,不同条件对应的数据条数