具有临时表的存储过程的 SqlDataAdapter.FillSchema

Posted

技术标签:

【中文标题】具有临时表的存储过程的 SqlDataAdapter.FillSchema【英文标题】:SqlDataAdapter.FillSchema with stored procedure that has temporary table 【发布时间】:2013-09-24 18:32:52 【问题描述】:

我在此处 (Display DataType and Size of Column from SQL Server Query Results at Runtime) 遇到了与此问题类似的问题,该问题没有可靠的解决方案。

我想知道是否有人找到了解决方案或解决方法。我可以使用SqlDataAdapter.Fill()没有问题,但是.FillSchema()会报错我在存储过程中创建的临时表不存在。

我的目标是能够使用来自源的数据和架构填充 DataTable。

【问题讨论】:

【参考方案1】:

存储过程和临时表通常不能很好地与数据库对象的强类型实现混合。

如果您将#temp 表更改为应该可以解决您的问题的表@variable。

如何从临时表更改为表变量的示例如下:

    CREATE TABLE #tempTable (ID INT, Val VARCHAR(50))

    DECLARE @tempTable TABLE(ID INT, Val VARCHAR(50))

【讨论】:

【参考方案2】:

我在SqlDataAdapter 遇到了同样的问题。我可以通过将代码更改为使用 SqlDataReader 来解决此问题。

如果你根本不需要修改架构

如果您不需要操作 DataTable 对象的架构并且您还计划使用从存储过程返回的数据,则以下代码段可以正常工作。

var command = new SqlCommand("stored procedure name")

    CommandType = CommandType.StoredProcedure 
;

var adapter = new SqlDataAdapter(command);
var dt = new DataTable();

adapter.Fill(dt);

var command = new SqlCommand("stored procedure name")

    CommandType = CommandType.StoredProcedure 
;

var reader = command.ExecuteReader();
var dt = new DataTable();

dt.Load(reader);

这两种方法都将使用与从存储过程调用返回的名称和类型相对应的列名称和类型填充数据表。如果您需要有关架构的信息,可以通过 DataTable.Columns 属性访问它。

如果需要修改架构

如果您只需要架构信息,或者如果您需要在使用数据填充 DataTable 对象中的架构之前对其进行操作,即使 SqlDataAdapter.FillSchema 不需要,以下方法也可以使用。

var command = new SqlCommand("stored procedure name")

    CommandType = CommandType.StoredProcedure 
;

var reader = command.ExecuteReader();

var schemaTable = reader.GetSchemaTable();

SqlDataReader.GetSchemaTable() 将返回一个 DataTable 对象,其中列元数据填充为行。

您可以枚举结果以构建和/或操作DataTable 对象中的列,该对象将保存SqlDataReader 返回的记录。

在我的例子中,我需要每列都是一个字符串,以避免在将数据导出到电子表格时出现来自 Microsoft Excel 的任何格式化“帮助”。例如,我的代码如下所示:

var dt = new DataTable();

foreach(DataRow row in schemaTable.Rows)

    dt.Columns.Add((string)row["ColumnName"], typeof(string));


dt.Load(reader);

【讨论】:

【参考方案3】:

如果你不需要DataSet,而只需要一个DataTable,你可以使用

DataTable dt= new DataTable();

dt.Load(cmd.ExecuteReader());

对于 DataSet,您至少必须告诉 SP 返回的表的名称(这意味着数字)。

DataSet ds = new DataSet();
SqlDataReader sdr = cmd.ExecuteReader();
ds.Load(sdr, LoadOption.OverwriteChanges,"Table1");

【讨论】:

你不喜欢这种方法吗?

以上是关于具有临时表的存储过程的 SqlDataAdapter.FillSchema的主要内容,如果未能解决你的问题,请参考以下文章

oracle存储过程中临时表的使用,该怎么处理

oracle存储过程中临时表的使用,该怎么处理

使用临时表的存储过程

oracle 怎么在存储过程中创建一个临时表,在里面插入数据,再查找这个临时表的所有数据,最后drop这个表。

Oracle存储过程中临时表的使用技巧

Oracle 存储过程的全局临时表的替代方法