多表查询展示到多DataGridView的问题及存储过程优化咨询
搜索功能实现问题与优化咨询
需求背景
正在实现一个搜索功能,需从数据库多张表查询数据并展示到对应DataGridView中(每张数据库表对应一个DataGridView)。
现有实现
存储过程
获取Style表数据的存储过程
CREATE PROCEDURE [dbo].[FetchCS_V2] @Keyword nvarchar(30) AS SELECT [RID] ,[CustomerBrand] ,[CustomerStyle] ,[ProductName] ,[ProductType] ,[ValidityDateFrom] ,[ValidityDateTo] ,[Colorway] ,[Season] ,[Factory] FROM [dbo].[CostSheet_Mst] WHERE RID Like '%' + @Keyword + '%' OR CustomerStyle Like '%'+ @Keyword + '%' OR ProductName Like '%'+ @Keyword + '%' OR ProductType Like '%'+ @Keyword + '%' OR ValidityDateFrom Like '%'+ @Keyword + '%' OR ValidityDateTo Like '%'+ @Keyword + '%' OR Colorway Like '%'+ @Keyword + '%' OR Season Like '%'+ @Keyword + '%' OR Factory Like '%'+ @Keyword + '%' GO
获取FOB表数据的存储过程
CREATE PROCEDURE [dbo].[FetchCS_FOB_V2] @Keyword nvarchar(30) AS SELECT [FobRID] ,[RID] ,[FOBType] ,[Amount] ,[Currency] FROM [dbo].[CostSheet_FOB] WHERE RID IN (SELECT [RID] FROM CostSheet_Mst where [RID] LIKE '%' + @Keyword + '%') OR [FOBType] LIKE '%' + @Keyword + '%' OR [Amount] LIKE '%' + @Keyword + '%' OR [Currency] LIKE '%' + @Keyword + '%' GO
C#搜索函数
private void searchFromDB() { try { string mainconn1 = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString; SqlConnection sqlconn = new SqlConnection(mainconn1); SqlCommand sqlcomm1 = new SqlCommand("exec [dbo].[FetchCS_V2] '"+searchTextBox.Text+"'", sqlconn); //主表存储过程 SqlCommand sqlcomm2 = new SqlCommand("exec [dbo].[FetchCS_FOB_V2] '" + searchTextBox.Text + "'", sqlconn); //FOB表存储过程 //sqlcomm1.CommandType = CommandType.StoredProcedure; SqlDataAdapter da1 = new SqlDataAdapter(); SqlDataAdapter da2 = new SqlDataAdapter(); da1.SelectCommand = sqlcomm1; da2.SelectCommand = sqlcomm2; DataTable dt1 = new DataTable(); DataTable dt2 = new DataTable(); da1.Fill(dt1); da2.Fill(dt2); dataGridViewStyleSearch.DataSource = dt1; dataGridViewFOBSearch.DataSource = dt2; sqlconn.Close(); } catch (Exception ex) { MessageBox.Show(string.Format("There's an error: {0}", ex.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
当前问题
- 搜索关键词为RID时,两个DataGridView都能返回对应数据;
- 搜索仅FOB表含有的字段(如FOBType、Amount、Currency)时,只有FOB表对应的DataGridView返回数据,Style表的DataGridView无结果。
优化疑问
是否使用单个存储过程查询所有表字段会更优?如果可行,如何将结果存入单个DataTable后拆分到对应DataGridView?
问题原因分析
当前Style表的存储过程FetchCS_V2仅在自身表字段中匹配关键词,当搜索FOB表独有的字段时,Style表无对应匹配逻辑,自然返回空结果。而FOB表的存储过程同时匹配了RID关联的主表数据和自身字段,因此能正常返回结果。
解决方案1:修改现有存储过程
修改FetchCS_V2,增加关联FOB表字段的匹配逻辑,确保搜索FOB字段时能返回关联的主表数据:
CREATE PROCEDURE [dbo].[FetchCS_V2] @Keyword nvarchar(30) AS SELECT DISTINCT m.[RID] ,m.[CustomerBrand] ,m.[CustomerStyle] ,m.[ProductName] ,m.[ProductType] ,m.[ValidityDateFrom] ,m.[ValidityDateTo] ,m.[Colorway] ,m.[Season] ,m.[Factory] FROM [dbo].[CostSheet_Mst] m LEFT JOIN [dbo].[CostSheet_FOB] f ON m.RID = f.RID WHERE m.RID Like '%' + @Keyword + '%' OR m.CustomerStyle Like '%'+ @Keyword + '%' OR m.ProductName Like '%'+ @Keyword + '%' OR m.ProductType Like '%'+ @Keyword + '%' OR m.ValidityDateFrom Like '%'+ @Keyword + '%' OR m.ValidityDateTo Like '%'+ @Keyword + '%' OR m.Colorway Like '%'+ @Keyword + '%' OR m.Season Like '%'+ @Keyword + '%' OR m.Factory Like '%'+ @Keyword + '%' -- 新增FOB表字段匹配逻辑 OR f.FOBType Like '%' + @Keyword + '%' OR f.Amount Like '%' + @Keyword + '%' OR f.Currency Like '%' + @Keyword + '%' GO
解决方案2:使用单个存储过程返回多结果集
单个存储过程可直接返回多个结果集,无需拆分DataTable,ADO.NET会自动处理结果集顺序,效率更高:
单个存储过程实现
CREATE PROCEDURE [dbo].[FetchAllCostSheetData] @Keyword nvarchar(30) AS -- 返回主表数据(包含FOB字段关联匹配) SELECT DISTINCT m.[RID] ,m.[CustomerBrand] ,m.[CustomerStyle] ,m.[ProductName] ,m.[ProductType] ,m.[ValidityDateFrom] ,m.[ValidityDateTo] ,m.[Colorway] ,m.[Season] ,m.[Factory] FROM [dbo].[CostSheet_Mst] m LEFT JOIN [dbo].[CostSheet_FOB] f ON m.RID = f.RID WHERE m.RID Like '%' + @Keyword + '%' OR m.CustomerStyle Like '%'+ @Keyword + '%' OR m.ProductName Like '%'+ @Keyword + '%' OR m.ProductType Like '%'+ @Keyword + '%' OR m.ValidityDateFrom Like '%'+ @Keyword + '%' OR m.ValidityDateTo Like '%'+ @Keyword + '%' OR m.Colorway Like '%'+ @Keyword + '%' OR m.Season Like '%'+ @Keyword + '%' OR m.Factory Like '%'+ @Keyword + '%' OR f.FOBType Like '%' + @Keyword + '%' OR f.Amount Like '%' + @Keyword + '%' OR f.Currency Like '%' + @Keyword + '%' -- 返回FOB表数据 SELECT [FobRID] ,[RID] ,[FOBType] ,[Amount] ,[Currency] FROM [dbo].[CostSheet_FOB] WHERE RID IN (SELECT DISTINCT m.RID FROM [dbo].[CostSheet_Mst] m LEFT JOIN [dbo].[CostSheet_FOB] f ON m.RID = f.RID WHERE m.RID Like '%' + @Keyword + '%' OR m.CustomerStyle Like '%'+ @Keyword + '%' OR m.ProductName Like '%'+ @Keyword + '%' OR m.ProductType Like '%'+ @Keyword + '%' OR m.ValidityDateFrom Like '%'+ @Keyword + '%' OR m.ValidityDateTo Like '%'+ @Keyword + '%' OR m.Colorway Like '%'+ @Keyword + '%' OR m.Season Like '%'+ @Keyword + '%' OR m.Factory Like '%'+ @Keyword + '%' OR f.FOBType Like '%' + @Keyword + '%' OR f.Amount Like '%' + @Keyword + '%' OR f.Currency Like '%' + @Keyword + '%') OR [FOBType] LIKE '%' + @Keyword + '%' OR [Amount] LIKE '%' + @Keyword + '%' OR [Currency] LIKE '%' + @Keyword + '%' GO
C#调用代码
private void searchFromDB() { try { string mainconn1 = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString; using(SqlConnection sqlconn = new SqlConnection(mainconn1)) { SqlCommand sqlcomm = new SqlCommand("[dbo].[FetchAllCostSheetData]", sqlconn); sqlcomm.CommandType = CommandType.StoredProcedure; sqlcomm.Parameters.AddWithValue("@Keyword", searchTextBox.Text); SqlDataAdapter da = new SqlDataAdapter(sqlcomm); DataSet ds = new DataSet(); da.Fill(ds); // 自动填充两个结果集到DataSet,顺序与存储过程返回一致 if(ds.Tables.Count >=1) dataGridViewStyleSearch.DataSource = ds.Tables[0]; if(ds.Tables.Count >=2) dataGridViewFOBSearch.DataSource = ds.Tables[1]; } } catch (Exception ex) { MessageBox.Show(string.Format("错误信息: {0}", ex.Message), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
注:使用using语句自动释放连接资源,参数化查询避免SQL注入风险(原字符串拼接写法存在漏洞)。
方案对比
- 单个存储过程返回多结果集:减少数据库连接次数,逻辑集中易维护,性能更优;
- 拆分DataTable:无必要,ADO.NET原生支持多结果集处理,拆分反而增加代码复杂度与性能损耗。
内容的提问来源于stack exchange,提问作者Riku_dola
相关产品推荐
相关产品推荐

