标签: plpgsql

Postgresql存储过程中基于会话的全局变量?

在Oracle的PL/SQL中,我可以使用包定义创建基于会话的全局变量.使用Postgresql的PLpg/SQL,它似乎不可能,因为没有包,只有独立的程序和功能.

以下是PL/SQL将g_spool_key声明为全局的语法...

CREATE OR REPLACE PACKAGE tox IS
        g_spool_key spool.key%TYPE := NULL;
        TYPE t_spool IS REF CURSOR RETURN spool%ROWTYPE;
        PROCEDURE begin_spool;
        PROCEDURE into_spool
            (
            in_txt IN spool.txt%TYPE
            );
        PROCEDURE reset_spool;
        FUNCTION end_spool
            RETURN t_spool;
        FUNCTION timestamp
            RETURN VARCHAR2;
    END tox;
Run Code Online (Sandbox Code Playgroud)

如何使用PLpg/SQL实现基于会话的全局变量?

oracle postgresql plsql plpgsql

9
推荐指数
3
解决办法
9878
查看次数

从PostgreSQL存储过程返回记录集的最简单方法是什么?

我只是有一个表格,其中包含国家列表及其ISO国家/地区代码.我将查询包装在存储过程(也称为函数)中,例如:

CREATE OR REPLACE FUNCTION get_countries(
                    ) RETURNS setof record AS $$
        SELECT country_code, country_name FROM country_codes
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

ERROR:  a column definition list is required for functions returning "record"
Run Code Online (Sandbox Code Playgroud)

我知道我可以定义一个TYPE,然后像光标一样循环遍历记录集,但是在更新版本的PostgreSQL(我使用的是8.4.3)下,有更好的方法可以做到这一点,但我正在尝试要记住.


编辑:

这有效:

CREATE OR REPLACE FUNCTION get_countries(
                    ) RETURNS setof country_codes AS $$
        SELECT country_code, country_name FROM country_codes
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

请注意"RETURNS setof [table name]".但它似乎并不是最灵活的.如果我尝试返回多个表的连接,它就会崩溃.

sql postgresql stored-procedures plpgsql

9
推荐指数
2
解决办法
2万
查看次数

在PL/pgSQL过程中使用临时表来清理表

我正在尝试从游戏数据库中删除与用户ID相关的所有数据.

有一张桌子可容纳所有游戏(每个游戏由3名玩家扮演):

# select * from pref_games where gid=321;
 gid | rounds |          finished
-----+--------+----------------------------
 321 |     17 | 2011-10-26 17:16:04.074402
(1 row)
Run Code Online (Sandbox Code Playgroud)

并且有一张桌子可以控制该游戏的玩家分数#321:

# select * from pref_scores where gid=321;
      id       | gid | money | quit
----------------+-----+-------+------
 OK531282114947 | 321 |   218 | f
 OK501857527071 | 321 |  -156 | f
 OK429671947957 | 321 |   -62 | f
Run Code Online (Sandbox Code Playgroud)

当我在PostgreSQL的psql-prompt上尝试以下SELECT INTO语句时,它似乎按预期工作(临时表在会话关闭时消失):

# select gid into temp temp_gids from pref_scores where id='OK446163742289';
SELECT

# select * from temp_gids ;
 gid …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql select-into

9
推荐指数
2
解决办法
2万
查看次数

将PL/pgSQL SELECT转换为数组

这是我的函数声明和正文的一部分:

CREATE OR REPLACE FUNCTION access_update()
RETURNS void AS $$
DECLARE team_ids bigint[];
BEGIN
    SELECT INTO team_ids "team_id" FROM "tmp_team_list";

    UPDATE "team_prsnl"
    SET "updt_dt_tm" = NOW(), "last_access_dt_tm" = NOW()
    WHERE "team_id" IN team_ids;
END; $$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

我想team_ids成为一个我可以在UPDATE声明中使用的一组int .这个函数给我这样的错误:

psql:functions.sql:62: ERROR:  syntax error at or near "team_ids"
LINE 13:  AND "team_id" IN team_ids;
Run Code Online (Sandbox Code Playgroud)

sql postgresql plpgsql postgresql-9.1

9
推荐指数
2
解决办法
2万
查看次数

在存储函数中使用预准备语句

我在数据库中有一个表:

create table store (
    ...
    n_status        integer not null,
    t_tag           varchar(4)
    t_name          varchar,
    t_description   varchar,
    dt_modified     timestamp not null,
    ...
);
Run Code Online (Sandbox Code Playgroud)

在我的存储函数中,我需要select多次对该表执行相同的操作:

select * from store
where n_place_id = [different values]
and t_tag is not null
and n_status > 0
and (t_name ~* t_search or t_description ~* t_search)
order by dt_modified desc
limit n_max;
Run Code Online (Sandbox Code Playgroud)

这里,t_search并且n_max是存储函数的参数.我认为为此使用准备好的声明是有意义的,但我遇到了奇怪的问题.这就是我所拥有的:

create or replace function fn_get_data(t_search varchar, n_max integer)
  returns setof store as
