【问题标题】:Postgresql stored procedure temporary table variable is not a known variablePostgresql 存储过程临时表变量不是已知变量
【发布时间】:2022-01-23 22:59:53
【问题描述】:

我一直在做研究并尝试了很多不同的方法,但都没有成功。我想创建一个临时表,然后在进行一些搜索时,用一些东西填满它。我可以通过在过程中声明一个表来使用 SQL Server 来做到这一点,但是使用 Postgresql 我已经读过我需要专门创建一个临时表。

我的策略一开始只是

CREATE TEMP TABLE myTempTable
( 
    propOne bigint, 
    propTwo smallint, 
    createdAtUtc timestamp(6)
);

我什至把它移到“BEGIN”之后。在文件中我收到此错误:

错误:“myTempTable”不是已知变量
第 77 行:从 myResult 中选择 * INTO myTempTable;

接下来,当我准备好填充临时表时,我尝试创建它...

WITH some_updated_records AS 
(
    UPDATE dbTable
    SET tablePropertyStatus = 3
    WHERE tablePropertyDate < storedProcedurePropertyDate
    RETURNING *
)
CREATE TEMP TABLE myTempTable as 
(
    SELECT * 
    FROM some_updated_records
);

我仍然得到与上面相同的基本错误,但在遇到 myTempTable 变量之前出现零错误。

我绝对不是 SQL 天才(也许,最终,在你的帮助下),所以我可能做错了一些其他事情。我的全部任务是将 SQL Server 存储过程转换为 Postgresql。

我做错了什么来使临时表变量未声明?有什么特殊的方式需要提前申报吗?我在如何创建或声明临时表方面犯了错误吗?

另一种策略可能是将记录保存到类型集合中,忘记“临时表”。有没有办法在 plpgsql 中做到这一点?

更新示例

这个版本不工作。它在创建表处停止。

CREATE OR REPLACE PROCEDURE MyTestProcedure(
    p_Endpoint Varchar(256),
    p_ContentType Varchar(200),
    MaxInProcess int = NULL)

LANGUAGE plpgsql

AS $body$

DECLARE
v_UtcNow timestamp(6);
v_ExpiredProcessing timestamp(6);

BEGIN
    SELECT CURRENT_TIMESTAMP into v_UtcNow at time zone 'utc';

    WITH first_updated AS (UPDATE MyTable
        SET Status = 1
        WHERE UpdatedAtUtc < v_UtcNow
        RETURNING Id, Status, UpdatedAtUtc)
        
    CREATE TEMP TABLE IF NOT EXISTS statustable AS (SELECT Id, Status, UpdatedAtUtc FROM first_updated)

    WITH m_result AS (UPDATE MyTable
    SET Status = 3,
    WHERE ExpirationDateTimeUtc < v_UtcNow
    RETURNING Id, Status, UpdatedAtUtc)
    
    INSERT INTO statustable from m_result;
            
    DROP TABLE statustable;
    
END;
$body$

这在创建表时出错。

INE 22:  CREATE TEMP TABLE statustable as...

另一个示例类似于先创建表然后插入其中。这大概就是我搞砸的地方。如果有人没有先添加,工作解决方案将在一分钟内添加。

【问题讨论】:

  • edit您的问题并向我们展示程序的完整代码。在使用 Postgres 时,您通常不需要一个临时表开始
  • 这是公司代码。我会试一试,但需要一段时间。我想出了一个更精简的版本来解决这个问题。谢谢@a_horse_with_no_name
  • 如果你想返回一些东西,你应该使用函数而不是过程。
  • 程序的退货无效。最后我正在使用临时表执行一些工作。
  • SQL Server temporary tables as variables 在 plpgsql 中不存在。

标签: sql postgresql plpgsql


【解决方案1】:

您可以使用 CTE,但将 CTE 放在括号中以创建表。

CREATE TEMPORARY TABLE myTempTable AS (
  WITH cte_updated_records AS (
    UPDATE dbTable
    SET tablePropertyStatus = 3
    WHERE tablePropertyDate < storedProcedurePropertyDate
    RETURNING *
  )
  SELECT * FROM cte_updated_records
);

【讨论】:

  • 这很整洁。我将尝试这种或另一种方式。
  • 如果你来自 SQL Server,你不会期望它,因为 WITH 必须在外面。
【解决方案2】:

在调试时,事情可能会变得有点疯狂。我发现,经常发生的事情是我尝试了一种很好的解决方案,但我不知道如何正确实施它,所以以下方法有效。我想我忘记了 INSERT INTO 中的选择。

CREATE OR REPLACE PROCEDURE MyTestProcedure(
    p_Endpoint Varchar(256),
    p_ContentType Varchar(200),
    MaxInProcess int = NULL)

LANGUAGE plpgsql

AS $body$

DECLARE
v_UtcNow timestamp(6);
v_ExpiredProcessing timestamp(6);

BEGIN
    SELECT CURRENT_TIMESTAMP into v_UtcNow at time zone 'utc';

    CREATE TEMP TABLE status_table(  
        Id bigint,
        Status smallint,
        CreatedAtUtc timestamp(6));

    WITH first_updated AS (UPDATE MyTable
        SET Status = 1
        WHERE UpdatedAtUtc < v_UtcNow
        RETURNING Id, Status, UpdatedAtUtc)

    INSERT INTO status_table
        SELECT Id, Status, UpdatedAtUtc 
        FROM first_updated;

    WITH m_result AS (UPDATE MyTable
        SET Status = 3
        WHERE ExpirationDateTimeUtc < v_UtcNow
        RETURNING Id, Status, UpdatedAtUtc)
    
    INSERT INTO status_table
        select Id, Status, UpdatedAtUtc 
        from m_result;
            
    DROP TABLE status_table;
    
END;
$body$

【讨论】:

    【解决方案3】:

    https://www.postgresql.org/docs/14/plpgsql-statements.html#PLPGSQL-STATEMENTS-ASSIGNMENT1 请参考提示部分:

    提示请注意,这种对带有 INTO 的 SELECT 的解释是 不同于 PostgreSQL 的常规 SELECT INTO 命令,其中 INTO 目标是一个新创建的表。如果你想创建一个表 从 PL/pgSQL 函数内的 SELECT 结果中,使用语法 CREATE 表...作为选择。

    基于此,你可以这样做

    CREATE TEMP TABLE  statustable AS (here is your query clause)
    

    也许你可以稍后更新。 另一点是按照手册,看来你不能用 CTE 来做 CREATE Table。

    WITH 子句中的每个辅助语句都可以是 SELECT、INSERT、 更新或删除;并且 WITH 子句本身附加到主 也可以是 SELECT、INSERT、UPDATE 或 DELETE 的语句。

    https://www.postgresql.org/docs/current/queries-with.html

    LukStorms 的回答非常简洁。但是薮步可能更具可读性?

    【讨论】:

    • 非常感谢! ...是的,可读性和权宜之计之间存在持续的斗争,但是当谈到可读性和使事情正常时......那就是痛苦开始的时候。哈哈。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    相关资源
    最近更新 更多