相关疑难解决方法(0)

Postgres中的Atomic UPDATE .. SELECT

我正在建立各种排队机制.有需要处理的数据行和状态标志.我正在使用一个update .. returning条款来管理它:

UPDATE stuff
SET computed = 'working'
WHERE id = (SELECT id from STUFF WHERE computed IS NULL LIMIT 1)
RETURNING * 
Run Code Online (Sandbox Code Playgroud)

嵌套的选择部分是否与更新锁相同,或者我是否有竞争条件?如果是这样,内部选择需要是select for update吗?

postgresql concurrency multithreading race-condition transaction-isolation

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

INSERT INTO ... FROM SELECT ... RETURNING id mappings

我正在使用PostgreSQL 9.3.

我想复制一些db记录.由于我正在为表使用自动增量pk id,因此我想从生成的重复记录ID返回到原始ID的id映射.例如,假设我有一个posts包含2条记录的表:

 [{'id': 1, 'title': 'first'}
, {'id': 2. 'title': 'second'}]
Run Code Online (Sandbox Code Playgroud)

使用SQL:

INSERT INTO posts (title) SELECT title FROM posts RETURNING id, ??
Run Code Online (Sandbox Code Playgroud)

我希望看到像这样的映射:

 [{'id': 3, 'from_id': 1}
, {'id': 4, 'from_id': 2}]
Run Code Online (Sandbox Code Playgroud)

有关如何填写上述问号以使其有效的任何想法?非常感谢!

sql postgresql sql-insert sql-returning

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

返回在UPDATE中实际更改的表的行

使用Postgres,我可以执行更新语句并返回受推荐影响的行.

UPDATE accounts
SET status = merge_accounts.status,
    field1 = merge_accounts.field1,
    field2 = merge_accounts.field2,
    etc.
FROM merge_accounts WHERE merge_accounts.uid =accounts.uid
RETURNING accounts.*
Run Code Online (Sandbox Code Playgroud)

这将为我提供与该WHERE子句匹配的所有记录的列表,但是不会告诉我操作实际更新了哪些行.

在这个简化的用例中,当然简单地添加另一个防护是微不足道的AND status != 'Closed,但是我的真实世界用例涉及从10,000个行的合并表中更新潜在的几十个字段,我希望能够检测哪些行实际上已经改变了,它们与之前的版本相同.(期望很少的行实际上会改变).

到目前为止我得到的最好的是

UPDATE accounts
SET x=..., y=...
FROM accounts as old WHERE old.uid = accounts.uid
FROM merge_accounts WHERE merge_accounts.uid = accounts.uid
RETURNING accounts, old
Run Code Online (Sandbox Code Playgroud)

这将返回一个新旧行的元组,然后可以在我的Java代码库本身内部进行区分 - 但这需要大量额外的网络流量并且可能容易出错.

理想的情况是能够让postgres返回实际有任何值更改的行 - 这可能吗?

在github上这是一个更真实的例子,我正在做的事情,结合到目前为止的一些建议.
使用Postgres 9.1,但如果需要可以使用9.4.要求是有效的

  • 能够执行新数据的upsert
  • 我们可能只知道要在任何给定行上更新的特定键/值对
  • 获取仅包含upsert实际更改的行的结果
  • 奖金 - 获取旧记录的副本.

由于这个问题已经打开,我现在已经完成了大部分工作,虽然我不确定我的方法是否是一个好主意 - 它有点被黑客攻击.

sql postgresql sql-update

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

RETURNING 导致错误:缺少表的 FROM 子句条目

我正在从 UUID 获取用户数据WHERE empl_user_pub_uuid = 'e2bb39f1f28011eab66c63cb4d9c7a34'

由于我不想进行额外的查询来获取额外的用户数据,所以我试图通过INSERT.

