小编use*_*521的帖子

多个冲突目标

我在列ab. 我需要这样的东西:

insert into my_table (a, b) values (1, 2), (1, 2)
on conflict (a) do update set c = 'a_violation'
on conflict (b) do update set c = 'b_violation'
Run Code Online (Sandbox Code Playgroud)

所以一般我想根据冲突目标进行不同的更新 - 不支持上面的语法(只支持一个on conflict语句)。有没有其他方法可以做到这一点?

postgresql duplication upsert postgresql-10

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

设置会话 - 用于存储用户 ID 的自定义变量

我想将用户 ID 存储在自定义会话变量中,并在触发器过程中使用(读取)它来授权用户操作。我发现了这样的东西:

set session "myapp.user" = '12345';
...
SELECT current_setting('myapp.user');
Run Code Online (Sandbox Code Playgroud)

它似乎有效 - 我认为“myapp.user”应该在 .conf 文件中声明,但似乎我可以即时创建会话变量(我根本没有更改 .conf 文件)。

这样做有什么坏处吗?

postgresql postgresql-9.4

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

为什么 jsonb 列上的 gin 索引会减慢我的查询速度,我该怎么办?

初始化测试数据:

CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE docs (data JSONB NOT NULL DEFAULT '{}');
-- generate 200k documents, ~half with type: "type1" and another half with type: "type2", unique incremented index and random uuid per each row
INSERT INTO docs (data)
SELECT json_build_object('id', gen_random_uuid(), 'type', (CASE WHEN random() > 0.5 THEN 'type1' ELSE 'type2' END) ,'index', n)::JSONB
FROM generate_series(1, 200000) n;
-- inset one more row with explicit uuid to query by it later
INSERT INTO docs (data) …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.4

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

选择每组至少一行满足条件的行

我有下表:

create table test (
  company_id integer not null, 
  client_id integer not null, 
  client_status text,
  unique (company_id, client_id)
);

insert into test values
  (1, 1, 'y'),    -- company1

  (2, 2, null),   -- company2

  (3, 3, 'n'),    -- company3

  (4, 4, 'y'),    -- company4
  (4, 5, 'n'),

  (5, 6, null),   -- company5
  (5, 7, 'n')
;
Run Code Online (Sandbox Code Playgroud)

基本上,有 5 家不同的公司,每家公司都有一个或多个客户,每个客户的状态为:“y”或“n”(也可能为空)。

我必须做的是为(company_id, client_id)至少有一个客户的状态不是“n”(“y”或 null)的所有公司选择所有对。所以对于上面的示例数据,输出应该是:

company_id;client_id
1;1
2;2
4;4
4;5
5;6
5;7
Run Code Online (Sandbox Code Playgroud)

我尝试了一些使用窗口函数的东西,但我无法弄清楚如何将所有客户端的数量与带有STATUS = 'n'.

select company_id,
count(*) over (partition …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.4

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

如何处理 select 中的大偏移量?

jtest有 200k 行,每行包含 jsonb { id: "<uuid>", key: <index> }<index>每行递增 1-200k 的整数)。上还有btree索引data->'key'

create extension if not exists pgcrypto;
create table jtest (data jsonb not null default '{}');
insert into jtest (data)
select json_build_object('id', gen_random_uuid(), 'key', i)::jsonb
FROM generate_series(1,200000) i;
create index jtest_key on jtest ((data->'key'));
Run Code Online (Sandbox Code Playgroud)

第一个查询(快速):

EXPLAIN ANALYZE
select j.data
from jtest j
order by j.data->'key' 
limit 20;

-- "Limit  (cost=0.42..1.43 rows=20 width=74) (actual time=0.023..0.044 rows=20 loops=1)"
-- "  ->  Index Scan using …
Run Code Online (Sandbox Code Playgroud)

postgresql limits offset-fetch postgresql-9.4

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

声明函数时出现“多次使用参数名称”错误 - 为什么会发生这种情况?

create function test(a integer, b integer)
returns table (a integer, b integer) as $$
  begin
    return query select 1, 2;
  end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

抛出异常:

ERROR:  parameter name "a" used more than once
CONTEXT:  compilation of PL/pgSQL function "test" near line 1
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?我认为函数参数名称与返回的表列名称无关。是否有一种解决方法可以让函数参数命名为“a”,并且在从函数返回的表中还有名为“a”的列?

我知道我可以返回,setof record但是我必须明确地“定义”从选择查询中的函数返回的列:

create function test(a integer, b integer)
returns setof record as $$
  begin
    return query select 1, 2;
  end;
$$ language plpgsql;

select * from test(1, 2) as (a integer, b integer)
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.4

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

unnest() 如何处理 NULL 值和空数组?

我正在尝试LEFT JOIN使用数组unnest()函数实现类似的功能。如果数组为空,我希望查询返回具有空值的行。因此,通过使用CASE构造,如果源数组为空,我想传递具有单个空元素的假数组,但它无法按预期工作:

查询 1

