存储过程生成 msg 512 子查询返回超过 1 个值
Posted
技术标签:
【中文标题】存储过程生成 msg 512 子查询返回超过 1 个值【英文标题】:stored procedure generating msg 512 Subquery returned more than 1 value 【发布时间】:2021-07-09 19:03:15 【问题描述】:在 Sql Server 2019 中我得到了
msg 512 子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。
在几个地方,第一个在本节中。
IF (SELECT Job FROM [PRODUCTION].[dbo].[Job] WHERE Part_Number = @PN) is null
SELECT @Job='NOTHING'
ELSE
SELECT @Job = (SELECT Job FROM [PRODUCTION].[dbo].[Job] WHERE Status_Date = (SELECT
Max(Status_Date) FROM [PRODUCTION].[dbo].[Job] WHERE Part_Number = @PN AND Status =
'Closed'))
我可以自己运行查询并且总是只得到一个结果。我已经尝试使用TOP 1
进行查询,但仍然得到消息 512。
【问题讨论】:
SELECT Max(Status_Date) ...
总是只得到一个结果。 SELECT Job FROM [PRODUCTION].[dbo].[Job] WHERE Status_Date = (...)
,不一定。它也是您设计中的子查询。
我打赌将top(1)
添加到if (select job
将解决它。
如果您在互联网上搜索该消息,您会发现很多关于为什么会发生此错误以及如何修复(甚至避免)它的讨论。但您似乎有一个常见的“组内第一”查询,而采用非常不同的方法会更合适。
我已经尝试使用 TOP 1 并且仍然得到错误。 Max(Status_Date) 只返回一个值
错误将来自您的第一个if
,而不是else
; else 中的 select
是否返回许多行都没有关系,分配给 @job
是完全合法的,但是 if(many rows) is null
是不行的。
【参考方案1】:
您的代码中有两个相同的逻辑缺陷。您知道 IF 语句是一个问题,因为它已经被指出。所以通过替换来避免它:
IF (SELECT Job FROM [PRODUCTION].[dbo].[Job] WHERE Part_Number = @PN) is null
SELECT @Job='NOTHING'
与
if not exists (select * from dbo.Job where Part_Number = @PN)
set @Job = 'NOTHING';
注意更好的做法。删除了数据库名称,因为连接应该确定这一点。删除方括号,因为它们不是必需的。使用 SET 分配标量值而不是 SELECT。语句终止符。等等。
附加错误是在用于检索作业值的选择语句中。去除多余的绒毛进行分配,你有:
SELECT Job FROM [PRODUCTION].[dbo].[Job]
WHERE Status_Date =
(SELECT Max(Status_Date)
FROM [PRODUCTION].[dbo].[Job]
WHERE Part_Number = @PN AND Status = 'Closed'
)
这里的子查询确实会为您想要的零件编号和状态选择一行。但是,您只选择一个日期,并且在 Status_Date 列中可能(并且显然是)许多行具有该特定日期。您没有将外部查询限制为适当的 part_number - 这可能会也可能不会解决您的问题(因为我不知道您的架构)。
因此,我建议您搜索我在 cmets 中使用的术语,并使用 row_number 方法访问“第一行”(实际上是降序排列的最后一行),而不是这种容易出错的方法。
为了完整起见,您可以将作业更改为:
set @Job = (top 1 Job from dbo.Job
where Part_Number = @PN and Status = 'Closed' order by Status_Date desc);
这也可能“避免”这个问题,但我不能在不了解您的架构的情况下说。据推测,许多工作可以具有相同的 Part_Number,所以我认为这里缺少一些东西。
【讨论】:
【参考方案2】:使用exists
尝试以下反转逻辑
if exists (select * from dbo.job where part_number = @PN)
select @job= (....)
else
select @Job='NOTHING'
【讨论】:
以上是关于存储过程生成 msg 512 子查询返回超过 1 个值的主要内容,如果未能解决你的问题,请参考以下文章
子查询返回的值不止一个.当子查询跟随在 =,!=,<,<=,>,>= 之后,或子查询用作
服务器: 消息 512,级别 16,状态 1,行 1 子查询返回的值多于一个。