Postgresql
如何以標準方式刪除沒有主鍵的記錄(即不使用 ctid)
使用案例
我們有一個沒有包含兩列(日期、事件)的 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 中都可以工作,而無需使用任何專有/慣用特性,這是該算法:
- 辨識完全重複的行。
- 將重複的行內容(但每個內容只有一個副本)放入臨時表中。
- 事務內:刪除原表中的重複行。將臨時表中的所有內容複製到原始表中。
這是一個工作範例(用於 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 | +------------+----------+