如何为存储过程的执行分配变量?

Ali*_*uri 1 t-sql sql-server stored-procedures

我想将sp_formCreateEventID存储过程返回的值赋给新变量(@eventId)。我最初以为是要走的路。该解决方案也符合SSMS生成的EXEC命令。

但是,由于某种原因,该EXECINT按预期从存储过程返回了a ,但是当它不能将其值分配给该@eventId变量时。

DECLARE @eventId INT
EXEC @eventId = sp_formCreateEventID @patientId, @programId, @clinicianId, @formId, @phaseTypeId, @draft, @dataCollectionDate, NULL
SELECT @eventId
Run Code Online (Sandbox Code Playgroud)

sp_formCreateEventID (不要恨我,我没有写这个……):

ALTER PROCEDURE  [dbo].[sp_formCreateEventID]
    @PatientID int,
    @ProgramID int,
    @ClinicianID int,
    @FormID int,
    @PhaseTypeID int,
    @Draft varchar(5),
    @CompletedDate varchar(40),
    @UserID int = null
AS
BEGIN


    IF @CompletedDate = ''
        SET @CompletedDate = NULL

    --for some forms such as Clinical Input - Initial, there should only have one form filled for a youth. If that is the case and the event has existed, just return that one.
    DECLARE @EID int
    SET @EID =  dbo.fn_GetExistingOnlyOneEventID(@PatientID, @ProgramID, @FormID)
    PRINT @eid
    IF @EID <> -99
    BEGIN
        SELECT 
        @EID AS 'EventID'
        RETURN
    END



    DECLARE @TxCycleID int
    DECLARE @TxCyclePhaseTypeID int
    DECLARE @TxCyclePhaseID int
    DECLARE @seqNum int
    DECLARE @NewEventID INT

    --if there is no cycle for this patient for this program, then create one.
    IF NOT EXISTS (SELECT * FROM TxCycle WHERE PatientID = @PatientID AND ProgID = @ProgramID)
    BEGIN
        INSERT INTO TxCycle
        (OpenDate, PatientID, ProgID)
        VALUES
        (GETDate(), @PatientID, @ProgramID)
    END

    SELECT 
        @TxCycleID = Max(TxCycleID)
    FROM TxCycle
    WHERE
        PatientID = @PatientID AND 
        ProgID = @ProgramID

    --In this cycle, for the current phase type, get the max seq number
    IF EXISTS (SELECT * FROM TxCyclePhase WHERE TxCycle = @TxCycleID)
    BEGIN
        SELECT 
            @seqNum = MAX(SeqNum)
        FROM
            TxCyclePhase
        WHERE
            TxCycle = @TxCycleID

        SET @seqNum = @seqNum + 1
    END
    ELSE
    BEGIN
        SET @seqNum = 1
    END

    PRINT 'New Seq Num: ' + CONVERT(Varchar(5),@seqNum)

    --greate a new seq number under the same phase
    INSERT INTO TxCyclePhase
    (Type, seqNum, TxCycle)
    VALUES
    (@PhaseTypeID, @seqNum, @TxCycleID)

    --get the new ID, this will be used for the Event
    SELECT
        @TxCyclePhaseID =  Max(TxCyclePhaseID)
    FROM
        TxCyclePhase

    DECLARE @isFinal int
    IF @Draft = 'Yes'
    BEGIN
        SET @isFinal = 0
    END
    ELSE
    BEGIN
        SET @isFinal = 1
    END

    IF EXISTS(SELECT * FROM LoginPassword WHERE ClinID = @ClinicianID AND AccessID IN (1,3))
    BEGIN
        IF NOT EXISTS (SELECT * FROM ClinPat WHERE ClinID = @ClinicianID AND PatientID = @PatientID)
        BEGIN
            INSERT INTO 
                ClinPat
            (ClinID, PatientID)
            VALUES
            (@ClinicianID, @PatientID)
        END
    END

    INSERT INTO FormPat
    (PatientID, ClinID, FormID, TxCyclePhase, Date, Final, DataCollectionDate)
    VALUES
    (@PatientID, @ClinicianID, @FormID, @TxCyclePhaseID, GETDATE(), @isFinal, @CompletedDate)



    SELECT @NewEventID = Scope_Identity()
    SELECT @NewEventID AS 'EventID'
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我究竟做错了什么?

