我正在构建一个工具,它将显示给定的PostgreSQL数据库(客户端的遗留应用程序)中的所有表,然后用户将深入挖掘,并可以查看给定表中的所有数据。它本质上是一个数据库查看器。
下一步将允许用户以与Airtable中的数据更新方式类似的方式更新每一行。
虽然对于大多数列我会有主键,所以我可以用来构建适当的Update ... where ID=?
语句,我意识到可能并非总是如此。例如,对于某些连接表,我没有ID或任何其他主键。
我仍然希望具有用户查看从这些列显示的数据网格的功能,通过单击鼠标选择一行并提供新值。
PostgreSQL曾经使用OID来为这种情况单点识别行,但即使对于我正在处理的遗留数据库,情况也不再如此。
我能想到的唯一解决方案是使用偏移/排序顺序来确定要更新哪一行,但如果在此期间排序更改或用户删除/添加某些行,则会导致竞争条件。
我有什么想法可以更新这样的“匿名”行吗?
Postgres中的每个表都有一个系统列ctid
,它明确地标识了一行。例:
drop table if exists my_table;
create table my_table(id int, str text);
insert into my_table values
(1, 'one'),
(1, 'two'),
(2, 'one');
select ctid, *
from my_table;
ctid | id | str
-------+----+-----
(0,1) | 1 | one
(0,2) | 1 | two
(0,3) | 2 | one
(3 rows)
您可以使用delete
或update
中的列:
delete from my_table
where ctid = '(0,2)'
returning *
id | str
----+-----
1 | two
(1 row)
DELETE 1
但请注意,根据ctid
,无法保证一行始终具有相同的the documentation:
CTID
行版本在其表中的物理位置。请注意,尽管可以使用ctid非常快速地定位行版本,但如果行的ctid被VACUUM FULL更新或移动,则行的ctid将会改变。因此,ctid作为长期行标识符是无用的。应该使用OID,甚至更好的用户定义的序列号来标识逻辑行。