Sql 更新/删除列中没有主键的任意行

Sql 更新/删除列中没有主键的任意行,sql,postgresql,Sql,Postgresql,我正在构建一个工具,该工具将显示给定PostgreSQL数据库(客户端的遗留应用程序)中的所有表,然后用户将深入其中,可以看到给定表中的所有数据。它本质上是一个数据库查看器 下一步将允许用户以类似于更新Airtable中数据的方式更新每一行 而对于大多数列,我都有主键,因此我可以使用它来构建适当的Update。。。其中ID=?语句,我意识到情况并非总是如此。例如,对于某些联接表,我没有ID或任何其他主键 我仍然希望有这样的功能,用户可以查看这些列中显示的数据网格,通过单击鼠标选择一行并提供新值

我正在构建一个工具,该工具将显示给定PostgreSQL数据库(客户端的遗留应用程序)中的所有表,然后用户将深入其中,可以看到给定表中的所有数据。它本质上是一个数据库查看器

下一步将允许用户以类似于更新Airtable中数据的方式更新每一行

而对于大多数列,我都有主键,因此我可以使用它来构建适当的
Update。。。其中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 from my_table
where ctid = '(0,2)'
returning *

 id | str 
----+-----
  1 | two
(1 row)

DELETE 1
但是请注意,不能保证每行始终具有相同的
ctid

ctid

行版本在其表中的物理位置。请注意,尽管ctid可用于快速定位行版本,但如果行的ctid被更新或移动,则该行的ctid将发生更改。因此,ctid作为长期行标识符是无用的。OID,或者更好的是用户定义的序列号,应该用于标识逻辑行


我想有一个名为
ctid
的专栏,对我来说可能会有帮助。