$body$
declare
    resulter        store%rowtype;
    mid             integer; …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql prepared-statement

9
推荐指数
2
解决办法
1万
查看次数

Postgresql plpgsql/sql是否支持where子句中的短路?

如果我有以下玩具查询

SELECT *
FROM my_tables
WHERE my_id in (
    SELECT my_other_id
    FROM my_other_tables
) AND some_slow_func(arg) BETWEEN 1 AND 2;
Run Code Online (Sandbox Code Playgroud)

WHERE子句中的第一个条件是否会短路第二个具有复杂运行时间的条件?

我正在研究一些实际上是plpgsql中FOR LOOP的一部分的sql,我可以对my_other_tables中存在的所有记录进行迭代,然后使用some_slow_func()在FOR LOOP的范围内进行测试.但我很好奇是否支持sql,或者plpgsql支持短路.

一些研究:我查看了Postgres的邮件列表,发现这说SQL一般不支持短路:

http://www.postgresql.org/message-id/171423D4-9229-4D56-B06B-58D29BB50A77@yahoo.com

但其中一个回复表明订单可以通过子选择来强制执行.我不确定他在说什么.我知道子选择是什么,但我不确定如何强制执行命令?有人可以为我澄清一下吗?

sql postgresql plpgsql

9
推荐指数
2
解决办法
3518
查看次数

PostgreSQL中两个数组的联合,没有取消

我在PostgreSQL中有两个我需要联合的数组.例如:

{1,2,3}工会{1,4,5}会回来{1,2,3,4,5}

使用连接(||)运算符不会删除重复的条目,即它返回 {1,2,3,1,4,5}

我在网上找到了一个解决方案,但我不喜欢它需要如何取消两个数组: select ARRAY(select unnest(ARRAY[1,2,3]) as a UNION select unnest(ARRAY[2,3,4,5]) as a)

是否有一个运算符或内置函数可以干净地结合两个数组?

arrays postgresql union plpgsql

9
推荐指数
2
解决办法
8675
查看次数

如何在 PostgreSQL 中发生错误时回滚事务?

我正在为 PostgreSQL 编写一个脚本,因为我希望它以原子方式执行,所以我将它包装在一个事务中。
我希望脚本看起来像这样:

BEGIN
-- 1) Execute some valid actions;
-- 2) Execute some action that causes an error.
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
END; -- A.k.a. COMMIT;
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,pgAdmin 在初始BEGIN. 如果我通过像这样附加分号来终止命令:BEGIN;它会通知我附近的错误EXCEPTION。
我意识到我可能混淆了控制结构和事务的语法,但是我在文档中找不到任何关于如何回滚失败事务的内容(也没有在 SO 中)。

我还考虑过事务可能会在出错时自动回滚,但由于以下脚本,情况似乎并非如此:

BEGIN;
-- 1) Execute some valid actions;
-- 2) Execute some action that causes an error.
COMMIT;
Run Code Online (Sandbox Code Playgroud)

警告我:ERROR: current transaction is aborted, commands ignored until end of transaction block然后我必须手动ROLLBACK;进行交易。

似乎我在这里遗漏了一些基本的东西,但是什么?

编辑:
我也试过DO像这样使用: …

postgresql transactions exception plpgsql rollback

9
推荐指数
1
解决办法
4934
查看次数

如何在函数内部强制 COMMIT 以便其他会话可以看到更新的行?

在 Postgres 12 数据库中,我在一个函数中有多个查询(SELECT、UPDATE、 ...),总共需要大约 20 分钟才能完成。我在顶部有一个检查,它执行UPDATEifstatus未运行:

create or replace function aaa.fnc_work() returns varchar as 
$body$
    begin
        if (select count(*) from aaa.monitor where id='invoicing' and status='running')=0 then
           return 'running';
        else
           update aaa.monitor set status='running' where id='invoicing';
        end if;
        --- rest of code ---
        --finally
        update aaa.monitor set status='idle' where id='invoicing';
        return '';
    exception when others then
         return SQLERRM::varchar;
    end
$body$
language plpgsql;
Run Code Online (Sandbox Code Playgroud)

这个想法是为了防止其他用户执行直到--- rest of code ---空闲status。

然而,其他人(调用相同的函数)似乎看不到更新的状态,他们也继续并开始执行 …

postgresql stored-procedures transactions plpgsql task-queue

9
推荐指数
1
解决办法
1万
查看次数

如何批量更新 postgres 中的单个列 5500 万条记录

我想更新 postgres 表的一列。记录大约有 5500 万条,因此我们需要批量更新 10000 条记录。注意:我们要更新所有行。但我们不想锁定我们的桌子。

我正在尝试以下查询 -

Update account set name = Some name where id between 1 and 10000
Run Code Online (Sandbox Code Playgroud)

我们如何为每 10000 条记录更新创建一个循环?

任何建议和帮助将不胜感激。

PostgreSQL 10.5

sql postgresql plpgsql

9
推荐指数
2
解决办法
1万
查看次数