标签: plpgsql

触发器:将删除的行移动到归档表

我的restrictionsPostgreSQL 数据库中有一个小(约 10 行)表,其中每天删除和插入值。

我想要一个名为 的表restrictions_deleted,从中删除的每一行都restrictions将自动存储。由于restrictions具有序列号,因此不会有重复项。

如何在 PostgreSQL 中编写这样的触发器?

postgresql trigger delete plpgsql

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

在 PL/pgSQL 中是否有一种简单的方法来检查查询是否没有返回结果?

我目前正在尝试使用 PL/pgSQL,想知道是否有更优雅的方法来做这样的事情:

select c.data into data from doc c where c.doc_id = id and c.group_cur > group_cur order by c.id desc limit 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        select c.data into data from doc c where c.doc_id = id and c.global_cur > global_cur order by c.id desc limit 1;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN NULL;
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql

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

21
推荐指数
2
解决办法
8016
查看次数

函数参数和带有 USING 子句的 JOIN 结果之间的命名冲突

鉴于当前 Postgres 9.4 中的此设置(来自此相关问题):

CREATE TABLE foo (ts, foo) AS 
VALUES (1, 'A')  -- int, text
     , (7, 'B');

CREATE TABLE bar (ts, bar) AS
VALUES (3, 'C')
     , (5, 'D')
     , (9, 'E');
Run Code Online (Sandbox Code Playgroud)

db<> fiddle here(也来自上一个问题)。

SELECT用 a写了一个FULL JOIN来实现引用问题的目标。简化:

SELECT ts, f.foo, b.bar
FROM   foo f
FULL   JOIN bar b USING (ts);
Run Code Online (Sandbox Code Playgroud)

As per specifications, the correct way to address the column ts is without table qualification. Either of the …

postgresql join naming-convention parameter plpgsql

18
推荐指数
1
解决办法
6345
查看次数

如何在 PL/pgSQL 中返回多行记录

我正在尝试使用 RECORD 数据类型返回多个记录,有没有一种方法可以附加到 RECORD 并在每次迭代时向该 RECORD 添加/附加一个新值。

也就是说,我要追加到rec使rec成为一组行,当循环结束,我可以只返回在我的函数结束。目前,我正在这样做 -

SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;
Run Code Online (Sandbox Code Playgroud)

我的完整代码在这里:

CREATE OR REPLACE FUNCTION validation()
  RETURNS RECORD AS $$
DECLARE
        rec RECORD;
        temp_row RECORD;
BEGIN

  CREATE TEMPORARY TABLE temp_table (col1 TEXT, col2 INTEGER, col3 BOOLEAN) ON COMMIT DROP;

  FOR temp_row IN SELECT * FROM staging.validation
  LOOP

    RAISE NOTICE 'sql: %', temp_row.sql;

    EXECUTE format('INSERT INTO temp_table %s', temp_row.sql);

    IF (SELECT DISTINCT temp_table.col3 FROM temp_table WHERE …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql postgresql-9.5

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

在 Postgres 中尝试 catch 等价物

我们在 Postgres 中有一个 try catch 等价物吗?我编写了一些由触发器调用的用户定义函数。我(不想)想忽略错误,以免流程中断。

postgresql error-handling plpgsql postgresql-9.6

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

PostgreSQL 过程语言开销(plpython/plsql/pllua...)

我试图实时任务的过程语言性能中查找有关 PostgreSQL用户定义函数的信息。

  1. 它们与内置函数相比如何?
  2. Postgres 如何调用/管理 plpython vs plpgsql vs pllua 函数(我对 Postgres 集成/上下文/数据传输方面,而不是 VM 本身感兴趣)有什么区别(在开销上)?
  3. 上下文是一个很大的开销吗?我可以将它用于实时数据映射吗(假设 1000 次查询/秒))
  4. 在 plpgsql 和其他 pg/语言中编写用户定义的函数有什么好处吗?在文档中,他们列举了优点,但我认为它们适用于所有 postgresql 过程语言。

相关发现:

postgresql plpgsql plpython

15
推荐指数
3
解决办法
6283
查看次数

