使用临时表创建函数时出错

Posted

技术标签:

【中文标题】使用临时表创建函数时出错【英文标题】:Error creating function with temporary tables 【发布时间】:2021-12-13 02:14:44 【问题描述】:

我正在创建一个包含临时表的函数,将函数与临时表一起使用对我来说有点困难,我完全不知道函数中是否允许它,因为我是新函数.

我要创建的函数如下:

CREATE FUNCTION FunctionTest (
    @Anio   int=null,
    @Mes    int=Null,
    @Meses  int=6

)
RETURNS @Tabla TABLE (
    AnioMes INT,
    Viaje VARCHAR(30),
    IdPorte INT,
    Carga VARCHAR(20),
    Peso numeric(32, 16)
)
AS
BEGIN

    Declare @AnioMes    varchar(8),
            @AnioMes6   varchar(8)

    if @Anio is null
        Select  @Anio   = YEAR(GETDATE()),
                @Mes    = MONTH(GETDATE())

    Select  @AnioMes    = (case when @Mes=12 then @Anio+1 else @Anio end *100 + Case when @Mes=12 then 1 else @Mes+1 end)*100 + 1
    Select  @AnioMes6   = convert(varchar(8), DATEADD(mm, -@Meses, @AnioMes), 112 )

    INSERT INTO @Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)   
    SELECT  year(cpsj.Delivery)*100 + MONTH(cpsj.Delivery) as AnioMes,  
            tr.TId as Viaje,
            cpsj.PId as IdPorte,            
            CASE WHEN tr.Load = 1 THEN 'CARGADO'
                WHEN tr.Load = 2 THEN 'VACIO'
            END  as Carga, 
            cpsj.Weight as Peso,            
    into #Temp
    FROM BDNEW.dbo.CENPACKSTOREJOIN cpsj 
    inner join TRANS tr on cpsj.ipId = tr.ipId
    inner join OPERA oper on tr.OId = oper.OId  
    WHERE   cpsj.Id = 'ID001'
    AND     tr.Area = 'lost'
    AND     tr.Status       = 2
    GROUP BY cpsj.Delivery, cpsj.IName
    ORDER BY cpsj.ipId

    if @AnioMes6 < '20160101'
        insert #Temp
        SELECT  Year(cpsj.Delivery)*100 + MONTH(cpsj.Delivery) as AnioMes,  
                tr.TId as Viaje,
                cpsj.PId as IdPorte,        
                CASE WHEN tr.Load = 1 THEN 'CARGADO'
                    WHEN tr.Load = 2 THEN 'VACIO'
                END  as Carga, 
                cpsj.Weight as Peso,                
        FROM BDOLD.dbo.CENPACKSTOREJOIN cpsj 
        inner join TRANS tr on cpsj.ipId = tr.ipId
        inner join OPERA oper on tr.OId = oper.OId
        WHERE   cpsj.Id = 'ID001'
        AND     tr.Area = 'lost'    
        AND     tr.Status       = 2
        GROUP BY cpsj.Delivery, cpsj.IName 
        ORDER BY cpsj.ipId

    Delete  #Temp
    where   viaje in (
                    select MAX(Viaje)
                    from    #Temp
                    group by IdPorte
                    having COUNT(IdPorte) > 1
                    )

    
    Select  AnioMes,
            Viaje,
            IdPorte, 
            Carga, 
            Peso, 
    from #Temp
    GROUP BY AnioMes,IdPorte Viaje, Carga, Peso
    ORDER BY AnioMes,IdPorte

RETURN 

END

如果你注意到我正在使用一个名为 #Temp 的临时表。

在尝试编译函数时出现错误消息,我收到以下错误消息:

无法从函数内访问临时表。

这就是为什么我前面提到如果你真的可以在函数中使用临时表。

感谢任何可以指导我如何处理此功能的人。

【问题讨论】:

我正试图绕过INSERT INTO @Tabla ... SELECT ... INTO #Temp ...请解释为什么你认为你需要@Tabla#Temp在这里? INSERT INTO @Tabla 是我为我的函数创建的东西,我真的不知道是否应该在那里使用它,或者我是否应该对语法进行一些修改 你应该只是INSERT INTO @Tabla,然后更新/删除@Tabla,然后你修改后@Tabla的内容就是函数返回的内容。 @AaronBertrand 您可以根据您的评论添加新答案,但要考虑到我在问题中发布的语法 @AaronBertrand 你知道you spend loads of time answering a question 和 OP 刚刚发布另一个问题,表明他们完全无视你的建议......非常伤人,TBH 【参考方案1】:

你要么使用

INSERT INTO @Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)   
SELECT  year(cpsj.Delivery)*100 ...

或者

SELECT  year(cpsj.Delivery)*100 ...
INTO #Temp
FROM...

不是两者:

INSERT INTO @Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)  
SELECT  year(cpsj.Delivery)*100 ...
INTO #Temp
FROM...

而且你不能在函数中使用临时表。

【讨论】:

如果我不使用 INSERT INTO @Table 我会收到错误消息 Invalid use of a side-effecting operator 'SELECT' within a function 这是因为您不能只选择结果集而不将其分配给变量。见:***.com/questions/13603111/…

以上是关于使用临时表创建函数时出错的主要内容,如果未能解决你的问题,请参考以下文章

flink - 创建临时表时出错

退出函数时删除临时表

ORACLE:在 dbms_redefinition 后删除临时表时出错

使用这些临时表返回选择查询的临时表创建函数

postgres - 使用提供临时表的函数创建视图

Oracle中用子查询创建临时表 并赋值数据