【发布时间】:2020-07-08 17:30:41
【问题描述】:
我正在尝试使用我编写的存储过程,它应该在“项目”表中创建一个新项目。它还会检查“已保存项目”表中是否存在具有相同 ID 的已保存项目,并在成功创建后将其删除。
还要检查传递的user_id是否有实际创建项目的权限(即不是标准用户)。
这是存储过程:
USE [BugMate_DB]
GO
/****** Object: StoredProcedure [dbo].[create_project] Script Date: 2020-07-08 11:05:30 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[create_project]
@project_name NVARCHAR(40),
@date_started DATETIME,
@project_description NVARCHAR(400),
@project_status NVARCHAR(40),
@project_active BIT,
@next_iteration_date DATETIME,
@created_by_userid INT,
@project_leader_id INT,
@save_id INT = NULL
AS
SET NOCOUNT ON
BEGIN
IF (SELECT TOP 1 roleid from user_info WHERE userid = @created_by_userid) = 'SDU'
BEGIN
RAISERROR ('User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1)
END
ELSE
BEGIN
INSERT INTO project(project_name, date_started, project_description, project_status, project_active, next_iteration_date, created_by_userid, project_leader_id)
VALUES (@project_name, @date_started, @project_description, @project_status, @project_active, @next_iteration_date, @created_by_userid, @project_leader_id)
IF @@ERROR <> 0
BEGIN
RAISERROR('Project creation insert failed.', 16, 1)
END
ELSE
BEGIN
IF @save_id != NULL
BEGIN
IF EXISTS (SELECT TOP 1 save_id FROM saved_project WHERE save_id = @save_id)
BEGIN
DELETE FROM saved_project WHERE save_id = @save_id
END
END
END
END
IF @@ERROR <> 0
BEGIN
RAISERROR('Error creating project', 16, 1)
END
ELSE
BEGIN
INSERT INTO project_member(userid, project_number)
VALUES (@created_by_userid, (SELECT project_number FROM project WHERE created_by_userid = @created_by_userid))
END
END
问题是我在执行我的 SP 时收到此错误:
消息 512,级别 16,状态 1,过程 create_project,第 48 行 子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。
我不确定为什么我的任何子查询都会返回多个值。
这是我试图传递的值:
USE [BugMate_DB]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[create_project]
@project_name = N'Test',
@date_started = N'12/25/2015 12:00:00 AM',
@project_description = N'This is a test.',
@project_status = N'InDevelopment',
@project_active = 1,
@next_iteration_date = N'12/25/2015 12:00:00 AM',
@created_by_userid = 19,
@project_leader_id = 19,
@save_id = NULL
SELECT 'Return Value' = @return_value
GO
我曾尝试使用“TOP 1”来尝试获取单个值,但它似乎不是我想要的。
据我所知,这也不是连接问题。
我是 SQL Server 新手,因此我们将不胜感激。
【问题讨论】:
-
过程中的最后一条语句就是问题所在。并且评论“......似乎不是我要寻找的”对你来说是有意义的,对其他人来说没有意义。您要使用的逻辑很可能是不正确的——随着时间的推移,同一个人肯定可以创建多个项目。并且您不能使用相等运算符将任何内容与 NULL 进行比较。为此,您必须使用 ISNULL。
-
读心术 - project_number 是一个身份列吗?
-
还有另一个缺陷 - 使用没有 order by 子句的 TOP 只会限制结果集中的行数。它不保证选择任何特定行。您应该将其替换为 EXISTS - 但这在逻辑上也可能不正确。
-
project_number 是标识列。我应该澄清一下,同一个人可以创建多个项目,检查“ IF (SELECT TOP 1 roleid from user_info WHERE userid = @created_by_userid) = 'SDU'”是为了验证用户的权限级别。感谢您的帮助@SMor
标签: sql sql-server database stored-procedures subquery