如何命名在存储过程中返回的数据集表?

时间:2009-02-26 10:32:01

标签: .net sql sql-server dataset

我有以下存储过程

Create procedure psfoo ()
AS
select * from tbA
select * from tbB

然后我以这种方式访问​​数据:

     Sql Command mySqlCommand = new SqlCommand("psfoo" , DbConnection)
     DataSet ds = new DataSet();
     mySqlCommand.CommandType = CommandType.StoredProcedure;
     SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter();
     mySqlDataAdapter.SelectCommand = mySqlCommand;
     mySqlDataAdapter.Fill(ds);

现在,当我想访问我的表时,我必须这样做:

     DataTable datatableA = ds.Tables[0];
     DataTable datatableB = ds.Tables[1];

数据集Tables属性也通过字符串(而不是int)获得了一个访问者。

是否可以在SQL代码中指定表的名称,以便我可以这样写:

     DataTable datatableA = ds.Tables["NametbA"];
     DataTable datatableB = ds.Tables["NametbB"];

我正在使用SQL Server 2008,如果这有所不同。

17 个答案:

答案 0 :(得分:32)

据我所知,从存储过程中,你不能这样做。但是,您可以在检索DataSet后设置名称,然后再使用它们。

ds.Tables[0].TableName = "NametbA";

答案 1 :(得分:8)

存储过程:

    select 'tbA','tbB','tbC' 
    select * from tbA
    select * from tbB
    select * from tbC

前端:

       int i = 1;
       foreach (string tablename in dsEmailData.Tables[0].Rows[0][0].ToString().Split(','))
       {
           dsEmailData.Tables[i++].TableName = tablename;
       }

希望这有帮助

答案 2 :(得分:6)

有没有理由在填写DataSet后无法手动命名它们?

mySqlDataAdapter.Fill(ds);
ds.Tables[0].TableName = "NametbA";
ds.Tables[1].TableName = "NametbB";

我不知道如何命名从存储过程中作为多个结果集的一部分返回的DataTables,但如果你知道存储过程返回什么,那么手动命名它们应该可以正常工作。

修改

知道您可以控制存储过程,一种替代方法可能是在表示表名的结果集中添加一列。然后你可以做类似的事情:

foreach (DataTable table in ds.Tables)
{
    table.TableName = table.Rows[0]["TableName"].ToString();
}

但是,这依赖于实际包含行的存储过程返回的结果集。如果它们不包含行,那么你必须将它包装在“if”语句中,而不是每个表都会得到一个名称。

答案 3 :(得分:2)

好主意,最好你的程序返回三个结果集,而不是在

上添加表名
firs trow of each table
select 'tbA' FirstTableName,'tbB' SecondTableName
select * from tbA
select * from tbB

每次执行程序时,表[0]都会有一行保留选择的表名

另一个想法是传递表名作为过程的输出参数

Create procedure psfoo (@tb1 varchar(50) output,@tb2 varchar(50) output)
AS
set @tb1='tbA'
set @tb2 'tbB'
select * from tbA
select * from tbB

如果此方法限制您并且选择是变量,则可以创建此类程序

Create procedure psfoo ()
    AS
    select * from tbA
    select * from tbB
return 'tbA,tbB'

并通过将程序retrun值拆分为string [] 你可以得到表格的名称

returnvalue=@returnvaluefromSp.split(new char[]{','});
string tablenam1=returnvalue[0];
string tablenam2=returnvalue[1];

答案 4 :(得分:1)

为了给数据集中的所有表命名, 我们需要在SP或T-Sql的最后写一个选择查询。

    lsqry = New System.Text.StringBuilder
lsqry.AppendLine("select * from Bill_main")
lsqry.AppendLine("select * from serviceonly")
lsqry.AppendLine("select * from PendingService")
lsqry.AppendLine("select * from T_servicebillhd")
lsqry.AppendLine("select 'Bill_Main','serviceonly','PendingService','T_servicebillhd'")

