标签: plpgsql

从 PostgreSQL 获取随机行?

我想通过 id 从我的表中随机获取一行。

我的表:

ID|Word     |Dificult|Category_id|
1 |'Dumb'   |'Easy'  | 3         |
2 |'Leopard'|'Medium'| 6         |
Run Code Online (Sandbox Code Playgroud)

如果我的用户选择了一个类别和一个困难,我会选择一个带有用户参数的随机单词,例如:

idRaffle := raffle.id;
   -- raffle.id = An id that postgres will bring me by some raffle function. 
d := 'Easy';
c := 3;
select * from words where id=idRaffle and Dificult=d and Category_id=c

raffle.id
Run Code Online (Sandbox Code Playgroud)

我不知道如何获得那个随机行 id ( raffle.id)。

注意它必须遵循用户的选择条件。

postgresql plpgsql

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

使用 PL/pgSQL 函数返回一条记录 - 加快查询速度

我有一个用 Perl 编写的非分叉游戏守护进程,它使用 acync 查询将玩家统计数据写入 PostgreSQL 9.3 数据库。但是当我需要从数据库中读取某些内容时(例如玩家是否被禁止或玩家是否具有 VIP 身份),那么我使用同步查询。

这会使游戏停止一小会,直到从数据库中读取该值。

我无法重写我的游戏守护程序以使用异步查询来读取值(我尝试过,但它需要进行太多更改),所以我的问题是:将几个不相关的查询组合在一起是否有意义(我需要在新玩家连接) 到 1 个过程,如何同时将多个值返回到我的 Perl 程序?

我当前的查询都以玩家 ID 作为参数并返回 1 个值:

-- Has the player been banned?
select true from pref_ban where id=?

-- What is the reputation of this player?
select
count(nullif(nice, false)) -
count(nullif(nice, true)) as rep
from pref_rep where id=?

-- Is he or she a special VIP player?
select vip > now() as vip from pref_users where id=?

-- How many …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql functions postgresql-9.3

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

如何使用 PLPGSQL 确定当前 search_path 中是否存在表?

我正在为一个应用程序编写一个安装脚本,该脚本是另一个应用程序的插件,所以我想检查另一个应用程序的表是否存在。如果没有,我想给用户一个有用的错误。但是,我不知道什么模式将保存这些表。

DO LANGUAGE plpgsql $$
BEGIN
    PERFORM 1
    FROM
        pg_catalog.pg_class c
        JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
    WHERE
        n.nspname = current_setting('search_path')
        AND c.relname = 'foo'
        AND c.relkind = 'r'; -- not sure if I actually need this or not...

    IF NOT FOUND THEN
        RAISE 'This application depends on tables created by another application';
    END IF;
END;
$$;
Run Code Online (Sandbox Code Playgroud)

但是,current_setting('search_path')返回"$user",public默认包含的 TEXT ,这不是很有用。

我唯一能想到的另一件事是尝试从表中选择并捕获异常。它可以完成这项工作,但我认为它不是很优雅,而且我读到它使用起来很昂贵(尽管在这种情况下可能没问题,因为我只运行一次?)。

postgresql plpgsql catalogs

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

Postgres plpgsql - 在动态创建语句中使用变量

使用 Postgres pl/pgsql,我尝试使用动态 EXECUTE 命令创建一个表,例如:

 ...
 DECLARE
    tblVar varchar := "myTable";
 BEGIN
 EXECUTE 'CREATE TABLE $1 ( 
             foo integer NOT NULL, 
             bar varchar NOT NULL)'
 USING _tblVar;
 ...
Run Code Online (Sandbox Code Playgroud)

但是,我继续收到错误消息

错误:“$1”处或附近的语法错误

如果我不使用$1令牌,而是编写字符串,myTable它就可以正常工作。

对 CREATE 调用使用动态语句是否有限制?

postgresql dynamic-sql plpgsql

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

错误:在不能接受集合的上下文中调用 set_valued 函数。它是关于什么的?

我使用 Postgresql 9.1 和 ubuntu 12.04。

克雷格的回答启发,我的问题类型SETOF或SETOF纪录的级联我以为我会使用顺利return querysetof record等一系列的发电机到这个PLPGSQL功能:

create or replace function compute_all_pair_by_craig(id_obj bigint)
    returns setof record as $$
begin
    return query select o.id, generate_series(0,o.value) from m_obj as o;     
end;
$$    language plpgsql;
Run Code Online (Sandbox Code Playgroud)

在执行期间我收到错误:

ERROR: set_valued function called in context that cannot accept a set

怎么了 ?与 Craig 相反,我告诉函数返回setof record

我可以实现与 Craig 完全一样的工作,即通过定义类型create type pair_id_value as (idx bigint, value integer)并让我的 plpgsql 函数返回 asetof of pair_id_value而不是setof record …

postgresql stored-procedures plpgsql set-returning-functions

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

Postgresql 函数来创建表

我想创建一个函数,以便创建一个具有特定结构的表,将表名的一部分作为参数传递,因此表名是 t_ 。与此类似:

