【问题标题】:Best Approach To Handle Multiple Select Statements In A Single Trip To The Database [duplicate]在一次访问数据库中处理多个选择语句的最佳方法 [重复]
【发布时间】:2013-07-23 01:29:36
【问题描述】:

我认为在以下示例中交易会帮助我,但我可能是错的。如果我在以下场景中没有太多,我试图避免的是对数据库进行 3 次不同的调用..

我想做以下事情:

  1. 从员工中选择姓名、地址
  2. 从状态中选择状态
  3. 从errorTable中选择错误

在这种情况下,我必须调用几个不同的选择来获取数据。处理这个场景以返回我想要读取的所有数据以最小化对数据库的几次调用的最佳方法是什么?

注意:没有表之间存在关系。

【问题讨论】:

  • 您获取的记录之间有什么关系(如果有)?您可以在问题中编辑一些架构信息吗?
  • 这些表之间没有关系。这就是我对如何处理这种场景感到困惑的原因
  • 如果您多次调用这三个查询,那么也许查看准备好的语句以尽量减少重复查询的开销。如果你每次只调用一次,这感觉就像在错误的地方进行优化。您是否量化了三个查询的开销并确定这确实是问题的原因?
  • 不确定为什么要在单次迭代中运行它们?表格之间没有关系,因此无法进行逻辑分组。
  • ...等等...什么?!怎么不是相关数据?

标签: .net sql sql-server tsql


【解决方案1】:

没有理由不能从 sql server 返回多个集合。

select name, address from employee;
select state from states;
select error from errorTable;

使用 sql reader 并获取 .NextResult 将转到下一个数据集。

http://csharp.net-informations.com/data-providers/csharp-multiple-resultsets.htm

