2011-12-07 30 views
12

Tôi có một bảng với chỉ số duy nhất trên hai cột, id_parent và SORT_ORDER để được chính xácMysql tạm thời ngăn chặn chỉ số duy nhất

+----+-----------+------------+-------------+-------------+-------------+ 
| id | id_parent | sort_order | some_data | other_data | more_data | 
+----+-----------+------------+-------------+-------------+-------------+ 
| 1 |   1 |   1 | lorem ipsum | lorem ipsum | lorem ipsum | 
| 2 |   1 |   2 | lorem ipsum | lorem ipsum | lorem ipsum | 
| 3 |   1 |   3 | lorem ipsum | lorem ipsum | lorem ipsum | 
+----+-----------+------------+-------------+-------------+-------------+ 

Bây giờ tôi muốn cập nhật chúng, dữ liệu của họ và SORT_ORDER của họ trong một đi. sort_order sẽ thay đổi từ 1 - 2 - 3 thành, ví dụ: 2 - 3 - 1.

Nhưng khi tôi bắt đầu chạy báo cáo cập nhật, chỉ mục duy nhất chặn tôi, đúng như mong đợi, nói rằng tôi không thể có hai hàng với id_parent = 1 and sort_order = 2. Vâng, tôi có thể đặt nó 4 cho bây giờ, cập nhật các hàng khác theo thứ tự chính xác, và sau đó thiết lập này. Nhưng sau đó, tôi sẽ phải chạy một câu lệnh bổ sung và hầu hết có thể thêm logic bổ sung vào ngôn ngữ kịch bản lệnh của tôi để xác định thứ tự cập nhật chính xác. Tôi cũng sử dụng ORM, và nó thậm chí còn trở nên bất tiện hơn.

Câu hỏi của tôi bây giờ, có cách nào để làm cho mysql tạm thời bỏ qua chỉ mục này không? Giống như bắt đầu một giao dịch đặc biệt, trong đó chỉ mục nào sẽ được tính toán ngay trước khi cam kết giao dịch?

+0

Bảng của bạn có phải là InnoDB hay không MyISAM? – Pacerier

Trả lời

6

Theo như tôi biết điều đó là không thể.

Lần duy nhất tôi thấy mọi thứ như thế là bạn có thể vô hiệu hóa các khóa không duy nhất trên các bảng myisam. Nhưng không phải trên InnoDB và không phải trên các phím độc đáo.

Tuy nhiên, để lưu bạn một hoặc hai bản cập nhật, bạn không cần phải có số chính xác 1, 2 và 3. Bạn cũng có thể có 4, 5 và 6. Phải không? Bạn sẽ sử dụng nó theo thứ tự và không có gì khác để các con số chính xác không quan trọng. Nó thậm chí sẽ giúp bạn tiết kiệm một bản cập nhật nếu bạn thông minh. Từ ví dụ của bạn

update table set sort_order = 4 where sort_order = 1 and id = 1 and id_parent = 1; 

Thứ tự sắp xếp mới là 2, 3, 1. Và chỉ trong một lần cập nhật.

+1

Xấu hổ với tôi, sử dụng 4-5-6 là rất đáng ghét. – Nameless

+0

Đồng ý về điều đó là không thể với nhiều cập nhật. Tuy nhiên việc cập nhật chúng trong một câu lệnh có thể hoạt động. Dù bằng cách nào, nó là 1 cho một giải pháp rõ ràng và đơn giản. –

4

‘Nhưng khi tôi bắt đầu chạy cập nhật báo cáo ...’ - Tôi hiểu, bạn đã cố gắng cập nhật các giá trị sử dụng nhiều câu lệnh UPDATE, giống như trong một vòng lặp. Là vậy sao? Làm thế nào về việc cập nhật chúng trong một lần? Như thế này, ví dụ:

UPDATE atable 
SET sort_order = CASE sort_order WHEN 3 THEN 1 ELSE sort_order + 1 END 
WHERE id_parent = 1 
    AND sort_order BETWEEN 1 AND 3 

Một tuyên bố duy nhất là nguyên tử, vì vậy, vào thời điểm cập nhật này kết thúc, các giá trị của sort_order, mặc dù đã thay đổi, vẫn độc đáo.

Tôi không thể kiểm tra điều này trong MySQL, xin lỗi, nhưng nó chắc chắn hoạt động trong SQL Server, và tôi tin rằng hành vi tôn trọng các tiêu chuẩn.

+0

Đã không nghĩ về nó. Tuy nhiên, sẽ là nỗi đau khi sử dụng với ORM. Đây là câu trả lời đúng hơn về câu hỏi được chỉ định sau đó trả lời bởi Andreas, nhưng có lẽ tôi sẽ kết thúc bằng lời khuyên của anh ấy. Tôi nên làm gì với câu trả lời đã chọn trong trường hợp này? Cung cấp cho nó để trả lời tôi sẽ sử dụng, hoặc để trả lời đó là gần gũi hơn về chủ đề? – Nameless

+0

Vâng, trong trường hợp khi có nhiều hơn một câu trả lời phù hợp với câu hỏi * *, có lẽ bạn nên đi với câu hỏi mà bạn sẽ áp dụng để giải quyết vấn đề * thực tế *. Vì vậy, nó có thể là câu trả lời của Andreas mà bạn nên chọn. Tuy nhiên, các cân nhắc khác có thể tồn tại. Tôi ổn với quyết định của bạn, dù sao đi nữa! –

+3

Điều đó sẽ không hoạt động trừ khi các hàng thực sự được cập nhật theo đúng thứ tự. Không có thời gian trong quá trình thực hiện có thể vi phạm khóa duy nhất. 'update sorttest set sort = sắp xếp + 1 theo sắp xếp desc;' sẽ không hoạt động nếu không có sắp xếp giảm dần, hàng đầu tiên sẽ vi phạm phím, ngay cả khi hàng thứ hai sắp được di chuyển ra khỏi vị trí. –

0

Lưu ý: Một số nhận xét đã đề cập rằng không phải lúc nào cũng hạn chế các ràng buộc duy nhất, đặc biệt trong InnoDB. Nếu bạn có thể cải thiện câu trả lời này, vui lòng nhấp vào "Chỉnh sửa" và thực hiện các cải tiến.

Bạn chỉ có thể thêm dòng này vào đầu script của bạn:

SET UNIQUE_CHECKS=0; 

Nó thường được sử dụng này kết hợp với:

SET FOREIGN_KEY_CHECKS=0; 

Biến UNIQUE_CHECKS được đề cập trong các tài liệu tại đây:
http://dev.mysql.com/doc/refman/5.0/en/converting-tables-to-innodb.html

+2

Chỉ cần thử điều này trên 5.6, không làm việc với InnoDB. Khóa trùng lặp vẫn phát ra lỗi. – bluecollarcoder

+0

@bluecollarcoder Bạn đã thử đặt * cả * 'UNIQUE_CHECKS' và' FOREIGN_KEY_CHECKS' thành 0? Và bạn có chắc chắn rằng bạn không sao chép * khóa chính * mà có lẽ vẫn không được phép? –

+1

Khoá duy nhất nằm trên cột không tham chiếu bất kỳ bảng nào khác, vì vậy 'FOREIGN_KEY_CHECKS' không liên quan ở đây. Và cột có khóa duy nhất chắc chắn không phải là một phần của khóa chính. Trong trường hợp nào bạn có thể nhận được 'UNIQUE_CHECKS = 0' để hoạt động như mong đợi trong trường hợp này? – bluecollarcoder

Các vấn đề liên quan