将DataTable传递给存储过程中的表值参数不起作用[关闭]
Posted
技术标签:
【中文标题】将DataTable传递给存储过程中的表值参数不起作用[关闭]【英文标题】:Passing DataTable to Table-Valued Parameter in stored procedure not working [closed] 【发布时间】:2021-08-23 12:44:29 【问题描述】:因此,我需要将表值参数(从 CheckBoxLists 中的选定选项填充)传递给存储过程,以便检索与我的表值参数中的某些条件匹配的配方,但是当我尝试这样做时它,它不返回任何东西。我正在研究 ASP.Net 和 C#。
SQL Server 存储过程
CREATE TYPE dbo.Filtros AS TABLE
(
Categoria NVARCHAR(50),
Dificuldade NVARCHAR(50),
Duracao NVARCHAR(50)
);
GO
ALTER PROCEDURE [dbo].[uspPesquisarReceita] (@TVP dbo.Filtros READONLY)
AS
BEGIN
SELECT R.NomeReceita, C.NomeCategoria, DF.Dificuldade, D.Duracao, R.ClassificacaoGeral, R.DataPublicacao, R.Foto, R.NumVisualizacoes, R.IDReceita
FROM dbo.Receitas R
LEFT JOIN dbo.Categorias C ON R.IDCategoria = C.IDCategoria
LEFT JOIN dbo.Dificuldade DF ON R.IDDificuldade = DF.IDDificuldade
LEFT JOIN dbo.Duracao D ON R.IDDuracao = D.IDDuracao
WHERE R.IDEstado = 1 AND C.NomeCategoria IN (SELECT Categoria FROM @TVP) OR DF.Dificuldade IN (SELECT Dificuldade FROM @TVP) OR D.Duracao IN (SELECT Duracao FROM @TVP)
END
我用来填充用作 TVP 的 DataTable 的代码是正确的,因为我通过将其内容打印到标签来测试它。因此,DataTable 正在正确接收和存储复选框列表中选择的选项。
用于存储过程和 DataTable 的 C# 用于存储来自存储过程的结果数据
public SqlDataReader receitaPesquisada(DataConnection conn, string pesquisa, DataTable tabelaParam)
SqlDataReader drObterReceita = null;
try
string strCmmd = "uspPesquisarReceita";
SqlCommand command = new SqlCommand(strCmmd, conn.Connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@Pesquisa", SqlDbType.NVarChar).Value = pesquisa;
SqlParameter param = new SqlParameter("@TVP", tabelaParam);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "dbo.Filtros";
command.Parameters.Add(param);
drObterReceita = command.ExecuteReader();
return drObterReceita;
catch (Exception ex)
Console.Write("Algo correu mal no método" + ex.ToString());
return drObterReceita;
public DataTable imprimirReceitaPesquisada(string pesquisa, DataTable tabelaParam)
DataConnection conn = new DataConnection();
DataTable dtbReceitaPesquisada = new DataTable();
dtbReceitaPesquisada.Columns.Add("NomeReceita", typeof(string));
dtbReceitaPesquisada.Columns.Add("Categoria", typeof(string));
dtbReceitaPesquisada.Columns.Add("Dificuldade", typeof(string));
dtbReceitaPesquisada.Columns.Add("Duracao", typeof(string));
dtbReceitaPesquisada.Columns.Add("ClassificacaoGeral", typeof(string));
dtbReceitaPesquisada.Columns.Add("DataPublicacao", typeof(string));
dtbReceitaPesquisada.Columns.Add("Foto", typeof(string));
dtbReceitaPesquisada.Columns.Add("NumVisualizacoes", typeof(string));
try
conn.openConnection();
SqlDataReader drObterReceita = this.receitaPesquisada(conn, pesquisa, tabelaParam);
while (drObterReceita.Read())
dtbReceitaPesquisada.Rows.Add(drObterReceita[0].ToString(), drObterReceita[1].ToString(), drObterReceita[2].ToString(), drObterReceita[3].ToString(), Math.Round(double.Parse(drObterReceita[4].ToString()), 1).ToString(), drObterReceita[5].ToString(), drObterReceita[6].ToString(), drObterReceita[7].ToString());
catch (Exception ex)
Console.Write("Algo correu mal no método" + ex.ToString());
finally
conn.closeConnection();
return dtbReceitaPesquisada;
感谢您的帮助!
【问题讨论】:
您的代码会创建一个 nvarchar 参数并将其添加到命令中。您的 TVP 参数永远不会被添加或使用。 感谢 SMor 的输入!发现得好。但是,即使添加了参数,它仍然无法正常工作。该页面不显示任何内容。Filtros
!= Filters
param.Direction = ParameterDirection.Input;
你也应该用using
来处理连接、命令和阅读器对象
你是对的@AlexanderPetrov。那是错误的,但在写这篇文章时确实是一个错字。类型表和类型名称具有相同的名称。不过谢谢!
【参考方案1】:
正如@Alexander Petrov 正确指出的那样,您正在声明一个名为 dbo.filters 的表类型
CREATE TYPE dbo.Filters AS TABLE
但在存储过程定义中,您传递的是 dbo.filtros 类型的表变量
ALTER PROCEDURE [dbo].[uspPesquisarReceita] (@TVP dbo.Filtros READONLY)
它应该是 dbo.filters 类型。
此外,在不带括号“ ( ) ”的 where 子句中同时使用 AND 和 OR 运算符时,请务必小心,因为 SQL 中 AND 优先于 OR,因此您的预期条件可能不会给您预期的结果。
让我解释一下,下面是你用过的地方
WHERE R.IDEstado = 1 AND C.NomeCategoria IN (SELECT Categoria FROM @TVP) OR DF.Dificuldade IN (SELECT Dificuldade FROM @TVP) OR D.Duracao IN (SELECT Duracao FROM @TVP)
如果您运行查询,您将在结果集中看到 R.IDEstado = 1 和 C.NomeCategoria 的值来自 @TVP 中的 Categoria 列的值,这两个都必须为真。 评估此 AND 后,将评估其他 OR 条件。
但是,您可能希望您的结果符合第一个条件
R.IDEstado = 1
强制为真,并且任何一个或多个条件来自
C.NomeCategoria IN (SELECT Categoria FROM @TVP) OR DF.Dificuldade IN (SELECT Dificuldade FROM @TVP) OR D.Duracao IN (SELECT Duracao FROM @TVP)
应该是正确的,但是如上所述,您并没有从您的查询中清楚地得到它。
所以你应该使用下面的 where,括号中的所有 OR 条件:
WHERE R.IDEstado = 1 AND (C.NomeCategoria IN (SELECT Categoria FROM @TVP) OR DF.Dificuldade IN (SELECT Dificuldade FROM @TVP) OR D.Duracao IN (SELECT Duracao FROM @TVP))
注意:您可能在查询中使用了 AND 和 OR 条件作为缩进,我只是在解释在 where 子句中使用 AND 和 OR 条件而不带括号的含义,这可能会或可能不会影响您的情况。
【讨论】:
嗨@PankajSanwal!谢谢你的长帖。事实上,在我写这篇文章时,Filtros vs dbo.Filters 是我的一个错字。这两个有相同的名字。我已经在 SQL 中尝试过你的建议,这实际上很有意义,这正是我想要的,但我仍然没有得到任何结果。还有其他想法吗?【参考方案2】:更新:我解决了我的问题。问题是我在用户单击搜索按钮后从复选框中检索值并将它们放入 DataTable 中。
但是,当用户单击搜索按钮时,它会将他重定向到不同的页面。在显示搜索结果的此页面中,我正在调用根据所选复选框列表选项填充我的 DataTable 的方法。但由于我将他重定向到不同的页面,回发使我的 DataTable 与 checkboxlist 值完全无用。
相反,我将 DataTable 分配给 Session 变量,并在重定向后在新页面中调用它。像魅力一样工作!谢谢大家。
【讨论】:
以上是关于将DataTable传递给存储过程中的表值参数不起作用[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JDBC 将表值参数(类数组参数)传递给 Microsoft SQL Server 2008 R2 中的存储过程? [复制]