在这个 SQL 存储过程中真的需要临时 table 吗?

Is a temp table really necessary in this SQL stored procedure?

在查看我参与的项目中的一些现有存储过程时,我看到了这样的事情:

declare @tmpTable Table (
    ID bigint,
    patientID   uniqueidentifier,
    resultDate  datetime,
    resultParameter nvarchar(50),
    resultValue decimal(18, 6),
    resultUnit  nvarchar(50),
    pos smallint,
    minpos smallint,
    maxpos smallint
)

if (@patientID is not null)
    begin
        declare @minpos smallint = 0;
        declare @maxpos smallint = 0;

        select 
            @minpos = min(a.pos),
            @maxpos = max(a.pos)
        from tbl_patientBiometricResults a (nolock)
        where a.patientID = @patientID

        insert into @tmpTable
        (
            ID,
            patientID,
            resultDate,
            resultParameter,
            resultValue,
            resultUnit,
            pos,
            minpos,
            maxpos
        )
        select 
            a.ID, 
            a.patientID,
            a.resultDate,
            a.resultParameter,
            a.resultValue,
            a.resultUnit,
            a.pos,
            @minpos,
            @maxpos
        from tbl_patientBiometricResults a (nolock)
        where a.patientID = @patientID

    end

select * from @tmpTable order by pos;

这里对我来说很突出的一点是他们使用的是临时 tables,我真的看不出这种类型的存储过程有什么好处。临时 table 中没有添加新字段(没有 table 的组合),只有 tbl_patientBiometricResults table.[=14= 中可用字段的子集]

在这种情况下使用临时 table 有好处吗?


好吧,断章取义似乎有点矫枉过正,但我​​发现在某些情况下,例如涉及 SSIS,您可能需要像这样构造一个 table 变量,以便 SSIS 包识别元数据存储过程 returns。不过不确定这对您的情况是否重要!

正如 Sean 在评论中提到的,使用 table 变量没有任何好处。您可以轻松地以更简单的格式重写查询,如下所示:

IF (@patientID is not null)
BEGIN
    SELECT  ID, 
            patientID,
            resultDate,
            resultParameter,
            resultValue,
            resultUnit,
            pos,
            minPos, --MIN(pos) OVER (PARTITION BY NULL) /*Alternative for SQL 2012+. No need for CROSS APPLY*/
            maxPos  --MAX(pos) OVER (PARTITION BY NULL)
    FROM tbl_patientBiometricResults
    CROSS APPLY(
                    SELECT  MIN(pos) minPos,
                            MAX(pos) maxPos
                    FROM    tbl_patientBiometricResults
                    WHERE   patientID = @patientID
                )
    WHERE patientID = @patientID
    ORDER BY pos;
END