在SQL Server 2012或更高版本中运行以下命令
CREATE TABLE TestTable1
(
Dim varchar(500),
Measure money,
PRIMARY KEY (Dim)
)
GO
CREATE TABLE TestTable2
(
Dim varchar(500),
Measure money,
PRIMARY KEY (Dim)
)
GO
CREATE PROCEDURE [dbo].[usp_InnerSp]
(
@Sql varchar(max)
)
AS
BEGIN
EXEC(@sql)
END
GO
CREATE PROCEDURE [dbo].[usp_ParentSp]
AS
BEGIN
DECLARE @sql VARCHAR(MAX);
SET @sql = 'SELECT t1.* FROM TestTable1 t1 INNER JOIN TestTable2 t2 ON t1.Dim = t2.Dim'
EXEC [dbo].[usp_InnerSp] @sql
WITH RESULT SETS (
(
[Dim] VARCHAR(500),
[Measure] MONEY
)
);
END
GO
在C#中创建一个控制台应用程序
static void Main(string[] args)
{
using (SqlConnection connection = new SqlConnection(@"Data Source=.\SQL2014;Initial Catalog=AdventureWorksDW2012;Integrated Security=SSPI;"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("usp_ParentSp", connection))
{
command.CommandType = CommandType.StoredProcedure;
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
}
}
}
}
运行代码时,会出现以下System.Data.SqlClient.SqlException
异常:
EXECUTE语句失败,因为其WITH RESULT SETS子句为结果集编号1指定了2个列,但该语句在运行时发送了3个列。
我希望.Net能够运行存储过程,即使它无论出于何种原因都无法检测到主键。
问题:你会推荐什么?这是.Net或SQL Server中的错误吗?
答案 0 :(得分:3)
为什么在选择[Dim]列(CommandBehavior.KeyInfo
)时甚至使用t1.*
?
要么根本不使用CommandBehavior.KeyInfo
(最佳方法)。
或更改
WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY));
到
WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY, [PrimaryKey] VARCHAR(500)));
(最差的解决方案)。
或将t1.*
更改为t1.Measure
和
WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY));
到
WITH RESULT SETS (([Measure] MONEY, [PrimaryKey] VARCHAR(500)));
(优于2但仍然比1差)。
答案 1 :(得分:0)
为什么要使用WITH RESULT SETS
开头?该错误与无法检测PK无关;它与添加到结果集的额外列有关,因为指定了CommandBehavior.KeyInfo
,而SET NO_BROWSETABLE ON
在执行查询之前又设置了SET NO_BROWSETABLE ON;
EXEC dbo.usp_ParentSp;
。如果您运行,则SSMS中会出现相同的错误:
WITH RESULT SETS
因此该错误与.NET无关。
没有太多情况需要WITH RESULT SETS
,并且显示的示例代码绝对不是其中之一,因此我建议从EXEC
中删除SqlDataReader.GetSchemaTable()
子句。并从WITH RESULT SETS
获取结果集元数据。
此外,使用sys.dm_exec_describe_first_result_set无论如何都无济于事,因为它不支持使用动态SQL。您可以使用sp_describe_first_result_set,因为它可以使用动态SQL,但它还需要WITH RESULT SETS
子句。当然,使用{{1}}最终并没有太大的好处,因为“is_part_of_unique_key”字段为NULL(至少在您的测试用例方面)。