Hvis jeg forstår dig rigtigt, har du brug for en måde til korrekt at administrere rækkefølgen af værdier i position
kolonne, når du indsætter nye spørgsmål, ændrer placeringen af et eksisterende eller sletter spørgsmål.
Lad os sige, at du har følgende DDL i din spørgsmålstabel:
CREATE TABLE `questions` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`question` VARCHAR(256) DEFAULT NULL,
`position` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
og indledende datasæt som dette
+----+------------+----------+
| id | question | position |
+----+------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
+----+------------+----------+
For at få ordnet liste med spørgsmål du gør indlysende
SELECT *
FROM questions
ORDER BY position;
For at indsætte et nyt spørgsmål til slutningen af spørgsmålslisten du gør
INSERT INTO questions (question, position)
SELECT 'New Question', COALESCE(MAX(position), 0) + 1
FROM questions;
Resultatet bliver:
+----+--------------+----------+
| id | question | position |
+----+--------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
| 4 | New Question | 4 |
+----+--------------+----------+
For at indsætte et nyt spørgsmål til en bestemt position (lad os sige til position 3) i listen gør du det med to forespørgsler:
UPDATE questions
SET position = position + 1
WHERE position >= 3;
INSERT INTO questions (question, position)
VALUES ('Another Question', 3);
Nu har du
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 5 | Another Question | 3 |
| 3 | Question 3 | 4 |
| 4 | New Question | 5 |
+----+------------------+----------+
Sådan skifter du placering af to spørgsmål (f.eks. spørgsmål med id 2 og 5) gør du
UPDATE questions AS q1 INNER JOIN
questions AS q2 ON q1.id = 2 AND q2.id = 5
SET q1.position = q2.position,
q2.position = q1.position
Lad os se, hvad vi har
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 5 | Another Question | 2 |
| 2 | Question 2 | 3 |
| 3 | Question 3 | 4 |
| 4 | New Question | 5 |
+----+------------------+----------+
Det er præcis, hvad du gør, når brugeren klikker på dine op- og ned-knapper og leverer korrekte spørgsmål-id'er.
Hvis du nu vil beholde din positionsrækkefølge uden huller, når du sletter spørgsmål, kan du gøre det.
For at slette fra slutningen af listen du bruger simpel slet
DELETE FROM questions WHERE id=4;
Resultater
+----+------------------+----------+
| id | question | position |
+----+------------------+----------+
| 1 | Question 1 | 1 |
| 5 | Another Question | 2 |
| 2 | Question 2 | 3 |
| 3 | Question 3 | 4 |
+----+------------------+----------+
Sletning af et spørgsmål i midten (eller begyndelsen) af listen kræver mere arbejde. Lad os sige, at vi vil slette spørgsmålet med id=5
-- Get the current position of question with id=5
SELECT position FROM questions WHERE id=5;
-- Position is 2
-- Now delete the question
DELETE FROM questions WHERE id=5;
-- And update position values
UPDATE questions
SET position = position - 1
WHERE position > 2;
Og endelig har vi
+----+--------------+----------+
| id | question | position |
+----+--------------+----------+
| 1 | Question 1 | 1 |
| 2 | Question 2 | 2 |
| 3 | Question 3 | 3 |
+----+--------------+----------+
OPDATERING :For at gøre vores liv nemmere kan vi pakke det hele ind i lagrede procedurer
DELIMITER $$
CREATE PROCEDURE add_question (q VARCHAR(256), p INT)
BEGIN
IF p IS NULL OR p = 0 THEN
INSERT INTO questions (question, position)
SELECT q, COALESCE(MAX(position), 0) + 1
FROM questions;
ELSE
UPDATE questions
SET position = position + 1
WHERE position >= p;
INSERT INTO questions (question, position)
VALUES (q, p);
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE swap_questions (q1 INT, q2 INT)
BEGIN
UPDATE questions AS qs1 INNER JOIN
questions AS qs2 ON qs1.id = q1 AND qs2.id = q2
SET qs1.position = qs2.position,
qs2.position = qs1.position;
END$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE delete_question (q INT)
BEGIN
SELECT position INTO @cur_pos FROM questions WHERE id=q;
SELECT MAX(position) INTO @max FROM questions;
DELETE FROM questions WHERE id=q;
IF @cur_pos <> @max THEN
UPDATE questions
SET position = position - 1
WHERE position > @cur_pos;
END IF;
END$$
DELIMITER ;
og brug dem sådan her:
-- Add a question to the end of the list
CALL add_question('How are you today?', 0);
CALL add_question('How are you today?', NULL);
-- Add a question at a specific position
CALL add_question('How do you do today?', 3);
-- Swap questions' positions
CALL swap_questions(1, 7);
-- Delete a question
CALL delete_question(2);