当前位置: 首页 > 面试题库 >

在以下语句完成之前,不提交CTE删除

徐晔
2023-03-14
问题内容

我遇到的问题是,删除的数据稍后仍会出现在同一查询中。自然,在完全独立的查询中,不会显示已删除的数据。

这不是我的用例,但是我认为这是显示问题的最简单方法:

CREATE TABLE company (id INT PRIMARY KEY, name TEXT);
CREATE TABLE employee (id INT PRIMARY KEY, company_id INT REFERENCES company(id), name TEXT);

INSERT INTO company VALUES (1, 'first company');
INSERT INTO company VALUES (2, 'second company');

INSERT INTO employee VALUES (1, 1, 'first employee');
INSERT INTO employee VALUES (2, 2, 'second employee');

-- this select can successfully query for the data which has just been deleted
WITH deleted_employee AS (DELETE FROM employee WHERE id = 1 RETURNING id)
SELECT id, name FROM employee JOIN deleted_employee USING (id);

-- this select shows it has been deleted
SELECT * FROM employee;

我把它放在这里了。

DELETE在整个查询完成之前,似乎没有提交正义,这感觉很奇怪,因为优先级要求DELETE发生在之前SELECT

有什么方法可以在单个查询中实现此目标吗?

编辑

答案已经回答了直接的问题。根本的问题是,如果没有更多与该公司关联的员工,则删除该员工然后删除其关联的公司。

这是我可以解决的查询:

WITH affected_company AS (DELETE FROM employee WHERE id = 1 RETURNING company_id)
DELETE FROM company
USING affected_company
WHERE NOT EXISTS (
  SELECT 1
  FROM employee
  WHERE company_id = affected_company.company_id
);

SELECT * FROM company;
SELECT * FROM employee;

和更新的小提琴。

您可以看到该公司没有被删除。


问题答案:

这是预期的并有文件记录。

引用手册

WITH中的子语句彼此并与主查询并发执行。因此,在WITH中使用数据修改语句时,指定更新实际发生的顺序是不可预测的。所有语句都使用相同的快照执行(请参见第13章),
因此它们不能“彼此”影响目标表 。这减轻了行更新实际顺序的不可预测性的影响,并且意味着RETURNING数据
是在不同的WITH子语句与主查询之间传递更改的唯一途径

(强调我的)

可以 使用链接的CTE删除公司:

with deleted_emp as (
  delete from employee 
  where id = 1 
  returning company_id, id as employee_id
)
delete from company
where id in (select company_id from deleted_emp) 
  and not exists (select * 
                  from employee e
                     join deleted_emp af 
                       on af.company_id = e.company_id 
                      and e.id <> af.employee_id)

重要的是从not exists子查询中排除刚删除的员工,因为这在第二个delete语句中始终可见,因此不存在永远不会为真。因此,子查询从本质上检查是否存在除分配给同一公司的已删除员工以外的其他员工。

在线示例:https://rextester.com/IVZ78695



 类似资料:
  • 问题内容: 表单在validateUsername函数之前提交时遇到问题,有机会在服务器端完成用户名检查。 仅在validateUsername函数完成后才如何提交表单?希望这很清楚… 问题答案: Olafur答案的更详细的版本-进行AJAX调用,函数无需等待就返回。 提交表单之前,回调不会结束。 您应该做的是让按钮/触发调用AJAX验证,并且回调应该提交表单而不是返回true。

  • 问题内容: 基本上我有(忽略异常处理等): 如果我理解正确,那应该不会有任何影响,因为它真正所做的只是为GC释放了资源。特别是对于Derby:不再需要语句,结果集和连接时,应明确关闭它们。与Derby的连接是应用程序外部的资源,并且垃圾收集器不会自动关闭它们。 但是,这会导致交易出现任何问题吗?我认为交易不依赖于该声明。有人可以确认吗? 问题答案: 绝对可以关闭它们,应该这样做。

  • 说明 协议2.1中读取state=2,3的结账请求后,从业务系统完成结账,并提交结果到服务端 请求地址 http://api.dc78.cn/Api/cash_post_cash 请求方式 GET 请求参数 参数 参数名称 必填 描述 范例 id 请求编号 此编号为协议2.1中返回的结算单id bzid 结算业务单号 返回 {"status":1,"info":"提交成功"} 请求方式 INI 请

  • 秒付业务,下行接口收到cash-pay后(下行接口详见0.5),完成相应的结账业务流程,并上传确认支付订单处理完成。 请求参数说明 参数 描述 必填 示例值 类型 最大长度 action 接口参数组 是 object └action 需要调用的接口名称 是 cash_post_cash string get GET参数组,本组参数需要参与签名 是 object └id 支付单流水号payid 是

  • 从for, foreach, if..elseif...else, try...catch...finally, while...do, do...while中快速提取或删除代码 提取或删除代码的时候,被绿色选中的是要提取的内容,被红色选中的是要被删除的内容. 操作步骤: 菜单栏: Code —> Unwrap\/Remove 快捷键: Mac: command + shift + Delete

  • 嗨,我正在用spring boot hibernate测试MySQL中的记录删除-插入-删除操作,我注意到一个问题,当插入发生时,记录似乎没有被完全删除。 3在hibernate kickstart上创建初始记录(通过类路径中的data.sql) 操作为 (1)创建的初始记录 (2)删除所有记录 (3)添加新记录 (4)删除所有记录 当执行断言时,发现结果列表中仍然包含最后一条记录,因此断言失败。