执行一个存储过程,能否实现同时返回几个值和行集?
例如我要同时返回table1中的字段的2个值,同时返回table2的10行(每行是有多个字段的).
如何将这些结果在程序中分别获取出来?

解决方案 »

  1.   

    我用SqlDataReader只能获得行集,不能获得输出参数的值,
    直接用SqlCommand又只能获得返回的参数的值,不能获得行集.
      

  2.   

    可以用output参数返回几个值,同时用select语句返回记录集
      

  3.   

    create procedure proc_name
      as   
      select   *   from   table2;
      

  4.   

    create procedure proc_name
    @ret1 int output,
    @ret2 varchar(20) output
      as   
    set nocount on
    select top 1 @ret1=field1,@ret2=field2 from table1  select   top 10 *   from   table2
    go--调用
    declare @r1 int
    declare @r2 varchar(20)exec proc_name @r1 output,@r2 output
    print @r1
    print @r2
      

  5.   

    再试了下,同时用SqlDataReader和SqlCommand可以成功,
    我用SqlDataReader只能获得行集,
    用SqlCommand获得返回的参数的值,
    但我同时分别调用了一次ExecuteReader()和一次ExecuteNonQuery(),
    究竟这种方式效率如何?是不是将一个存储过程执行了2次?加大了数据库负担吗?
    以上是用的asp.net方式
      

  6.   

    上面贴在发错,怎么csdn现在不能编辑贴子了么?
    再试了下,同时用SqlDataReader和SqlCommand可以成功,
    我用SqlDataReader来获得行集,
    用SqlCommand来获得返回的参数的值,
    但我同时分别调用了一次ExecuteReader()和一次ExecuteNonQuery(),
    究竟这种方式效率如何?是不是将一个存储过程执行了2次?加大了数据库负担吗?
    以上是用的asp.net方式
      

  7.   

    to 海阔天空:
    我试了下你的方法,无法用SqlDataReader来获得第一行的值.
      

  8.   

    想同时获得输出参数的值是不可能的在存储过程里面如果有结果集又有输出参数,那么必须等到DataReader关闭以后才能得到输出参数的值,注意虽然很麻烦但是你少连接了一次数据库,节省了许多开销,也是很值得的
      

  9.   

    要不你把输出参数一起放到表中(用nuion all),传回到datatable时,再选出这输出参数行
      

  10.   

    问题:
    1:怎么把输出参数放到表中?nuion all是什么作用?怎么使用?
    海阔天空的select top 1 @ret1=field1,@ret2=field2 from table1,是无法
    把输出参数构建成1行的,
    2:另外,
    当输出2个select输出2个行集时,asp.net的SqlDataReader只能获得第一个select行集的结果,
    第2个行集结果怎么获得?
      

  11.   

    最开始的问题已经解决了,可以用一个存储过程同时获得行集和输出参数,
    SqlDataReader sqlReader = null;
    sqlReader = CmdObj.ExecuteReader();
    while(sqlReader.Read())
    {
    chapterTotal =  sqlReader.GetInt16(0);
    }
    sqlReader.Close();//这里必须要关闭才能获得下面的输出参数
    //CmdObj.ExecuteNonQuery();//不用执行ExecuteNonQuery()来再执行一次存储过程,直接可以获得输出参数
    chapterTotal =  Convert.ToInt32(CmdObj.Parameters["@chapterTotal"].alue);
    ======================
    现在新的问题就是,当多个行集时,怎么用sqlReader来获得结果,测试了下,只能获得第一个行集,
    当第一个行集读完后,sqlReader.Read()就读不出任何数据而结束了,后面的行集无法获得,有什么方法吗?
      

  12.   

    是union all 打错
     有点像C#中的meger
    如你的列:select * from table 
    结果
     id ,col1,col2
     1   qw   qg
     2   eg   ge假设你的输出参数为@ret1,@ret2
    就 select * from table  union all
     select 0,@ret1,@ret2结果就会
    id ,col1,col2
     1   qw   qg
     2   eg   ge
     0  @ret1 @ret2  我也刚学C#  以上只是本人的想法~
      

  13.   

    msdn中的例子' Assumes that connection is a valid SqlConnection object.
    Dim command As SqlCommand = New SqlCommand( _
      "SELECT CategoryID, CategoryName FROM dbo.Categories;" & _
      "SELECT EmployeeID, LastName FROM dbo.Employees", connection)
    connection.Open()Dim reader As SqlDataReader = command.ExecuteReader()Dim nextResult As Boolean = True
    Do Until Not nextResult
      Console.WriteLine(vbTab & reader.GetName(0) & vbTab & reader.GetName(1))  Do While reader.Read()
        Console.WriteLine(vbTab & reader.GetInt32(0) & vbTab & reader.GetString(1))
      Loop  nextResult = reader.NextResult()
    Loopreader.Close()
    connection.Close()
      

  14.   

    才看清,你是用C#的
    也是msdn的例子:// Assumes that connection is a valid SqlConnection object.
    SqlCommand command = new SqlCommand(
      "SELECT CategoryID, CategoryName FROM dbo.Categories;" +
      "SELECT EmployeeID, LastName FROM dbo.Employees", connection);
    connection.Open();SqlDataReader reader = command.ExecuteReader();do
    {
      Console.WriteLine("\t{0}\t{1}", reader.GetName(0), reader.GetName(1));  while (reader.Read())
        Console.WriteLine("\t{0}\t{1}", reader.GetInt32(0), reader.GetString(1));} while (reader.NextResult());reader.Close();
    connection.Close();
      

  15.   

    msdn上的例子都看了,那个太简单,只是输出单一的值或者只是行.
    所有问题全部解决了,用union all可以用多种思路全部搞定,
    存储过程定义时,注意几点,
    CREATE PROCEDURE test 
    @id1 smallint output,
    @id2 int ,
    @id3 int 
    AS
    set nocount on
    BEGIN TRANSACTIONSELECT @id1 = id 
    FROM BookIndex
    WHERE (bID = 135 )
    COMMIT TRANSACTIONSELECT id, 1   //这里注意,第一个行集是1列,但union all的表必须是列数相同,因此用1凑够列数
    FROM BookIndex
    WHERE (bid = @id2 ) or (bid = @id3 )  union   allSELECT ChapterTotal, name//第2个行集是2列
    FROM BookIndex
    WHERE (bid = 145 )  union   allSELECT @id1 , 2//这里注意,不能直接将赋值给输出参数的语句作为union all的对象,必须先获得@id的值再union all
    GO这样所有结果全部放在一个行集的表里返回了.
    具体在程序里获得返回的行集,怎么判断第1个行集结束,和第2个行集开始的呢?如果知道确切的每个
    行集返回的行数是很简单的,但如果不知道每个行集返回的行数呢?我采用将第一个和第二个行集的列的类型
    设置不同来搞定,获取结果时,当程序捕捉到转变类型异常,就知道是第2个行集开始了.
      

  16.   

    另外不知道union的效率如何?增加了服务器的负担吗?
      

  17.   

    看来union all是不怎么消耗资源的,效率很高,而单独union效率要损失,因为要去比较.