【讨论】:

    【解决方案2】:

    如果您不能使用存储过程,那么您可以选择:在一个批次中执行多个select 语句。此“批处理”由 SQL Server 作为单个实体处理,返回多个结果集。一旦你有了它,你就可以

    1. 通过 SqlDataReader 读取它,因此:

      using ( SqlConnection connection = new SqlConnection(connectionString))
      using ( SqlCommand cmd = connection.CreateCommand() )
      {
      
        cmd.CommandText = " select * from foo"
                        + " select * from bar"
                        + " select * from baz"
                        + " select * from bat"
                        ;
        cmd.CommandType = CommandType.Text; ;
      
        using ( SqlDataReader reader = cmd.ExecuteReader() )
        {
          int n = 0 ;
      
          do
          {
      
            Console.WriteLine( "Result set #{0}", ++n ) ;
            int rows = 0 ;
            while ( reader.Read() )
            {
              ++rows ;
              for ( int i = 0 ; i < reader.FieldCount ; ++i )
              {
                object o1 = reader[i] ; // get object by ordinal column number
                string columnName = reader.GetName(i) ;
                object o2 = reader[columnName];
              }
            }
            Console.WriteLine("  {0} rows", rows ) ;
      
          } while ( reader.NextResult() ) ;
        }
      
    2. 通过SqlDataAdapter阅读它,因此:

      DataSet results = new DataSet() ;
      
      using ( SqlConnection connection = new SqlConnection(connectionString))
      using ( SqlCommand cmd = connection.CreateCommand() )
      using ( SqlDataAdapter adapter = new SqlDataAdapter(cmd) )
      {
        cmd.CommandText = " select * from foo"
                        + " select * from bar"
                        + " select * from baz"
                        + " select * from bat"
                        ;
        cmd.CommandType = CommandType.Text; ;
      
        connection.Open() ;
        int rowcount = adapter.Fill(results) ;
        connection.Close() ;
      
      }
      
      Process(results) ;
      

    【讨论】:

      【解决方案3】:

      我认为您可以使用reader.NextResult() 来遍历结果集。借用codeproject的例子:

      connection.Open();
      dataReader = command.ExecuteReader(); // a multi-select query
      while (loopResult) {
         stringBuilder = new System.Text.StringBuilder();
         while (dataReader.Read()) {
            stringBuilder.AppendLine(dataReader.GetInt32(0).ToString());
         }
         System.Windows.MessageBox.Show(stringBuilder.ToString(), "Data from the result set");
         loopResult = dataReader.NextResult();
      }
      

      但是,我不确定对不相关数据的查询进行分组的基本原理是什么。这可能会使您的项目更难理解和维护。

      【讨论】:

      • @我不知道 OP 是否提到他正在使用 .NET。那么,为什么要采用这种解决方案。
      • @Rahul 它被标记为 sql-server ...我做了一个假设。
      • 是标记为 sqlserver 而不是 .NET。此外,OP 要求 TSQL 解决方案/建议和 .NET。
      • @Rahul 是的。还有t-sql。通常,当有人针对sql-server 运行t-sql 时,他们使用的是.NET。我肯定是错的……不过这是一个合理的假设,不是吗?
      • 我正在使用.Net,它的好假设
      【解决方案4】:

      如果表之间没有关系,你可以做一种

      Select [Your selected columns]
      From (select * from table1 where [conditon for table1]) t1
      Inner join (select * from table2 where [condition for table2]) t2 on 1=1 
      Inner join (select * from table3 where [condition for table3]) t3 on 1=1 
      

      这使得一次访问数据库。

      【讨论】:

      • 如果查询 1 返回 10 条记录,查询 2 返回 20 条记录,查询 3 返回 30 条记录,那么您将返回 6000 条记录。这不是我所说的优化。
      • @MatBailie 好点。我会为每张桌子的一行工作得很好。而且对多个表中的多行进行不好的优化。
      • 为什么不能从 sql server 返回多个集合并在数据读取器中捕获它们?
      【解决方案5】:

      我假设您使用的是 ASP.Net 4.0...

      您可以通过执行以下操作将查询“链接”在一起:

      select name, address from employee;select state from states;select error from errorTable;
      

      然后像这样填写DataSet

      string sql = "...";
      SqlCommand comm = new SqlCommand(sql, con);
      SqlDataAdapter adpr = new SqlDataAdapter(comm);
      DataSet ds = new DataSet();
      adpr.Fill(ds);
      

      【讨论】:

      • 是的,我也这么认为,查询将单独运行,而不是单个调用
      • 据我了解,将对数据库进行 1 次调用并返回 3 个表/结果...
      【解决方案6】:

      如果它们之间存在关系,您可以尝试使用 JOIN 表进行选择查询

      【讨论】:

      • 没有表之间有关系
      • 加入不是一个解决方案,因为他很可能正在尝试查询不同的表
      • @MillerKoijam - 这只是一个笛卡尔积。您是否真的建议使用三个不同记录集的 CROSS JOIN ???
      • 可能,带有多选查询的 SP 是唯一的选择。
      【解决方案7】:

      您可能需要考虑使用存储过程。

      【讨论】:

      • 如果这不是一个选项怎么办?您还可以给我看一个带有这些样本选择的 sp 的快速样本吗?
      • 如果 sp 不是一个选项,那么您可能需要考虑使用 union 将几个 select 语句耦合在一起。例如: select column1,column2 ,column3 from table1 union select column1,column2 ,column3 from table2 唯一需要注意的是,所有查询的列数必须相同。
      • Errr,和数据类型一样。错误,您需要一种方法来识别哪一行来自哪个查询。错误,并且由于与该附加列通信,您可能会产生网络流量开销。错误,以及在一个记录集中存在列但在其他记录集中不存在列的情况下传递 NULL 的其他流量。错误,以及由于可能将数据强制放入具有相同类型但名称错误的字段而引起的混乱。是的,只有一个警告......
      猜你喜欢
      • 2012-10-18
      • 2016-01-16
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多