我正在构建一个工具,它将显示给定PostgreSQL数据库(客户端的遗留应用程序)中的所有表,然后用户可以深入了解并查看给定表中的所有数据。它本质上是一个数据库查看器。
下一步将允许用户以类似于Airtable中更新数据的方式更新每一行。
虽然对于大多数列而言,我将拥有主键,因此我可以使用它来构建适当的Update ... where ID=?
语句,我意识到可能并非总是如此。例如,对于某些连接表,我没有ID或任何其他主键。
我仍然希望具有用户查看从这些列显示的数据网格的功能,通过单击鼠标选择一行并提供新值。
PostgreSQL 曾经使用OID来为这种情况单点识别行,但即使对于我正在处理的遗留数据库,情况也不再如此。
我能想到的唯一解决方案是使用偏移/排序顺序来确定要更新哪一行,但如果在此期间排序更改或用户删除/添加某些行,则会导致竞争条件。
任何想法如何更新此类"匿名"行?
答案 0 :(得分:4)
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
符合<services>
<service name="themepark.Service1">
<clear />
<endpoint binding="basicHttpBinding" contract="themepark.IService1" />
</service>
</services>
,the documentation:
CTID
行表格中的行版本的物理位置。请注意,尽管可以使用ctid非常快速地定位行版本,但如果行的ctid被VACUUM FULL更新或移动,则行的ctid将会改变。因此,ctid作为长期行标识符是无用的。应该使用OID,甚至更好的用户定义的序列号来识别逻辑行。