gra*_*der 5

您需要在过程的底部返回。

RETURN @NewEventID
Run Code Online (Sandbox Code Playgroud)

这是一个完整但简单的示例:

CREATE PROCEDURE [dbo].[uspExampleOne] 
@Parameter1 INT
AS

BEGIN

SET NOCOUNT ON

RETURN 333

SET NOCOUNT OFF

END
GO
Run Code Online (Sandbox Code Playgroud)

Declare @MyValue INT
EXEC @MyValue = [dbo].[uspExampleOne]  111
SELECT '@MyValueHere' = @MyValue 
Run Code Online (Sandbox Code Playgroud)

结果:

@MyValueHere
333
Run Code Online (Sandbox Code Playgroud)

但是更好的恕我直言的设计是使用OUTPUT变量:

为什么?

当您需要第二个输出时会发生什么?当所需的值不是INT时会发生什么?

ALTER PROCEDURE [dbo].[uspExampleOne] 
@Parameter1 INT ,
@OutParameter2 INT OUT
AS

BEGIN

SET NOCOUNT ON

Select @OutParameter2 = 444

RETURN 333

SET NOCOUNT OFF

END
GO
Run Code Online (Sandbox Code Playgroud)

Declare @MyValue INT
Declare @OutParameterTwo INT

EXEC @MyValue = [dbo].[uspExampleOne]  111 , @OutParameterTwo OUT
SELECT '@MyValueHere' = @MyValue 

Select '@OutParameterTwoHere' = @OutParameterTwo
Run Code Online (Sandbox Code Playgroud)

输出量

@MyValueHere
333
@OutParameterTwoHere
444
Run Code Online (Sandbox Code Playgroud)

下面显示了我对具有OUTPUT参数的“未来打样”的含义

ALTER PROCEDURE [dbo].[uspExampleOne] 
@Parameter1 INT ,
@OutParameter2 INT OUT,
@OutParameter3 VARCHAR(128) OUT
AS

BEGIN

SET NOCOUNT ON

Select @OutParameter2 = 444
Select @OutParameter3 = 'Better Design With Output Parameters.  Not stuck with 1 return-value or data-type'

RETURN 0 /* everything went ok */

SET NOCOUNT OFF

END
GO
Run Code Online (Sandbox Code Playgroud)

和它的电话

Declare @MyValue INT
Declare @OutParameterTwo INT
Declare @OutParameterThree VARCHAR(128)

EXEC @MyValue = [dbo].[uspExampleOne]  111 , @OutParameterTwo OUT , @OutParameterThree OUT
SELECT '@MyValueHere' = @MyValue 

Select '@OutParameterTwoHere' = @OutParameterTwo , '@OutParameterThreeHere' = @OutParameterThree
Run Code Online (Sandbox Code Playgroud)

和输出

@OutParameterTwoHere    @OutParameterThreeHere
444                     Better Design With Output Parameters.  Not stuck with 1 return-value or data-type
Run Code Online (Sandbox Code Playgroud)

  • 我个人更喜欢使用OUTPUT参数作为返回值。在这种情况下,它们都可以,但是返回值限于int,并且旨在指示执行状态,而不是返回值。两种方法的优秀示例。 (2认同)
  • @Sean。我完全同意。当他们(或其他开发人员)在gitErDone“ return”上使用OUTPUT变量时,您将始终感激您自己。当您需要第二个输出时会发生什么?当所需的值不是INT时会发生什么?与“返回”相比,“输出”要好得多。除了“搞定”。他们更喜欢轻松自在。 (2认同)