标签: plpgsql

通过 Postgres 触发器中的键分配给 NEW

在触发器主体中,如何NEW通过其字段名称为其分配值?
这就是我想要做的:

some_key = "some_column";
NEW[some_key] = 5;
Run Code Online (Sandbox Code Playgroud)

postgresql trigger plpgsql functions

5
推荐指数
1
解决办法
5655
查看次数

未修改主表时获取插入的行数

我有一个分区表,其中数据仅驻留在子表中。主表有一个插入触发器,可以将插入的数据分配到适当的子表中。

现在,我需要创建一个 PL/pgSQL 过程,该过程从(主)表中选择一些数据并使用一些更改的值重新插入它。

通常我会使用ROW_COUNT诊断变量并完成它。问题是 ROW_COUNT 始终为 0,因为主表中没有插入任何内容(触发器在途中捕获并重定向插入)。

我的下一个想法是做类似的事情

WITH inserted AS (
  INSERT INTO master (...) SELECT ... FROM master WHERE ... RETURNING master.field
) SELECT count(*) FROM inserted INTO rowcount;
Run Code Online (Sandbox Code Playgroud)

但是,再次,rowcount 总是最终为 0,因为没有实际插入到主表中。

如果我做

WITH insertable AS (
  SELECT ... FROM master WHERE ...
), blah AS (
  SELECT count(*) INTO rowcount FROM insertable
) INSERT INTO master SELECT * FROM insertable;
Run Code Online (Sandbox Code Playgroud)

然后 Postgresql 抱怨说:

错误:INTO 与无法返回数据的命令一起使用

SQL 状态:42601

等等...

如果是我最后的代码提取,我如何将行数inserted放入rowcount我的程序中的变量中,然后我可以用它来做东西 …

postgresql partitioning plpgsql

5
推荐指数
1
解决办法
2942
查看次数

使用触发器在插入或更新时将列与 json 列中的字段同步

我是一个数据库/postgres 初学者,所以请耐心等待。
如果我有一张桌子,就像这样。

