Sqlite 如何在表中删除后更新某些元组
我试图在SQLite中建立一个音乐流媒体服务数据库模型,我想创建一个触发器:当一首歌曲从播放列表中删除时,它后面的每首歌曲都需要将其位置递减。我真的不知道怎么写这个触发器 下面是播放列表表格的示例(很抱歉有葡萄牙语名称。idMusica=Song ID;posicao=Song在播放列表中的位置) 为了进一步解释我想要的,这里有一个例子:Sqlite 如何在表中删除后更新某些元组,sqlite,triggers,Sqlite,Triggers,我试图在SQLite中建立一个音乐流媒体服务数据库模型,我想创建一个触发器:当一首歌曲从播放列表中删除时,它后面的每首歌曲都需要将其位置递减。我真的不知道怎么写这个触发器 下面是播放列表表格的示例(很抱歉有葡萄牙语名称。idMusica=Song ID;posicao=Song在播放列表中的位置) 为了进一步解释我想要的,这里有一个例子: 如果我从播放列表1中删除歌曲6,歌曲11的位置将变为3。我相信以下操作将如您所愿:- CREATE TRIGGER IF NOT EXISTS playli
如果我从播放列表1中删除歌曲6,歌曲11的位置将变为3。我相信以下操作将如您所愿:-
CREATE TRIGGER IF NOT EXISTS playlistreorder
AFTER DELETE ON playlist
BEGIN
UPDATE playlist SET posicao = posicao -1 WHERE posicao > old.posicao AND idPlayList = old.idPlayList;
END
;
- 注意,表名被假定为播放列表
DROP TABLE IF EXISTS playlist;
CREATE TABLE IF NOT EXISTS playlist (idMusica INTEGER, idPlayList INTEGER, posicao INTEGER);
INSERT INTO playlist (idMusica,idPlayList, posicao) VALUES
(12,1,1),(5,1,2),(6,1,3),(11,1,4),
(1,2,1),(2,2,2),(3,2,2),(4,2,4),(9,2,5)
;
CREATE TRIGGER IF NOT EXISTS playlistreorder
AFTER DELETE ON playlist
BEGIN
UPDATE playlist SET posicao = posicao -1 WHERE posicao > old.posicao AND idPlayList = old.idPlayList;
END
;
SELECT * FROM playlist;
DELETE FROM playlist WHERE posicao = 3 AND idplayList = 1;
SELECT * FROM playlist;
示例结果
重新订购前(第一次查询):-
重新排序后(第二次查询):-
我认为这种方法从根本上是错误的,过于脆弱。与其跟踪播放列表中的绝对位置,不如跟踪相对位置。这样,在插入或删除歌曲时,您就不必更新位置: 如果前三首歌曲的
posicao
值为1,2,3,并且您希望在位置2添加一首歌曲,而不是更新当前的2到3、当前的3到4等等,则在当前1和2位置的posicao
之间使用一个新值:在这种情况下为1.5
删除时,不要担心填补空白;被删除歌曲两侧的posicao
,仍按正确顺序排列
如果出于某种原因需要绝对位置,可以使用sqlite的现代版本(3.25或更高版本)在SELECT
中动态计算绝对位置,例如
SELECT idMusica, row_number() OVER (ORDER BY posicao) AS pos
FROM playlist_songs
WHERE idPlaylist = :playlistid
ORDER BY posicao
或者,每次从给定播放列表中获取一行时,只要该行是按posicao
排序的,就只需增加程序中的一个计数器
基于窗口函数的查询,用于插入到播放列表的中间并删除,给定一个绝对位置(尽管对于删除,如果您的连接表不是没有ROWID的,则更容易跟踪程序中歌曲的ROWID,并使用所选歌曲的ROWID进行删除):
INSERT INTO playlist_songs(idMusica, idPlaylist, posicao)
VALUES(:songid, :playlistid
, (SELECT (pos + prev_pos) / 2.0
FROM (SELECT posicao AS pos
, lag(posicao, 1, 0.0) OVER (ORDER BY posicao) AS prev_pos
, row_number() OVER (ORDER BY posicao) AS rn
FROM playlist_songs WHERE idPlaylist = :playlistid)
WHERE rn = :position));
DELETE FROM playlist_songs
WHERE rowid = (SELECT rowid
FROM (SELECT rowid, row_number() OVER (ORDER BY posicao) AS rn
FROM playlist_songs WHERE idPlaylist = :playlistid)
WHERE rn = :position);