Postgresql

如何以標準方式刪除沒有主鍵的記錄(即不使用 ctid)

  • March 7, 2022

使用案例

我們有一個沒有包含兩列(日期、事件)的 PK 的日誌表;

您插入了一行。然後你想撤消插入的記錄。

有沒有辦法刪除該行(不刪除具有相同數據的其他行),不使用僅 postgres 的功能?

我想要一個在另一個數據庫中工作的解決方案(它不需要完全標準,它只能在一個數據庫中:Sqlite、Oracle、MySql 或 SQLServer)。

例子:

create table the_log(
 date date,
 event_id integer
);

insert into the_log(date, event_id) values ('2019-09-21',1),('2019-09-21',1);

select * from the_log;

我的攻擊:

delete from the_log where row_number() over ()=1;

delete from the_log limit 1;

with the_log_2 as (select *, row_number() over () as version from prueba_sin_clave)
delete from the_log_2 where version=1;

我認為答案是否定的。我想知道我是否錯了,或者在我閱讀的哪些文件中我是對的。

**注意:**這會使您失去數據,因此請考慮使用事務塊。

我認為這是更通用的解決方案:

如果您認為要刪除的行是:

select * from the_log limit 1 

那麼如果您有一列具有唯一值…

delete from the_log  
where unique_the_log_column in 
(select unique_log_column from the_log limit 1); 

如果您沒有唯一列,但有兩列合併生成唯一值:

delete from the_log  
where (col1, col2) in (select col1, col2 from the_log limit 1); 

其中 any_the_log_column 是該表中具有唯一值的列。

這可能會刪除任何 dbms 中日誌表的第一行 - 如果列中的數據不重複,但請記住,有時在某些數據庫中未選擇按順序選擇表,因此您必須在此表中有一個 id…

考慮創建一個 id 列並將其增加表中的行數,基於日期或其他內容,如果您不想在未來受到傷害……

如果您只是想消除完全重複的行(只保留一個實例),那麼沒有一種完全與 RDBMS 無​​關的方法可以做到這一點。 DELETE ... ORDER BY ... LIMIT適用於 MySQL,但不適用於其他一些。在 Oracle 上,您可以使用隱藏的ROWID.

完成重複數據刪除的一種解決方案應該在幾乎任何 RDBMS 中都可以工作,而無需使用任何專有/慣用特性,這是該算法:

  1. 辨識完全重複的行。
  2. 將重複的行內容(但每個內容只有一個副本)放入臨時表中。
  3. 事務內:刪除原表中的重複行。將臨時表中的所有內容複製到原始表中。

這是一個工作範例(用於 MySQL)。通過細微的語法變化,您可以在任何 RDBMS 上進行這項工作。

CREATE TABLE the_log (
 date date,
 event_id integer
);

INSERT INTO the_log (date, event_id)
 VALUES ('2019-09-21',1),('2019-09-21',1);

SELECT * FROM the_log;

從兩個完全重複的行開始。

+------------+----------+
| date       | event_id |
+------------+----------+
| 2019-09-21 |        1 |
| 2019-09-21 |        1 |
+------------+----------+

CREATE TEMPORARY TABLE the_log_duplicates LIKE the_log;

INSERT INTO the_log_duplicates
 SELECT date, event_id
 FROM the_log
 GROUP BY date, event_id
 HAVING count(*) > 1;

START TRANSACTION;

DELETE the_log
 FROM the_log
 JOIN the_log_duplicates
 USING (date, event_id);

INSERT INTO the_log
 SELECT * FROM the_log_duplicates;

COMMIT;

DROP TEMPORARY TABLE the_log_duplicates;

SELECT * FROM the_log;

看,您的重複行現在是一個。

+------------+----------+
| date       | event_id |
+------------+----------+
| 2019-09-21 |        1 |
+------------+----------+

引用自:https://dba.stackexchange.com/questions/218282