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 的回答非常简洁。但是几个步骤可能更具可读性?
我一直在做研究并尝试各种不同的方法,但没有成功。我想创建一个临时 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 的回答非常简洁。但是几个步骤可能更具可读性?