如果两个进程同时尝试刷新实体化视图会发生什么?

根据文档:

CONCURRENTLY 刷新物化视图而不锁定物化视图上的并发选择。(……)

... 其他内容 ...

即使使用此选项,一次也只能针对任何 一个物化视图运行一个 REFRESH

一个函数可以检查 MATERIALIZED VIEW 的上次刷新时间,如果超过 60 秒,它会刷新它。

但是,如果我尝试同时从两个单独的进程刷新物化视图会发生什么?他们会排队还是会引发错误?

有没有办法检测何时刷新 MATERIALIZED VIEW 从​​而避免触摸它?

目前,我已经在刷新(设置refreshingtrue)之前填充表记录,然后false在过程完成时将其设置为。

EXECUTE 'INSERT INTO refresh_status (last_update, refreshing) 
         VALUES (clock_timestamp(), true) RETURNING id') INTO refresh_id;
EXECUTE 'REFRESH MATERIALIZED VIEW CONCURRENTLY my_mat_view';
EXECUTE 'UPDATE refresh_status SET refreshing=false WHERE id=$1' USING refresh_id;
Run Code Online (Sandbox Code Playgroud)

然后,每当我调用此过程时,我都会检查最新的last_update及其refreshing值。如果refreshing为 true,则不要尝试刷新物化视图。

EXECUTE 'SELECT 
           extract(epoch FROM now() - (last_update))::integer, 
           refreshing
         FROM refresh_status
         ORDER BY …
Run Code Online (Sandbox Code Playgroud)

postgresql materialized-view plpgsql

15
推荐指数
2
解决办法
8064
查看次数

并发事务导致竞争条件对插入具有唯一约束

我有一个 Web 服务(http api),它允许用户安静地创建资源。在身份验证和验证之后,我将数据传递给 Postgres 函数,并允许它检查授权并在数据库中创建记录。

我今天发现了一个错误,即在同一秒内发出了两个 http 请求,导致使用相同的数据两次调用此函数。函数内部有一个子句,它在表上进行选择以查看值是否存在,如果存在,则获取 ID 并在下一个操作中使用该 ID,如果不存在,则插入数据,获取返回 ID,然后在下一个操作中使用它。下面是一个简单的例子。

select id into articleId from articles where title = 'my new blog';
if articleId is null then
    insert into articles (title, content) values (_title, _content)
    returning id into articleId;
end if;
-- Continue, using articleId to represent the article for next operations...
Run Code Online (Sandbox Code Playgroud)

正如您可能猜到的那样,我对数据进行了幻读,其中两个事务都进入了if articleId is null then块并试图插入到表中。一个成功了,另一个失败了,因为一个领域的独特限制。

我已经环顾四周,看看如何抵御这种情况,并找到了一些不同的选择,但由于某些原因,它们似乎都不适合我们的需求,我正在努力寻找任何替代方案。

  1. insert ... on conflict do nothing/update...我首先查看了on conflict看起来不错的选项,但是唯一的选项是do nothing不返回导致冲突的记录的 ID,并且do update不会工作,因为它会导致触发器在实际数据时被触发没有改变。在某些情况下,这不是问题,但在许多情况下,这可能会使会话用户会话无效,这是我们无法做到的。 …

postgresql concurrency transaction plpgsql upsert

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

使用上下文生成异常

当 PostgreSQL 抛出异常时,有一行“CONTEXT”,如:

    ERROR:  INSERT has more target COLUMNS than expressions
    LINE 3: ...
                                                         ^
    QUERY:  INSERT INTO ...
    CONTEXT:  PL/pgSQL FUNCTION "XXXXX" line 4 at SQL statement
Run Code Online (Sandbox Code Playgroud)

但是当我抛出异常时,这条线不存在。我没有找到如何添加它。

    RAISE EXCEPTION 'blablabla' USING HINT = 'blablablabla';
Run Code Online (Sandbox Code Playgroud)

是否可以将此行添加到我的异常中?

postgresql error-handling plpgsql

13
推荐指数
1
解决办法
4552
查看次数