让我们假设一个多租户应用程序包含以下表格:
person (tenant_id, id, status, name, company_id)
company (tenant_id, id, name)
更新人员条目时,以下约束适用:
company_id
必须存在且tenant_id
必须匹配status
必须有效我目前正在使用一个考虑所有约束的查询:
UPDATE person
SET person.company_id = 100
WHERE person.tenant_id = 'A'
AND person.id = 1
AND person.status = 10
AND EXISTS (SELECT TRUE FROM company WHERE company.tenant_id='A' and company.id=100)
查询的输出表示已更新的行数。
在没有更新行的情况下,我想知道根本原因。是因为:
id
(在我的情况下,这是我的主键)不存在。id
已存在,但status
不正确。company_id
不存在。这将允许我返回相应的错误消息。
你认为最好是:
SELECT id, status, name FROM person WHERE tenant_id = 'A' AND id = 1
如果未找到任何条目,我可以立即返回404。
如果找到条目,我可以检查status
是否有效。如果它无效,我可以返回错误消息。
company
对象存在SELECT id, name FROM company WHERE tenant_id = 'A' AND id = 100
如果它不存在,我可以返回错误信息。
如果是,我可以尝试进行更新。
运行包含所有约束的初始查询,因为自步骤1以来数据可能已更改。
优点:没有?
缺点:多个数据库调用,进程较慢,数据可以在此过程中更改。
在这里,我尝试保持乐观并立即运行初始查询,因为大多数时候数据都是有效的。
我进行了额外的查询(与上面相同),只有在数据无效时才知道根本原因。
在我运行初始查询和上次查询的时间之间,数据可能仍会发生变化。
优点:数据有效时更快
缺点:如果发生错误,可以进行多次数据库调用,在此过程中可以更改数据。
这样可以解决“数据更改”问题,但我想避免使用存储过程。
优点:进行一次数据库调用
缺点:数据库工作负载
答案 0 :(得分:0)
尝试使用
UPDATE person
SET person.company_id = 100
WHERE person.tenant_id = 'A'
AND person.id = 1
AND person.status = 10
AND EXISTS (SELECT id FROM company WHERE company.tenant_id='A' and company.id=100)
答案 1 :(得分:0)
从性能的角度来看,最有可能的是“先运行整个查询并尝试查找之后的原因”是您的最佳选择,其中“之后”表示“仅在案例中”当事实证明没有更新行“。
这是基于这样的“失败”将相对罕见的假设,并且该假设本身基于以下假设:用于识别要更新的行的选择标准将相对最近建立。 (如果是5天前的一批数据,情况可能略有不同。)
(我可能还想从功能的角度来看,尝试将错误消息提升到你想要的精度水平是相对不常见的,原因是它总是变得比你想象的更“复杂”而且比你想象的要复杂得多。)