select element 
from (
  select array['a']::text[] as arr --< single non-null element
) sub, unnest(
  (
    case when array_length(sub.arr, 1) <= 0 then (array[null])::text[] 
    else sub.arr 
    end
  )
) element
-- returns 1 row with element = "a"
Run Code Online (Sandbox Code Playgroud)

查询 2

select element 
from (
  select array[]::text[] as arr --< empty array
) sub, unnest(
  (
    case when array_length(sub.arr, 1) <= 0 then (array[null])::text[] 
    else sub.arr 
    end
  )
) element
-- …
Run Code Online (Sandbox Code Playgroud)

postgresql join array postgresql-9.4

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

如何在函数中选择受影响的行数作为变量?

create or replace function test()
returns void as $$
begin
  update tbl set col1 = true where col2 = false;
  -- now I want to raise exception if update query affected more than 2 rows to rollback the update
end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

如何在函数中为变量选择受影响的行数?

postgresql

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

如何在psql终端中粘贴汉字?

我正在尝试将中文字符粘贴到 psql 终端中:

$ psql
=> \encoding
=> UTF8
# Ctrl+v (?????)
=> ???????
Run Code Online (Sandbox Code Playgroud)

粘贴到普通终端(Max OS)时,它工作正常:

$ # Ctrl+v (?????)
$ ?????
Run Code Online (Sandbox Code Playgroud)

可能有什么问题?

postgresql psql postgresql-9.4

4
推荐指数
1
解决办法
753
查看次数

如果行更改,如何回滚事务?

我正在使用Postgres 9.3.

当我更新表中的行时,我的流程如下所示:

  1. 获取旧行(例如SELECT * FROM tbl WHERE id = 1
  2. 在旧数据范围内验证新数据(在第 1 点中提取的旧行) - 这是由我的应用程序在 postgres 之外完成的。
  3. 用新数据更新行(例如UPDATE tbl SET .... WHERE id = 1

问题是old数据可能在第 2 点期间发生变化,因此验证,即使通过也可能是outdated在第 3 点(更新行)期间。我知道我可以执行这样的更新UPDATE .... WHERE id = 1 AND column1='oldValue'以确保某些字段不会更改,但是我的验证(也比较新旧值)非常复杂,我无法在 SQL UPDATE 语句中“编写”它。

所以我想到了这样的事情:

  1. BEGIN
  2. SELECT * FROM tbl WHERE id = 1
  3. 在我这边执行验证
  4. UPDATE SET=... WHERE id = 1
  5. COMMIT

COMMIT如果在事务执行期间 id = 1 的行发生更改,我想失败。是否可以使用这样的交易?如果不是,其他解决方案是什么?

postgresql postgresql-9.3

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

如果执行了 UPDATE,如何从“upsert”查询返回值?

WITH upsert AS (UPDATE tbl SET a = 2 WHERE a = 1 RETURNING tbl.*)
INSERT INTO tbl (a)
SELECT 1 WHERE NOT EXISTS( SELECT * FROM upsert )
RETURNING *
Run Code Online (Sandbox Code Playgroud)

这个“upsert”语句有效,但是我想检索 UPDATE 或 INSERTED 值。当 upsert 执行INSERT(行尚未在 db 中)时,插入的值将从查询中正确返回。

但是,当UPDATE执行时,不会返回任何值(但行是更新的)。我试过添加,RETURNING upsert.*但它产生错误missing FROM-clause entry for table \"upsert\"

postgresql upsert postgresql-9.3

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

带有 order by 的窗口函数返回奇怪的结果

这是示例:

drop table if exists tst;

create table tst (
num integer not null
);

insert into tst values (1), (2), (3);

-- window functions WITH order by clause
select *, max(num) over (partition by true order by num asc), array_agg(num) over (partition by true order by num asc) as test
from tst;

-- window functions WITHOUT order by clause
select *, max(num) over (partition by true), array_agg(num) over (partition by true) as test
from tst;
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此处输入图片说明

为什么order by子句对聚合功能有影响?

postgresql window-functions

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

什么是最好的(为了性能)事务隔离级别?

在我的应用程序中执行了两种类型的查询:

DELETE FROM tbl1 WHERE user_id = 1;
INSERT INTO tbl1 VALUES (...), (...), ...;
Run Code Online (Sandbox Code Playgroud)

UPDATE tbl2 WHERE id = 1 SET ...;
DELETE FROM tbl3 WHERE tbl2_id = 1;
INSERT INTO tbl3 VALUES (...), (...), ...;
DELETE FROM tbl4 WHERE tbl2_id = 1;
INSERT INTO tbl4 VALUES (...), (...), ...;
Run Code Online (Sandbox Code Playgroud)

我使用的 ORM 自动将事务隔离级别设置为REPEATABLE READ,我想知道它是否是最佳性能的正确选择。我的目标是只执行全部或不执行(来自上面的 2 个事务),我不关心任何读取...

那么在我的情况下哪种隔离级别最适合最佳性能?

postgresql postgresql-9.3

0
推荐指数
1
解决办法
2080
查看次数