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

时间:2019-05-22 19:04:57

标签: sql-server tsql stored-procedures

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

但是,由于某些原因,EXEC行会按预期从存储过程中返回INT,但是当它无法将其值分配给@eventId变量时。

DECLARE @eventId INT
EXEC @eventId = sp_formCreateEventID @patientId, @programId, @clinicianId, @formId, @phaseTypeId, @draft, @dataCollectionDate, NULL
SELECT @eventId

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'

enter image description here

我在做什么错了?

1 个答案:

答案 0 :(得分:5)

您需要在过程底部返回一个回车。

RETURN @NewEventID

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

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

BEGIN

SET NOCOUNT ON

RETURN 333

SET NOCOUNT OFF

END
GO

Declare @MyValue INT
EXEC @MyValue = [dbo].[uspExampleOne]  111
SELECT '@MyValueHere' = @MyValue 

结果:

@MyValueHere
333

但是更好的IMHO设计是使用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

Declare @MyValue INT
Declare @OutParameterTwo INT

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

Select '@OutParameterTwoHere' = @OutParameterTwo

输出

@MyValueHere
333
@OutParameterTwoHere
444

以下显示了我对使用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

及其调用

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

并输出

@OutParameterTwoHere    @OutParameterThreeHere
444                     Better Design With Output Parameters.  Not stuck with 1 return-value or data-type