SQLite Restrict/Update/cascade

SQLite Restrict/Update/cascade

"should not be able delete movie if there are any linked data present",
    async done => {
      const movieId = 100;
      const query = 
      `DELETE FROM ${MOVIES}
      WHERE id = ${movieId}`;
"should be able to delete movie",
    async done => {
      const movieId = 5915;
      const query = `DELETE FROM ${MOVIES}
      WHERE id = ${movieId}`;

所以我有这两行,但我想在第二个删除而不是在第一个删除,我知道它与更新、级联、删除、限制有关,但我无法弄清楚或找到更多信息现在...后端看起来像

const CREATE_MOVIE_GENRES_TABLE = `
CREATE TABLE ${MOVIE_GENRES} (
  movie_id integer NOT NULL REFERENCES movies(id) ON DELETE RESTRICT ON UPDATE CASCADE,
  genre_id integer NOT NULL REFERENCES genres(id) ON DELETE RESTRICT,
  Primary key (movie_id, genre_id)
)`;

超过一部电影 tables

我知道我从电影中删除的部分肯定是错误的...而且我也想不出创建 table 部分的正确方法

简而言之,你所拥有的似乎没问题。

假设 100 通过 [=77 映射 到一种或多种流派=] table(第一个)并且 5915 未映射 通过movies_genres table 然后:-

  • 由于外键约束冲突,第一个 DELETE FROM movies WHERE id=100 将失败
  • 第二个DELETE FROM movies WHERE id=5915将删除电影。
  • 正在更新 100,将 ID 设置为 999,例如UPDATE movies SET id=999 WHERE id=100 将工作 并且更新将传播到 movies_genres movie_id 为 100 的行将其设置为 999.
  • 正在更新 5915,将 ID 设置为 55555,例如UPDATE movies SET id=55555 WHERE id=5915 会工作 ,movies_genres 中没有行 movie_id 为 5195。

但是,如果 5915 有映射并且您想强制删除它,那么您必须从 movie_genres table 中删除映射,然后删除 5915 例如

DELETE FROM movie_genres WHERE movie_id=5915;

其次是

DELETE FROM movies WHERE id=5915;

演示

为了证明以上内容(注意 updates/deletions 的顺序适合单个 运行):-

DROP TABLE IF EXISTS movie_genres;
DROP TABLE IF EXISTS movies;
DROP TABLE IF EXISTS genres;

CREATE TABLE IF NOT EXISTS movies (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE IF NOT EXISTS genres (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE movie_genres (
  movie_id integer NOT NULL REFERENCES movies(id) ON DELETE RESTRICT ON UPDATE CASCADE,
  genre_id integer NOT NULL REFERENCES genres(id) ON DELETE RESTRICT,
  Primary key (movie_id, genre_id)
);

INSERT INTO movies VALUES (100,'Movie100'),(5915,'Movie5915'),(10,'Movie10');
INSERT INTO genres VALUES (1,'Genre1'),(2,'Genre2'),(3,'Genre3');
INSERT INTO movie_genres VALUES /* map movie 100 genre 1*/ (100,1), /* extras */(10,1),(10,2),(10,3);

UPDATE movies SET id = 55555 WHERE id = 5915;
UPDATE movies SET id = 999 WHERE id = 100;
/* reset id's */
UPDATE movies SET id=5915 WHERE id=5555;
UPDATE movies SET id=100 WHERE id=999;

/* Will delete as 5915 has no genres */
DELETE FROM movies WHERE id = 5915;

/* Reapply 5915 that was deleted and add mapppings to genres */
INSERT INTO movies VALUES (5915,'Movie5915');
INSERT INTO movie_genres VALUES /* map movie 5915 genre 1,2 and 3*/ (5915,1),(5915,2),(5915,3);

/* Force delete 5915 by-passing FK conflict i.e. doing the equivalent of cascade before deletion */
DELETE FROM movie_genres WHERE movie_id=5915;
DELETE FROM movies WHERE id= 5915;

/* DELETE WILL FAIL due to FK conflict */
DELETE FROM movies WHERE id = 100;

运行 以上消息日志:-

DROP TABLE IF EXISTS movie_genres
> OK
> Time: 0.186s


DROP TABLE IF EXISTS movies
> OK
> Time: 0.12s


DROP TABLE IF EXISTS genres
> OK
> Time: 0.074s


CREATE TABLE IF NOT EXISTS movies (id INTEGER PRIMARY KEY, name TEXT)
> OK
> Time: 0.084s


CREATE TABLE IF NOT EXISTS genres (id INTEGER PRIMARY KEY, name TEXT)
> OK
> Time: 0.122s    

CREATE TABLE movie_genres (
  movie_id integer NOT NULL REFERENCES movies(id) ON DELETE RESTRICT ON UPDATE CASCADE,
  genre_id integer NOT NULL REFERENCES genres(id) ON DELETE RESTRICT,
  Primary key (movie_id, genre_id)
)
> OK
> Time: 0.169s


INSERT INTO movies VALUES (100,'Movie100'),(5915,'Movie5915'),(10,'Movie10')
> Affected rows: 3
> Time: 0.084s


INSERT INTO genres VALUES (1,'Genre1'),(2,'Genre2'),(3,'Genre3')
> Affected rows: 3
> Time: 0.084s


INSERT INTO movie_genres VALUES /* map movie 100 genre 1*/ (100,1), /* extras */(10,1),(10,2),(10,3)
> Affected rows: 4
> Time: 0.084s



UPDATE movies SET id = 55555 WHERE id = 5915
> Affected rows: 1
> Time: 0.084s


UPDATE movies SET id = 999 WHERE id = 100
> Affected rows: 1
> Time: 0.096s

/* reset id's */
UPDATE movies SET id=5915 WHERE id=5555
> Affected rows: 0
> Time: 0s


UPDATE movies SET id=100 WHERE id=999
> Affected rows: 1
> Time: 0.096s


/* Will delete as 5915 has no genres */
DELETE FROM movies WHERE id = 5915
> Affected rows: 0
> Time: 0s


/* Reapply 5915 */
INSERT INTO movies VALUES (5915,'Movie5915')
> Affected rows: 1
> Time: 0.083s


INSERT INTO movie_genres VALUES /* map movie 5915 genre 1,2 and 3*/ (5915,1),(5915,2),(5915,3)
> Affected rows: 3
> Time: 0.096s


/* Force delete 5915 by-passing FK conflict i.e. doing the equivalent of cascade before deletion */
DELETE FROM movie_genres WHERE movie_id=5915
> Affected rows: 3
> Time: 0.107s


DELETE FROM movies WHERE id= 5915
> Affected rows: 1
> Time: 0.084s


/* Nothing to delete due to id change */
DELETE FROM movies WHERE id = 100
> FOREIGN KEY constraint failed
> Time: 0.003s