CREATE TABLE testy (
    id INTEGER REFERENCES other_table,
    name varchar(128) PRIMARY KEY,
    json JSONB NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

我在寻找插入或更新,将设置列之前创建一个触发器id,并name与在相同名称字段的值json

因此,例如,如果testy包含以下内容UPDATE testy SET json = '{"id":2,"name":"jim"}' WHERE id = 1并被调用。

id | name | json
---+------+-----
 1 | "jim"| {"id":1,"name":"jim"}
Run Code Online (Sandbox Code Playgroud)

想要的结果是

id | name | json
---+------+-----
 2 | "jim"| {"id":2,"name":"jim"}
Run Code Online (Sandbox Code Playgroud)

我希望使其相当通用,因此不需要对列名进行硬编码。如果相应的 json 字段不存在,则将该列设置为 NULL 即可。到目前为止我有

CREATE TABLE testy_index (
    id INTEGER PRIMARY KEY
);

INSERT INTO testy_index VALUES …
Run Code Online (Sandbox Code Playgroud)

postgresql trigger plpgsql json postgresql-9.4

5
推荐指数
1
解决办法
5032
查看次数

我们可以在第一次执行 PL/pgSQL 函数时执行最佳计划而不是通用计划吗?

我有一个非常繁忙的功能,我需要以最佳方式优化。此函数只是一个嵌套的 select 语句,遗留应用程序每秒请求数次。

索引已就位,但我注意到它仅在第一次执行函数后使用。我认为问题在于 Postgres 创建了一个通用的执行计划,因为它在大多数情况下是高度排他的,但有时可能没有那么好。

当我EXPLAIN ANALYZE在第一次执行后进行测试时,查询运行得非常快,但应用程序会话仅调用该函数一次,然后终止。我需要第一次执行使用实际的优化计划。任何人都可以帮忙吗?

我们尝试弄乱管理连接池的连接器驱动程序来发出一个DISCARD TEMP而不是DISCARD ALL,因此它可以保持会话的缓存计划并且性能达到顶峰,但我不想在生产环境中这样做.

我们使用的是在 CentOS 6 上运行的 Postgres 9.4。我试过作为 SQL 函数运行,但没有帮助,它实际上作为 plpgsql 函数更快。下面是函数代码:

CREATE OR REPLACE FUNCTION public.ap_keepalive_geteqpid_veiid(
    IN tcbserie bigint,
    IN protocolo integer)
  RETURNS TABLE(eqpid integer, veiid integer, tcbid integer, veiplaca character varying, veiproprietariocliid integer, tcbtppid integer, tcbversao character, veirpmparametro double precision, tcbconfiguracao bigint, tcbevtconfig integer, veibitsalertas integer, sluid integer, harid integer) AS
$BODY$
BEGIN
    RETURN QUERY
    SELECT  teqp.eqpID, 
            teqp.eqpveiID AS veiID, 
            tcb.tcbID, 
            tvei.veiPlaca, 
            tvei.veiProprietariocliID, …
Run Code Online (Sandbox Code Playgroud)

postgresql performance hints plpgsql postgresql-9.4 postgresql-performance

5
推荐指数
1
解决办法
923
查看次数

将 ROWTYPE 参数传递给 EXECUTE

我正在 Postgres 中开发一个函数,旨在为查询的每个记录恢复一组函数中包含的检查结果的值。只有这些函数之一会返回正确的值。这些函数有一个公共前缀“fn_condition_”,并接收一个“my_table”类型的对象作为参数。

由于进行检查的函数数量未知,我决定查阅 Postgres 目录,从表中pg_catalog.pg_proc搜索带有前缀“fn_condition_”的函数并使用EXECUTE.

我的问题是将参数传递给EXECUTE.

create or replace function test_conditions()
returns void as 
$$
declare
    v_record my_table%rowtype;
    v_function pg_proc%rowtype;    
begin 
    set search_path = 'pg_catalog';

    for v_record in (select * from my_table where id in (1,2,3)) loop
        for v_function in (
            SELECT  p.proname
            FROM    pg_namespace n
            JOIN    pg_proc p
            ON      p.pronamespace = n.oid
            WHERE   n.nspname = 'operacional'
            and p.proname like ('fn_condition\\_%')
            order by p.proname) 
        loop
         -- execute 'select ' || v_function.proname || '(' …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql plpgsql postgresql-8.3

5
推荐指数
1
解决办法
2491
查看次数

使用复合类型的数组作为函数参数并访问它

Books在 Postgres 中创建了一个类型,它有 2 个numeric字段和 2 个varchar字段。我想将Books一个函数的数组发送到INSERT匹配表中的那些值。

这是我的类型:

CREATE TYPE Books AS (
V_Book_ID NUMERIC,
V_Row_Num NUMERIC,
V_Book_OWNER TEXT,
V_Book_OWNER_ID TEXT
);
Run Code Online (Sandbox Code Playgroud)

这是我的功能:

CREATE OR REPLACE FUNCTION Update_Table(row_book Books[]) RETURNS TEXT AS $$
DECLARE
   Status TEXT;
   I_Max integer := array_length(row_book, 1);
BEGIN
FOR I in 1..I_Max
  LOOP
   INSERT INTO books_table(Book_ID,
   Row_Num,
   Book_OWNER,
   Book_OWNER_ID)
   values
   (row_book[I].V_Book_ID,
   row_book[I].V_Row_Num,
   row_book[I].V_Book_OWNER,
   row_book[I].V_Book_OWNER_ID);
END LOOP;

   STATUS:='Saved';
exception when others then
   STATUS:='failure';
   RETURN STATUS;

END;
$$ …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql functions array composite-types

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

PL/pgSQL regclass 引用名为 like 关键字的表

我想通过在现有表名的基础上附加后缀来创建一个新表名。Postgres 9.5 PL/pgSQL 函数获取作为regclass类型传入的现有表名,并以字符串形式返回新名称。我format()用来构造新名称,通常会使用%I占位符。只要传入的表名不匹配任何 PL/pgSQL 关键字,这就会起作用。在这种情况下,无论我选择(%I%s)什么类型的组件,引用都是错误的。

考虑以下函数:

CREATE OR REPLACE FUNCTION make_name(old_name regclass)
RETURNS text                                           
LANGUAGE plpgsql AS                                    
$$                                                     
BEGIN                                                  
    RETURN format('%I_new', old_name);                 
END;                                                   
$$;                                                    
Run Code Online (Sandbox Code Playgroud)

进一步假设有两个表:treenodeoverlay。为这两个函数调用此函数会产生以下新名称:

SELECT make_name('overlay'::regclass);
     make_name     
-------------------
 """overlay"""_new
(1 row)

SELECT make_name('treenode'::regclass);
  make_name   
--------------
 treenode_new
(1 row)
Run Code Online (Sandbox Code Playgroud)

事实证明overlay它也是一个 PL/pgSQL 函数(就像format,但treenode不是),它似乎改变了引用行为。如果%s与 一起使用format(),结果将是"overlay"_new。当我使用||运算符时也会发生同样的情况。如果我使用text作为输入参数类型,一切都按预期工作,但我更喜欢使用regclass.

有没有办法用不带引号的关键字匹配regclass表名(例如overlay …

postgresql syntax datatypes plpgsql regclass

5
推荐指数
1
解决办法
2087
查看次数

分配具有动态列名的列

我得到了要在 ( BEFORE UPDATE) 触发器中设置的列的名称,我想将其设置为该OLD值并忽略传入的任何内容。我尝试了以下操作:

CREATE OR REPLACE FUNCTION prevent_column_update() RETURNS TRIGGER AS $$
  DECLARE
    col TEXT := TG_ARGV[0];
  BEGIN
    EXECUTE format('SELECT ($1).%I INTO ($2).%I', col, col) USING OLD, NEW;
    RETURN NEW;
  END;
  $$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

并使用如下:

CREATE TRIGGER request_protect_date_price_value
  BEFORE UPDATE OF date_price ON requests
  FOR EACH ROW EXECUTE PROCEDURE prevent_column_update('date_price');
Run Code Online (Sandbox Code Playgroud)

但是当更新它失败时:

ERROR:  syntax error at or near "("
LINE 1: SELECT ($1).date_price INTO ($2).date_price
                                    ^
QUERY:  SELECT ($1).date_price INTO ($2).date_price
Run Code Online (Sandbox Code Playgroud)

postgresql trigger dynamic-sql plpgsql postgresql-9.5

5
推荐指数
1
解决办法
6392
查看次数

是否可以使用 plpgsql 或 SQL 创建用户定义的类型?

不同于DOMAIN我想知道是否可以在没有 C 的情况下创建用户定义的类型。

具体来说,我想创建一个这样的类型

CREATE TYPE name (
    INPUT = input_function,
    OUTPUT = output_function
    [ , RECEIVE = receive_function ]
    [ , SEND = send_function ]
    [ , TYPMOD_IN = type_modifier_input_function ]
    [ , TYPMOD_OUT = type_modifier_output_function ]
    [ , ANALYZE = analyze_function ]
    [ , INTERNALLENGTH = { internallength | VARIABLE } ]
    [ , PASSEDBYVALUE ]
    [ , ALIGNMENT = alignment ]
    [ , STORAGE = storage ]
    [ , LIKE = like_type …
Run Code Online (Sandbox Code Playgroud)

postgresql datatypes plpgsql

5
推荐指数
1
解决办法
386
查看次数

Joining a function and a view

我有一个功能 get_sa001 and a view Axis_RefCustomer.

当我get_sa001在一段时间内单独执行我的函数时,比如说 2016 - 2017,执行时间约为 6 秒。

SELECT d."Selling_date",  d."Value_in_EUR", d."Value_in_currency", d."Site"
FROM report.get_sa001('2016-01-01'::date, '2017-03-31'::date, 32) AS d
Run Code Online (Sandbox Code Playgroud)

当我在视图上执行选择时Axis_RefCustomer,它运行大约 1 秒。

Select a."Selling_currency" FROM report."Axis_RefCustomer" AS a
Run Code Online (Sandbox Code Playgroud)

当我将它们连接在一起时,执行时间约为 39 秒!

SELECT d."Selling_date",
a."Selling_currency", 
d."Value_in_EUR", 
d."Value_in_currency", 
d."Site"
FROM report.get_sa001('2016-01-01'::date, '2017-03-31'::date, 32) AS d 
LEFT JOIN report."Axis_RefCustomer" 
AS a ON d."Site" = a."Site" 
AND d."Internal_reference" = a."Reference_internal" 
AND d."Customer_code" = a."Customer_code"
Run Code Online (Sandbox Code Playgroud)

Is there anyway to reduce the amount of time my query …

postgresql performance execution-plan plpgsql

5
推荐指数
1
解决办法
169
查看次数