Using con As New SqlConnection(lsConnection)
    Try
        con.Open()
        Using cmd As SqlCommand = con.CreateCommand
            With cmd
                .CommandText = lsqry.ToString
                .CommandType = CommandType.Text
            End With
            Using da As New SqlDataAdapter(cmd)
                da.Fill(DS)
            End Using
        End Using

        For li As Integer = 0 To DS.Tables.Count - 2
            DS.Tables(li).TableName = DS.Tables(DS.Tables.Count - 1).Rows(0).Item(li)
        Next
    Catch ex As Exception

    End Try
End Using

在上面的例子中,我使用的是t-sql语句而不是SP。 其中我写了4个选择查询,最后一个是这些表的表名。 并获取包含表名称的最后一个表,并使用TableName属性将其分配给表。

答案 5 :(得分:0)

我知道这是旧帖子,但是在类似的情况下,当我的存储过程返回多个数据集时,我不确定根据满足的条件将返回多少数据集。

因此,我实现了如下排序以按特定顺序获取我的返回数据集,因此我也可以基于代码侧提供的条件在C#代码上管理每个数据集。

if (dsop != null && dsop.ReturnDataSet != null && dsop.ReturnDataSet.Tables.Count > 0)
{
            foreach (DataTable dt in dsop.ReturnDataSet.Tables)
            {
                if (dt.Rows.Count > 0 && dt.Columns.Count > 1)
                {
                    foreach (DataRow dr in dt.Rows)
                    {            //Alarm table[0]
                        if (dt.TableName == "Table")
                        {
                            OperatorHistory operatorReportEntity = new peratorHistory
                            {                                   
                            };
                            reportdata.Add(operatorReportEntity);
                        }
                        //ARC table[2], DW table[3], GT table[4]
                        else if (dt.TableName == "Table2" || dt.TableName == "Table3" || dt.TableName == "Table4")
                        {
                            OperatorHistory operatorReportEntity = new peratorHistory
                            {                                   
                            };
                            reportdata.Add(operatorReportEntity);
                        }
                   }    
               }           
             }  
  }

--table[0]
if(LEN(@ADEventIdsForAlarms ) > 1)
select * from (
---my query logic here
) as TBL_ADEventIdsForAlarms
else
select 'TBL_ADEventIdsForAlarms'

--table[1]
--/* Just Message  */ UNION ALL
if(LEN(@ADEventIdsForOPR ) > 1)
---my query logic here
) as TBL_ADEventIdsForOPR
else
select 'TBL_ADEventIdsForOPR'

--table[2]
if(LEN(@ADEventIdsForARC) > 1)
select * from (
---my query logic here
) as TBL_ADEventIdsForARC
else
select 'TBL_ADEventIdsForARC'

答案 6 :(得分:0)

这个问题很古老,但它在谷歌搜索的顶端,呵呵。 也许它会帮助某人......

答案是肯定的,可以在代码中指定表的名称,以便您可以通过名称访问DataSet中的DataTable。

首先,我必须解释TableMapping的工作原理。 如果我们没有使用SqlDataAdapter指定TableMappings(SqlDataAdapter将填充我们的DataSet),那么默认情况下,第一个表将命名为" Table",第二个将命名为" Table1",third将被命名为"表2"等

因此,当我们想在DataSet中命名DataTable时,我们就像这样使用它:

//...

System.Data.DataSet myDataSet = new System.Data.DataSet();

using (System.Data.SqlClient.SqlDataAdapter dbAdapter = new System.Data.SqlClient.SqlDataAdapter(dbCommand))
{
    dbAdapter.TableMappings.Add("Table", "MyFirstTitleForTableOne");
    dbAdapter.TableMappings.Add("Table1", "MyFirstTitleForTableTwo");
    dbAdapter.TableMappings.Add("Table2", "MyFirstTitleForTableThree");
    dbAdapter.TableMappings.Add("Table3", "MyFirstTitleForTableFour");
        //...

    dbAdapter.Fill(myDataSet);
}

//...

现在,我们可以通过标题访问DataTable:

