子查询 returns 多个值?
Subquery returns more than one value?
我正在尝试使用我编写的存储过程,它应该在“项目”table 中创建一个新项目。它还会检查“已保存项目”table 中是否存在具有相同 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 服务器的新手,如有任何帮助,我们将不胜感激。
请使用 IS NULL
比较 NULL
值,如下所示:
IF @save_id IS NULL
或
IF @save_id IS NOT NULL
尝试改变这个
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
到
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid = '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
编辑:包括显式角色访问。
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 )
END
更新:
USE [BugMate_DB]
GO
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
BEGIN
SET NOCOUNT ON;
DECLARE @err INT = 0;
DECLARE @output TABLE ( project_number INT );
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
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
)
OUTPUT inserted.project_number INTO @output
VALUES (
@project_name, @date_started, @project_description, @project_status, @project_active, @next_iteration_date, @created_by_userid, @project_leader_id
);
-- Capture error value.
SET @err = @@ERROR;
IF @err <> 0
BEGIN
RAISERROR ( 'Project creation insert failed.', 16, 1 );
END
ELSE
BEGIN
IF @save_id IS NULL
BEGIN
IF EXISTS ( SELECT * FROM saved_project WHERE save_id IS NULL )
BEGIN
DELETE FROM saved_project WHERE save_id IS NULL;
END
END
END
END
IF @err <> 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 @output )
);
END
END
我以前没见过这种类型的查询
INSERT INTO project_member(userid, project_number)
VALUES (@created_by_userid,
(SELECT project_number FROM project WHERE created_by_userid = @created_by_userid))
我会做任何一个
INSERT INTO project_member(userid, project_number)
VALUES (@created_by_userid, @project_id)
如果我只是插入 2 个值。
如果插入很多值,我会 SELECT
而不是 VALUES
。
如果我插入的值可能多于 1 行:
INSERT INTO project_member(userid, project_number)
SELECT created_by_userid, project_number FROM project
WHERE created_by_userid = @created_by_userid
我只是猜测,因为那是关于第 46 行的内容
此外,sacse 所说的 IF (@save_id IS NULL)
也许某处有答案
我正在尝试使用我编写的存储过程,它应该在“项目”table 中创建一个新项目。它还会检查“已保存项目”table 中是否存在具有相同 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 服务器的新手,如有任何帮助,我们将不胜感激。
请使用 IS NULL
比较 NULL
值,如下所示:
IF @save_id IS NULL
或
IF @save_id IS NOT NULL
尝试改变这个
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
到
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid = '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
编辑:包括显式角色访问。
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 )
END
更新:
USE [BugMate_DB]
GO
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
BEGIN
SET NOCOUNT ON;
DECLARE @err INT = 0;
DECLARE @output TABLE ( project_number INT );
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = @created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
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
)
OUTPUT inserted.project_number INTO @output
VALUES (
@project_name, @date_started, @project_description, @project_status, @project_active, @next_iteration_date, @created_by_userid, @project_leader_id
);
-- Capture error value.
SET @err = @@ERROR;
IF @err <> 0
BEGIN
RAISERROR ( 'Project creation insert failed.', 16, 1 );
END
ELSE
BEGIN
IF @save_id IS NULL
BEGIN
IF EXISTS ( SELECT * FROM saved_project WHERE save_id IS NULL )
BEGIN
DELETE FROM saved_project WHERE save_id IS NULL;
END
END
END
END
IF @err <> 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 @output )
);
END
END
我以前没见过这种类型的查询
INSERT INTO project_member(userid, project_number)
VALUES (@created_by_userid,
(SELECT project_number FROM project WHERE created_by_userid = @created_by_userid))
我会做任何一个
INSERT INTO project_member(userid, project_number)
VALUES (@created_by_userid, @project_id)
如果我只是插入 2 个值。
如果插入很多值,我会 SELECT
而不是 VALUES
。
如果我插入的值可能多于 1 行:
INSERT INTO project_member(userid, project_number)
SELECT created_by_userid, project_number FROM project
WHERE created_by_userid = @created_by_userid
我只是猜测,因为那是关于第 46 行的内容
此外,sacse 所说的 IF (@save_id IS NULL)
也许某处有答案