CREATE OR REPLACE FUNCTION create_table_type1(t_name VARCHAR(30)) RETURNS VOID AS $$
BEGIN
    EXECUTE "CREATE TABLE IF NOT EXISTS t_"|| t_name ||"
    (
    id SERIAL,
    customerid INT,
    daterecorded DATE,
            value DOUBLE PRECISION,
    PRIMARY KEY (id)
    )"
END
$$ LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)

然后像这样调用它:

SELECT create_table_type1('one');
Run Code Online (Sandbox Code Playgroud)

是否可以?

postgresql plpgsql functions postgresql-9.2

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

如何在 PL/pgSQL 中获取手动引发的异常的异常上下文?

在 Postgres 中,我们使用以下代码获取异常的“堆栈跟踪”:

EXCEPTION WHEN others THEN
    GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;
Run Code Online (Sandbox Code Playgroud)

这适用于“自然”异常,但如果我们使用

RAISE EXCEPTION 'This is an error!';
Run Code Online (Sandbox Code Playgroud)

...然后没有堆栈跟踪。根据邮件列表条目,这可能是故意的,尽管我终生无法弄清楚原因。这让我想找出另一种抛出异常的方法,而不是使用RAISE. 我只是错过了一些明显的东西吗?有没有人有这个技巧?我可以让 Postgres 抛出一个包含我选择的字符串的异常,这样我不仅可以在错误消息中获得我的字符串,还可以获得完整的堆栈跟踪吗?

这是一个完整的例子:

CREATE OR REPLACE FUNCTION error_test() RETURNS json AS $$
DECLARE
    v_error_stack text;
BEGIN

    -- Comment this out to see how a "normal" exception will give you the stack trace
    RAISE EXCEPTION 'This exception will not get a stack trace';

    -- This will give a divide by zero error, complete with stack …
Run Code Online (Sandbox Code Playgroud)

postgresql error-handling exception plpgsql postgresql-9.3

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

如何防止 PostgreSQL 触发器被另一个触发器触发?

我在一张桌子上有 2 个触发器;一种适用于插入:

CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();
Run Code Online (Sandbox Code Playgroud)

这会更新表中的一些值。
还有一个用于更新(填充历史表):

CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();
Run Code Online (Sandbox Code Playgroud)

问题是,当我在表中插入新行时,该过程"add_info"()会进行更新并因此触发第二个触发器,该触发器以错误结束:

ERROR:  record "new" has no field "field1"
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免这种情况?

postgresql trigger plpgsql postgresql-9.3

11
推荐指数
2
解决办法
7709
查看次数

PostgreSQL Upsert 不适用于分区表

有一张这样的表:

CREATE TABLE aggregated_master (
  "user"       BIGINT,
  type         TEXT,
  date         TIMESTAMP,
  operations   BIGINT,
  amount       NUMERIC,
  PRIMARY KEY ( "user", type, date )
);
Run Code Online (Sandbox Code Playgroud)

这张表是很多分区继承的主表。分区由 DATE 字段中的 MONTH 完成。例如:2017 年 8 月的分区将是 agg_201708,它的 PK 将是 pk_agg_201708 在插入之前通常会触发将插入重定向到正确的分区。

问题是我想在这个表中做一个 UPSERT。DO CONFLICT 部分不起作用。

最初的代码是这样的

INSERT INTO aggregated_master (user, type, date, oeprations, amount)
SELECT user, type, date, SUM(ops), SUM(amt)
FROM ...
WHERE ...
GROUP BY USER, TYPE, DATE
ON CONFLICT ON CONSTRAINT pk_aggregated
DO UPDATE SET operations = EXCLUDED.operations
          ,   amount = EXCLUDED.amount
Run Code Online (Sandbox Code Playgroud)

但是后来我注意到约束 …

postgresql plpgsql upsert

10
推荐指数
2
解决办法
5367
查看次数

尽管存在冲突,但仍会出现多行插入的死锁 DO NOTHING

设置

我有一个如下所示的批量插入功能set_interactions(arg_rows text)

with inserts as (
    insert into interaction (
        thing_id,
        associate_id, created_time)
    select t->>'thing_id', t->>'associate_id', now() from
    json_array_elements(arg_rows::json)  t
    ON CONFLICT (thing_id, associate_id) DO NOTHING
    RETURNING thing_id, associate_id
) select into insert_count count(*) from inserts;

-- Followed by an insert in an unrelated table that has two triggers, neither of which touch any of the tables here (also not by any of their triggers, etc.)
Run Code Online (Sandbox Code Playgroud)

(我这样包装它是因为我需要计算实际插入的数量,而没有“假行更新”技巧。)

该表interaction有:

  1. 只有一个约束:多列主键 (thing_id, associate_id)
  2. 没有索引
  3. 只有一个触发器:插入后,对于每一行。

触发器执行以下操作:

DECLARE …
Run Code Online (Sandbox Code Playgroud)

postgresql deadlock plpgsql upsert postgresql-9.6

10
推荐指数
1
解决办法
9338
查看次数