Подзапрос возвращает более одного значения? - PullRequest
0 голосов
/ 08 июля 2020

Я пытаюсь использовать написанную мной хранимую процедуру, которая должна создать новый проект в таблице «Project». Он также проверяет, есть ли в таблице «Сохраненный проект» сохраненный проект с тем же идентификатором, и удаляет его после успешного создания.

Также предполагается, что переданный 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 Сервер, поэтому любая помощь будет принята с благодарностью.

Ответы [ 3 ]

0 голосов
/ 08 июля 2020

Попробуйте изменить это

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
0 голосов
/ 08 июля 2020

Я раньше не видел этот тип запроса

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.

Если бы я вставлял, возможно, более одной строки значений:

INSERT INTO project_member(userid, project_number)
SELECT created_by_userid, project_number FROM project
WHERE created_by_userid = @created_by_userid

Я просто догадываюсь, так как это примерно линия 46

Кроме того, что Саксе сказал о IF (@save_id IS NULL)

, возможно, там где-то есть ответ

0 голосов
/ 08 июля 2020

Сравните значения NULL, используя IS NULL, как показано ниже:

IF @save_id IS NULL

или

IF @save_id IS NOT NULL
...