我正在尝试在SQLite中建立音乐流服务数据库的模型,我想创建此触发器:从播放列表中删除歌曲时,其后的每一首歌曲的位置都必须降低。我不太确定如何编写此触发器。
这是播放列表的一个示例(对不起,葡萄牙的名字。idMusica =歌曲ID; posicao =歌曲在播放列表中的位置)
为了进一步解释我想要的内容,这里有一个例子: 如果我从播放列表1中删除歌曲6,则歌曲11的位置将变为3。
答案 0 :(得分:1)
我相信以下内容可以满足您的要求:-
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;
答案 1 :(得分:0)
我认为这种方法从根本上是错误的,而且过于脆弱。而不是跟踪播放列表中的绝对位置,而是跟踪相对位置。这样,您在插入或删除歌曲时就不必更新位置:
如果前三首歌曲的posicao
值为1,2,3,并且您想在位置2添加歌曲,而不是将当前的2更新为3,将当前的3更新为4,依此类推,请在当前1和2位置的posicao
的中间使用一个新值:在这种情况下为1.5。
删除时,不用担心填补空白;删除的歌曲两侧的posicao
的顺序仍然正确。
如果出于某种原因需要绝对位置,则可以SELECT
中使用现代版本的sqlite(3.25或更高版本)以及类似的内容动态计算它
SELECT idMusica, row_number() OVER (ORDER BY posicao) AS pos
FROM playlist_songs
WHERE idPlaylist = :playlistid
ORDER BY posicao
或者每次您从给定的播放列表中获取一行时,只要在程序中增加一个计数器,只要posicao
对其进行排序即可。
基于窗口函数的查询,用于插入到播放列表的中间并在给定绝对位置的情况下进行删除(尽管要删除,但如果联结表不是WITHOUT 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);