OUTPUT INSERTED Id/SCOPE_IDENTITY() 在 C# (ASP.NET Core Razor Pages) SQL 查询中返回 null,在 SQL Server Mana

Posted

技术标签:

【中文标题】OUTPUT INSERTED Id/SCOPE_IDENTITY() 在 C# (ASP.NET Core Razor Pages) SQL 查询中返回 null,在 SQL Server Management Studio 中工作正常【英文标题】:OUTPUT INSERTED Id/SCOPE_IDENTITY() returns null in C# (ASP.NET Core Razor Pages) SQL query, works fine in SQL Server Management Studio 【发布时间】:2019-08-08 17:29:38 【问题描述】:

我有以下参数化 SQL 查询,它将数据插入到表中,获取新行的(自动递增的)Id 值,然后将该新值插入到另一个表中:

DECLARE @engId_newtable TABLE(engId INT); 
DECLARE @engId_new INT; 

INSERT INTO eng (locationTypeId, engNumb, projectId, engTypeId, capacity, cylNo, employeeId, bore, stroke, crankOffset, rodLength, cr, crankThrow, pinOffset, engDesc) 
OUTPUT INSERTED.engId INTO @engId_newtable 
SELECT a.locationTypeId, @engNumb, b.projectId, c.engTypeId, @capacity, @cylNo, d.employeeId, @bore, @stroke, @crankOffset, @rodLength, @cr, @crankThrow, @pinOffset, @engDesc 
FROM dbo.locationType AS a,dbo.project AS b,dbo.engType AS c,dbo.employees AS d 
WHERE a.locationType = @locationType AND b.projectCode = @projectCode AND b.engineType = @engineType AND c.engType = @engType AND d.userName = @userName ;

SELECT @engId_new = engId FROM @engId_newtable; 

INSERT INTO oil (engId, oilQuantity, oilTypeId) 
SELECT @engId_new, @oilQuantity, a.oilTypeId 
FROM dbo.oilType AS a 
WHERE a.oilManufacturer = @oilManufacturer AND a.oilRange = @oilRange AND a.oilGrade = @oilGrade ;

该查询在 SQL Server Management Studio (SSMS) 中执行时运行良好,但是当我尝试使用我的 ASP.NET Core C# (Razor Pages) 项目运行它时,它失败并出现以下错误:

System.Data.SqlClient.SqlException: '无法将值 NULL 插入 列'engId',表'TestEng.dbo.oil';列不允许空值。 插入失败。声明已终止。'

所以看来OUTPUT INSERTED 命令不起作用。我也尝试过使用SELECT @engId_new = SCOPE_IDENTITY(),甚至@@IDENTITY,但它们也返回null并给出相同的错误。

我在项目的其他领域也有类似的查询(使用OUTPUT INSERTED),它们运行良好。直到今天早些时候,当我们更改运行 SQL 数据库的服务器时,此查询也正常工作 - 也许我需要更改一些数据库/表设置?

非常感谢任何帮助,我真的很茫然。谢谢。


编辑:显示查询的执行方式

查询是以编程方式构建的 - 我知道查询构建函数可以正常工作,因为我的所有其他查询都可以正常工作 - 我尝试执行的查询与此处显示的完全相同(它由查询构建器作为单个字符串返回):

"DECLARE @engId_newtable TABLE(engId INT); DECLARE @engId_new INT; INSERT INTO eng (locationTypeId, engNumb, projectId, engTypeId, capacity, cylNo, employeeId, bore, stroke, crankOffset, rodLength, cr, crankThrow, pinOffset, engDesc) OUTPUT INSERTED.engId INTO @engId_newtable SELECT a.locationTypeId, @engNumb, b.projectId, c.engTypeId, @capacity, @cylNo, d.employeeId, @bore, @stroke, @crankOffset, @rodLength, @cr, @crankThrow, @pinOffset, @engDesc FROM dbo.locationType AS a,dbo.project AS b,dbo.engType AS c,dbo.employees AS d WHERE a.locationType = @locationType AND b.projectCode = @projectCode AND b.engineType = @engineType AND c.engType = @engType AND d.userName = @userName ;SELECT @engId_new = engId FROM @engId_newtable; INSERT INTO oil (engId, oilTypeId) SELECT @engId_new, a.oilTypeId FROM dbo.oilType AS a WHERE a.oilManufacturer = @oilManufacturer AND a.oilRange = @oilRange AND a.oilGrade = @oilGrade ;"

查询执行函数,从razor页面模型调用,查询和连接作为参数传递:

public void ExecuteVoid(SqlConnection con, string query, List<SqlColumn> columns, List<SqlFilter> filters)
    
        SqlCommand cmd = new SqlCommand(query, con);
        Parameterize(cmd, columns, filters);
        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();
    

Parameterize 函数只是将所有相关参数添加到查询中。同样,就像查询构建器函数一样,我知道它可以工作,因为我的所有其他查询都按预期执行。


编辑 2:SQL Server Profiler

下图显示了我可以在 SQL Server Profiler 中看到的与该查询相关的所有事件:

查询的所有部分都按预期写出,所有参数都存在,但查询仍然失败。

【问题讨论】:

你可以在 c# 中做到这一点,很可能你只是弄错了。显示代码? SQL 探查器显示哪些查询(SP 语句)和异常? @Arvo SQL 分析器显示事件类 RPC:Completed 的单个事件,文本数据为 exec sp_executesql,然后是查询。编辑:也得到异常Cannot insert the value NULL into column 'engId', table 'TestEng.dbo.oil'; column does not allow nulls. INSERT fails. 在分析器中选择更多事件,例如异常、sp 语句已启动、sp 语句已完成 - 这样您应该会看到更多。并且 - 您在探查器中的查询看起来与应有的完全一样吗? @Arvo 查看我对该问题的第二次编辑 【参考方案1】:

我发现了问题!我在我的第一个查询中使用HttpContext.Session.GetString 来获取WHERE 子句的值(到eng 表)。我在代码的其他地方更改了字符串的名称,却忘记在查询中更改它。所以,这个问题实际上与 SQL 无关。 我可以说 SQL 服务器探查器对于查找此错误至关重要,因此,如果您在使用 Visual C# 参数化 sql 查询时遇到问题,请查看那里的查询,您可能会突出一些未发现的问题。

【讨论】:

以上是关于OUTPUT INSERTED Id/SCOPE_IDENTITY() 在 C# (ASP.NET Core Razor Pages) SQL 查询中返回 null,在 SQL Server Mana的主要内容,如果未能解决你的问题,请参考以下文章

latex生成pdf 出现missing$ inserted

SQL执行并返回执行前/后结果

G.Finding the Radius for an Inserted Circle 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛

mongodb分页查询,排序

SQL Inserted和deleted详解

使这个查询更快