WITH _u AS (
    SELECT
        eu.empl_user_pvt_uuid,
        ee.email,
        ep.name_first
    FROM employees.users eu
    LEFT JOIN (
        SELECT DISTINCT ON (ee.empl_user_pvt_uuid)
            ee.empl_user_pvt_uuid,
            ee.email
        FROM employees.emails ee
        ORDER BY ee.empl_user_pvt_uuid, ee.t DESC
    ) ee ON eu.empl_user_pvt_uuid = ee.empl_user_pvt_uuid
    LEFT JOIN (
        SELECT DISTINCT ON (ep.empl_user_pvt_uuid)
            ep.empl_user_pvt_uuid,
            ep.name_first
        FROM employees.profiles ep
    ) ep ON eu.empl_user_pvt_uuid = ep.empl_user_pvt_uuid
    WHERE empl_user_pub_uuid = 'e2bb39f1f28011eab66c63cb4d9c7a34'
)
INSERT INTO employees.password_resets (empl_pwd_reset_uuid, empl_user_pvt_uuid, t_valid, for_empl_user_pvt_uuid, token)
SELECT 'f70a0346-a077-11eb-bd1a-aaaaaaaaaaaa', '6efc2b7a-f27e-11ea-b66c-de1c405de048', '2021-04-18 …
Run Code Online (Sandbox Code Playgroud)

sql postgresql greatest-n-per-group sql-insert sql-returning

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

postgres:在冲突插入时更新一行并返回旧值

我需要一个查询来更新表中的一行,但如果 id 不存在,它会插入默认值。它还必须避免线程竞争条件。

我在这里找到了一个应该没问题的答案 /sf/answers/554957021/

使用此查询:

UPDATE tbl x
SET    tbl_id = 24
     , name = 'New Gal'
FROM  (SELECT tbl_id, name FROM tbl WHERE tbl_id = 4 FOR UPDATE) y 
WHERE  x.tbl_id = y.tbl_id
RETURNING y.tbl_id AS old_id, y.name AS old_name, x.tbl_id, x.name;
Run Code Online (Sandbox Code Playgroud)

所以我认为它应该在更新后返回旧值,并且应该防止线程竞争条件。

但是,如果该行不存在,我需要添加一个插入,并且这次还返回插入的值(旧值没有意义,因为它们不存在)。

所以基本上我需要做类似的事情

INSERT INTO tbl 
    (...) VALUES (...) 
    RETURNING ..., ... 
ON CONFLICT DO
UPDATE tbl x
SET    tbl_id = 24
     , name = 'New Gal'
FROM  (SELECT tbl_id, name FROM tbl WHERE tbl_id = …
Run Code Online (Sandbox Code Playgroud)

sql postgresql insert-update race-condition select-for-update

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

是否有可能(如何?)从"更新后"触发器返回旧值

UPDATE "Users" 
SET "displayName" = 'new_name' 
WHERE id = 1 
RETURNING "displayName"
Run Code Online (Sandbox Code Playgroud)

上面的查询返回NEW值.我想知道更新后的OLDdisplayName.我知道有可能:

 UPDATE ... 
 FROM SELECT ... 
 RETURNING ...
Run Code Online (Sandbox Code Playgroud)

但我想使用AFTER UPDATE触发器.是否有可能以AFTER UPDATE某种方式从触发器"返回"旧值?如果是这样的触发器体如何?

sql postgresql sql-update postgresql-9.3

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

从PostgreSQL中的UPDATE查询返回多个值

我是编写DB函数的新手,我需要OUT在执行UPDATE查询时返回'last_login_at'的值作为参数.

这是我的功能片段:

...
LOOP
    UPDATE "user" SET 
        last_login_at = current_timestamp, 
        first_name = p_first_name,
        last_name = p_last_name,
    WHERE ext_user_id = p_ext_user_id AND platform_id = p_platform_id
    RETURNING id INTO v_user_id;
    is_new := false;
    // The next 'CASE' is not valid - Need to replace it with a valid one.  
    has_logged_in_today = CASE
     WHEN date_part('day', age(current_timestamp, last_login_at)) > 1
     THEN true
     ELSE false
     END;
    IF FOUND THEN 
        EXIT;
    END IF;
..
..
END LOOP;
Run Code Online (Sandbox Code Playgroud)

可以做多个RETURNING x INTO y …

sql postgresql plpgsql sql-update sql-returning

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