子查询 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)

也许某处有答案