2011-08-04 33 views
22

Tôi gặp sự cố khi nhận các truy vấn phụ được chọn để hoạt động trên UPDATE. Tôi đang thử một số nội dung như sau:Cập nhật MYSQL với WHERE SELECT lỗi truy vấn con số

UPDATE foo 
    SET bar=bar-1 
WHERE baz= 
     (
     SELECT baz 
     FROM foo 
     WHERE fooID='1' 
    ) 

Trường hợp foo là tên bảng có khóa chính fooID. barbaz thuộc loại INT. Khi thực hiện điều này, tôi nhận được lỗi sau:

Error: A query failed. You can't specify target table 'foo' for update 
in FROM clause 
+0

bản sao có thể có của [Xóa SQL: không thể chỉ định bảng đích để cập nhật trong mệnh đề FROM] (http://stackoverflow.com/questions/45494/sql-delete-cant-specify-target- table-for-update-in-from-clause) – ajreal

+0

http://stackoverflow.com/search?q=specify+target+table – ajreal

Trả lời

47

Từ đây: web article "Lý do cho lỗi này là MySQL không cho phép cập nhật cho một khi bạn cũng đang sử dụng cùng một bảng trong một lựa chọn bên trong làm tiêu chí cập nhật của bạn. " Bài báo tiếp tục cung cấp một giải pháp, đó là sử dụng một bảng tạm thời.

Sử dụng ví dụ này, cập nhật của bạn phải được điều này:

update foo 
set bar = bar - 1 
where baz in 
(
    select baz from 
    (
    select baz 
    from foo 
    where fooID = '1' 
) as arbitraryTableName 
) 
+0

Điều này đã làm nó! :) Cảm ơn rất nhiều !! – Erik

+1

Nhưng tôi phải nói, tôi ngạc nhiên rằng điều này không được hỗ trợ một cách rõ ràng hơn ... – Erik

+0

Tôi sẽ truy cập lại ngay khi có cơ hội, nhưng chỉ là một ý nghĩ chưa được kiểm tra mà tôi nghĩ mình sẽ ném ra: một cách sạch hơn để làm việc xung quanh lỗi của OP là không sử dụng * bất kỳ * subselects và thay vì JOIN foo trên chính nó trong truy vấn UPDATE? Các câu lệnh SELECT lồng nhau ở đây làm việc, và chúng là giải pháp mà tôi luôn sử dụng cho tình huống này vì nhìn thấy câu trả lời của bạn, nhưng chúng khá là hack - nếu JOIN hoạt động, nó giống như giải pháp 'đúng'. –

4

Do lỗi 1093 Lỗi 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000. Công việc xung quanh là tạo một bảng tạm thời.

CREATE TEMPORARY table foo_bak (SELECT baz from foo WHERE fooID='1'); 

UPDATE foo 
    SET foo.bar=foo.bar-1 
WHERE foo.baz = 
    (
    SELECT baz 
    FROM foo_bak 
); 

DROP TABLE foo_bak; 
+0

yeah tôi đã thử đặt tên mọi thứ nhưng không may mắn .. có vẻ như bạn không thể sử dụng bảng trong truy vấn phụ ... mà tôi tìm thấy một chút ngớ ngẩn. – Erik

+0

Có, nếu tôi nhớ chính xác, PostgreSQL cho phép điều này. Giải pháp của Dwb sạch hơn nhiều. – ace

+0

Nó hoạt động cho tôi bằng cách sử dụng mysql 5.6! Câu trả lời chính xác! –

0

Cho đến giờ tôi biết, khi cập nhật bảng, Mysql khóa nó để cập nhật an toàn. Bạn không thể chọn dữ liệu và cập nhật cùng một bảng như bạn đang cố gắng.

Những văn bản này sẽ giúp bạn

+0

Nhưng không phải là truy vấn phụ được cho là không tương quan? (tức là truy vấn bên trong chạy đầu tiên, truy vấn bên ngoài chạy sau) ... Đây là một truy vấn rất hữu ích để có thể chạy, có vẻ lạ rằng nó sẽ không được phép. :( – Erik

0

Trong một số trường hợp, bạn cũng có thể tận dụng lợi thế của biến MySQL. ví dụ:

SET @id1 = (SELECT id FROM foo WHERE name = 'parent'); 
UPDATE foo SET parent_id = @id1 WHERE name = 'emails'; 
Các vấn đề liên quan