为什么 INSERT as SELECT with NOT EXISTS 会导致独特的违规?

问题描述 投票:0回答:1

Postgres 版本是 14.10。该表没有其他任何内容(即没有行级安全性等):

create schema perf;
create table perf.dba_hist_sqltext(
  queryid bigint primary key
, query text);

我不明白的是这怎么行不通:
即使它在数据库<>小提琴上)

WITH uniqstatements AS (
    SELECT ss.queryid,
           min(ss.query) query
    FROM pg_stat_statements AS ss
    GROUP by ss.queryid )
INSERT INTO perf.dba_hist_sqltext 
SELECT ss.queryid,
       ss.query
FROM uniqstatements AS ss
WHERE NOT EXISTS (
      SELECT 'X'
      FROM perf.dba_hist_sqltext AS st
      WHERE st.queryid = ss.queryid);

enter image description here

WITH
子句为每个
queryid
返回一行。主查询应该运行
WITH
子句,然后根据要插入的目标表检查每一行,如果它不存在,则插入它。然而,正如您所看到的,有些东西没有按预期工作。

我使用内联视图而不是

WITH
子句开始此查询,并且它具有相同的错误,因此我尝试使用
WITH
子句。

我使用 SQL 已有 30 多年了,对此我感到很困惑。

NOT EXISTS
不应允许重复项进入。如果它不起作用,为什么要执行该操作。

我在这里缺少什么?

sql postgresql exists
1个回答
0
投票
  1. REINDEX INDEX dhst_queryid_pk;
    以防损坏。
  2. 如果唯一约束当前是 deferred,并发工作线程可能会抢在你之前插入,并且你只能在该语句或其所在事务的末尾才发现它。
  3. 通过 RLS 进行的混淆非常奇特,但完全有可能。
  4. 滥用
    rule
    系统
    可能会导致这种偏执,类似于长而复杂的触发器链(约束触发器也可以延迟)。

索引损坏是第一位的,因为经过仔细检查,其他所有内容通常都是可见的。此外,该示例不可重现:
db<>fiddle 的演示

create schema perf;
create table perf.dba_hist_sqltext(
  queryid bigint primary key
, query text);

create table pg_stat_statements(queryid,query)as values
(1,'select*from everything join all_else on true;');

WITH uniqstatements AS (
    SELECT ss.queryid,
           min(ss.query) query
    FROM pg_stat_statements AS ss
    GROUP by ss.queryid )
INSERT INTO perf.dba_hist_sqltext 
SELECT ss.queryid,
       ss.query
FROM uniqstatements AS ss
WHERE NOT EXISTS (
      SELECT 'X'
      FROM perf.dba_hist_sqltext AS st
      WHERE st.queryid = ss.queryid)
RETURNING *;
查询id 查询
1 select*from everything join all_else on true;
INSERT 0 1
WITH uniqstatements AS (
    SELECT ss.queryid,
           min(ss.query) query
    FROM pg_stat_statements AS ss
    GROUP by ss.queryid )
INSERT INTO perf.dba_hist_sqltext 
SELECT ss.queryid,
       ss.query
FROM uniqstatements AS ss
WHERE NOT EXISTS (
      SELECT 'X'
      FROM perf.dba_hist_sqltext AS st
      WHERE st.queryid = ss.queryid)
RETURNING *;
查询id 查询
INSERT 0 0
© www.soinside.com 2019 - 2024. All rights reserved.