Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để chúng tôi kiểm soát thứ tự động theo Trường trong bảng?

Nếu tôi hiểu bạn đúng, bạn cần một cách để quản lý đúng chuỗi các giá trị ở vị trí position khi bạn chèn câu hỏi mới, thay đổi vị trí của câu hỏi hiện có hoặc xóa câu hỏi.

Giả sử bạn có DDL sau trong bảng câu hỏi của mình:

CREATE TABLE `questions` (
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `question` VARCHAR(256) DEFAULT NULL,
    `position` INT(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
);

và tập dữ liệu ban đầu như thế này

+----+------------+----------+
| id | question   | position |
+----+------------+----------+
|  1 | Question 1 |        1 |
|  2 | Question 2 |        2 |
|  3 | Question 3 |        3 |
+----+------------+----------+

Để nhận danh sách câu hỏi theo thứ tự bạn làm rõ ràng

SELECT * 
  FROM questions 
 ORDER BY position;

Để chèn một câu hỏi mới vào cuối danh sách câu hỏi bạn làm gì

INSERT INTO questions (question, position) 
SELECT 'New Question', COALESCE(MAX(position), 0) + 1
  FROM questions;

Kết quả sẽ là:

+----+--------------+----------+
| id | question     | position |
+----+--------------+----------+
|  1 | Question 1   |        1 |
|  2 | Question 2   |        2 |
|  3 | Question 3   |        3 |
|  4 | New Question |        4 |
+----+--------------+----------+

Để chèn một câu hỏi mới vào một vị trí cụ thể (giả sử ở vị trí 3) trong danh sách, bạn làm điều đó với hai truy vấn:

UPDATE questions
   SET position = position + 1
 WHERE position >= 3;

INSERT INTO questions (question, position) 
VALUES ('Another Question', 3);

Bây giờ bạn có

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  2 | Question 2       |        2 |
|  5 | Another Question |        3 |
|  3 | Question 3       |        4 |
|  4 | New Question     |        5 |
+----+------------------+----------+

Để hoán đổi vị trí của hai câu hỏi (ví dụ:câu hỏi với id 2 và 5) bạn thực hiện

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

Hãy xem những gì chúng tôi có

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  5 | Another Question |        2 |
|  2 | Question 2       |        3 |
|  3 | Question 3       |        4 |
|  4 | New Question     |        5 |
+----+------------------+----------+

Đó chính xác là những gì bạn làm khi người dùng nhấp vào các nút lên và xuống của bạn, cung cấp id câu hỏi chính xác.

Bây giờ, nếu bạn muốn giữ trình tự vị trí của mình không có khoảng trống khi xóa câu hỏi, bạn có thể làm điều đó.

Để xóa khỏi cuối danh sách bạn sử dụng thao tác xóa đơn giản

DELETE FROM questions WHERE id=4;

Kết quả

+----+------------------+----------+
| id | question         | position |
+----+------------------+----------+
|  1 | Question 1       |        1 |
|  5 | Another Question |        2 |
|  2 | Question 2       |        3 |
|  3 | Question 3       |        4 |
+----+------------------+----------+

Xóa câu hỏi ở giữa (hoặc đầu) danh sách đòi hỏi nhiều công việc hơn. Giả sử chúng tôi muốn xóa câu hỏi có 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;

Và cuối cùng chúng tôi có

+----+--------------+----------+
| id | question     | position |
+----+--------------+----------+
|  1 | Question 1   |        1 |
|  2 | Question 2   |        2 |
|  3 | Question 3   |        3 |
+----+--------------+----------+

CẬP NHẬT :Để giúp cuộc sống của chúng ta dễ dàng hơn, chúng ta có thể gói gọn tất cả trong các thủ tục được lưu trữ

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 ;

và sử dụng chúng như thế này:

-- 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);



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lưu trữ giá trị băm SHA1 trong MySQL

  2. Sự cố với JPA, EclipseLink và mysql phân biệt chữ hoa chữ thường

  3. Chỉ mục (dựa trên không) phải lớn hơn hoặc bằng 0

  4. Làm cách nào để sửa đổi một cột MySQL để cho phép NULL?

  5. Chèn một danh sách đơn giản vào bảng MySQL (php)