System.Data.DataTable firstTable = myDataSet.Tables["MyFirstTitleForTableOne"];
System.Data.DataTable secondTable = myDataSet.Tables["MyFirstTitleForTableTwo"];

很抱歉,但我没有编写检查null(myDataSet)的代码或在try / catch块中设置代码,因为我认为这与此问题无关。

答案 7 :(得分:0)

应该使用原始表中的select into“yourtablename”,这只是一个例子,找到select into statement的正确语法。

这是满足您要求的正确方法。三江源。

答案 8 :(得分:0)

试试这个。在MS SQL 2008 R2中,我总是使用它。

mySqlDataAdapter.Fill(ds,"NameTableA");

答案 9 :(得分:0)

试试这个

YourDataAdapter.Fill(ds, "Table");

答案 10 :(得分:0)

你可以试试这个:

在您的程序中添加以下行

Select 'TableName1','TableName2';

使用C#:

for (var i=0;i<ds.Tables[0].Columns.Count;i++)
 {
    ds.Tables[i + 1].TableName = ds.Tables[0].Columns[i].ColumnName;

  }

答案 11 :(得分:0)

我知道这是一个老问题,但我想今天做同样的事情,所以我不只是循环遍历结果数据集的索引。因为如果存储过程按选择的顺序改变,.net代码就会爆炸。

我提出了使用表名向结果集添加列并使用case语句查看表中是否存在列的解决方案。但它似乎只是在移动代码。刚刚使SQL静态化。另外,如果在不同的表中有一个名为相同的列,那该怎么办呢?拉梅...

myDS.Tables(i).Columns.Contains("TableName")

答案 12 :(得分:0)

我知道这是一篇非常古老的帖子,但要回答...... 是的,这是可能的。 只需在dataadapter "TableName"调用中添加Fill即可。

MyDataAdapter.Fill(ds, "TableName");  

我是C#家伙,但你明白了。

答案 13 :(得分:0)

我有一个存储过程访问企业中的所有数据并返回多个结果集。在每个结果集之前使用名称进行选择对我来说更有意义。 像这样:

SELECT 'Customers' AS TableName
SELECT ID, Name FROM dbo.Customer
SELECT 'Orders' AS TableName
SELECT ID, Created FROM dbo.[Order]

然后,当我迭代MyDataSet.Tables时,我只有一个循环和直接查找逻辑。没有主元数据表可以跟上。这甚至在没有返回表时也能工作。如果未返回表数据,则不会返回匹配的元数据,这对我来说很有意义。

For Each DataTable As DataTable In MyDataSet.Tables
  MyDataSet.Tables(MyDataSet.Tables.IndexOf(DataTable) + 1).TableName = DataTable.Rows(0)("TableName")
Next

如果我想在元数据表中添加更多列,我可以。

答案 14 :(得分:0)

您可以返回一个额外的结果集来命名表格,如下所示:

SELECT 'firstTableName' AS tbl
UNION
SELECT 'secondTableName' AS tbl
UNION
...

如果这是第一个结果集,您可以使用它来命名后续结果集。

答案 15 :(得分:0)

这对我有用,但需要一些额外的工作才能获得预期的表名:

    Dim tableCount As Integer = 3
    Dim tables(tableCount) As DataTable
    tables(0) = (New DataTable("Employee"))
    tables(1) = (New DataTable("Manager"))
    tables(2) = (New DataTable("Department"))
    dsUControlData.Tables.Add(tables(0))
    dsUControlData.Tables.Add(tables(1))
    dsUControlData.Tables.Add(tables(2))

    'Fill required tables
    da.Fill(0, 0, tables)

    Return dsUControlData

答案 16 :(得分:-1)

可能这可能是解决方法

 Create procedure psfoo ()
 AS
 select * ,'tbA' as TableName from tbA
 select * ,'tbB' as TableName from tbB

然后在C#代码中

     foreach (DataTable dt in ds.Tables)
        {
            if (dt.Rows[0]["TableName"].ToString().Contains("tbA"))
            {

            }
            else if (dt.Rows[0]["TableName"].ToString().Contains("tbB"))
            {

            }
        }