Postgresql 存储过程临时 table 变量不是已知变量

Postgresql stored procedure temporary table variable is not a known variable

我一直在做研究并尝试各种不同的方法,但没有成功。我想创建一个临时 table,然后在我进行一些搜索时,用东西填充它。我能够通过 SQL 服务器通过在过程中声明一个 table 来做到这一点,但是对于我读过的 Postgresql,我需要专门创建一个临时的 table。

我的策略刚开始时

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

我什至把它移到了“BEGIN”之后。在文件中我得到这个错误:

ERROR: "myTempTable" is not a known variable
LINE 77: SELECT * INTO myTempTable from myResult;

接下来,我尝试在准备填充时创建临时 table...

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 服务器存储过程转换为 Postgresql。

我做错了什么使临时 table 变量未声明?我需要提前申报的特殊方式吗?关于如何创建或声明临时 table.

我是不是弄错了

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

更新w/Examples

这个版本不行。它在创建 table.

处停止
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$

这在 table 创建时出错。

INE 22:  CREATE TEMP TABLE statustable as...

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

您可以使用 CTE,但要将 CTE 放在 table 创建的括号内。

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

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

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$

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

Tip Note that this interpretation of SELECT with INTO is quite different from PostgreSQL's regular SELECT INTO command, wherein the INTO target is a newly created table. If you want to create a table from a SELECT result inside a PL/pgSQL function, use the syntax CREATE TABLE ... AS SELECT.

基于此然后你可以做

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

也许你可以稍后更新。 另一点是按照手册,似乎你不能通过使用 CTE 来创建 Table。

Each auxiliary statement in a WITH clause can be a SELECT, INSERT, UPDATE, or DELETE; and the WITH clause itself is attached to a primary statement that can also be a SELECT, INSERT, UPDATE, or DELETE.

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

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