Làm cách nào để có được ID của hàng được cập nhật cuối cùng trong MySQL bằng PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Làm cách nào để có được ID của hàng được cập nhật cuối cùng trong MySQL bằng PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Câu trả lời:
Tôi đã tìm thấy câu trả lời cho vấn đề này :)
SET @update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT @update_id := id)
WHERE some_other_column = 'blah' LIMIT 1;
SELECT @update_id;
EDIT bởi aefxx
Kỹ thuật này có thể được mở rộng hơn nữa để lấy ID của mỗi hàng bị ảnh hưởng bởi câu lệnh cập nhật:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Điều này sẽ trả về một chuỗi với tất cả các ID được nối bằng dấu phẩy.
WHERE
mệnh đề, bạn chỉ cần sử dụng cùng một WHERE
mệnh đề trong truy vấn tiếp theo của mìnhSELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
có thể chấp nhận một đối số sẽ đặt giá trị được trả về bởi cuộc gọi tiếp theo LAST_INSERT_ID()
. Ví dụ : UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Bây giờ, SELECT LAST_INSERT_ID();
sẽ trả về id cập nhật. Xem câu trả lời của newtover để biết thêm chi tiết.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. Tuy nhiên, nó không lấy được nhiều id, vì vậy câu trả lời này là vượt trội.
Hừm, tôi ngạc nhiên rằng trong số những câu trả lời tôi không thấy giải pháp đơn giản nhất.
Giả sử, item_id
là một cột nhận dạng số nguyên trong items
bảng và bạn cập nhật các hàng bằng câu lệnh sau:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Sau đó, để biết hàng bị ảnh hưởng mới nhất ngay sau câu lệnh, bạn nên cập nhật một chút về câu lệnh sau:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Nếu bạn chỉ cần cập nhật hàng thực sự thay đổi, bạn sẽ cần thêm bản cập nhật có điều kiện của item_id thông qua kiểm tra LAST_INSERT_ID nếu dữ liệu sẽ thay đổi trong hàng.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Đây là chính thức đơn giản nhưng đáng chú ý phản trực giác. Nếu bạn đang làm:
update users set status = 'processing' where status = 'pending'
limit 1
Thay đổi nó thành này:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
Việc thêm last_insert_id(user_id)
vào trong where
mệnh đề là yêu cầu MySQL đặt biến nội bộ của nó thành ID của hàng tìm thấy. Khi bạn chuyển một giá trị cholast_insert_id(expr)
như thế này, cuối cùng nó sẽ trả về giá trị đó, trong trường hợp ID như ở đây luôn là một số nguyên dương và do đó luôn luôn đánh giá là đúng, không bao giờ can thiệp vào mệnh đề where. Điều này chỉ hoạt động nếu một số hàng thực sự được tìm thấy, vì vậy hãy nhớ kiểm tra các hàng bị ảnh hưởng. Sau đó, bạn có thể nhận được ID theo nhiều cách.
Bạn có thể tạo các chuỗi mà không cần gọi LAST_INSERT_ID (), nhưng tiện ích của việc sử dụng hàm theo cách này là giá trị ID được duy trì trong máy chủ làm giá trị được tạo tự động cuối cùng. Nó an toàn cho nhiều người dùng vì nhiều khách hàng có thể đưa ra câu lệnh CẬP NHẬT và nhận giá trị chuỗi riêng của họ bằng câu lệnh SELECT (hoặc mysql_insert_id ()), mà không ảnh hưởng hoặc bị ảnh hưởng bởi các máy khách khác tạo ra giá trị chuỗi riêng của họ.
Trả về giá trị được tạo cho cột AUTO_INCREMENT bằng câu lệnh INSERT hoặc UPDATE trước đó. Sử dụng chức năng này sau khi bạn đã thực hiện một câu lệnh INSERT vào một bảng có chứa trường AUTO_INCREMENT hoặc đã sử dụng INSERT hoặc UPDATE để đặt giá trị cột với LAST_INSERT_ID (expr).
Lý do cho sự khác biệt giữa LAST_INSERT_ID () và mysql_insert_id () là LAST_INSERT_ID () được sử dụng dễ dàng trong các tập lệnh trong khi mysql_insert_id () cố gắng cung cấp thông tin chính xác hơn về những gì xảy ra với cột AUTO_INCREMENT.
Thực hiện câu lệnh INSERT hoặc UPDATE bằng hàm LAST_INSERT_ID () cũng sẽ sửa đổi giá trị được trả về bởi hàm mysqli_insert_id ().
Để tất cả chúng cùng nhau:
$affected_rows = DB::getAffectedRows("
update users set status = 'processing'
where status = 'pending' and last_insert_id(user_id)
limit 1"
);
if ($affected_rows) {
$user_id = DB::getInsertId();
}
(FYI rằng lớp DB ở đây .)
Đây là phương pháp tương tự như câu trả lời của Salman A, nhưng đây là mã bạn thực sự cần để làm điều đó.
Đầu tiên, chỉnh sửa bảng của bạn để nó sẽ tự động theo dõi bất cứ khi nào một hàng được sửa đổi. Xóa dòng cuối cùng nếu bạn chỉ muốn biết khi nào một hàng ban đầu được chèn.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Sau đó, để tìm ra hàng cập nhật cuối cùng, bạn có thể sử dụng mã này.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Tất cả mã này được nâng lên từ MySQL so với PostgreSQL: Thêm cột 'Thời gian sửa đổi lần cuối' vào Bảng và Hướng dẫn sử dụng MySQL: Sắp xếp hàng . Tôi chỉ lắp ráp nó.
Truy vấn :
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Hàm PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
Nó làm việc cho tôi;)
Hơn nữa với câu trả lời được chấp nhận ở trên
Đối với những người thắc mắc về :=
&=
Sự khác biệt đáng kể giữa :=
và =
, và đó là :=
hoạt động như một toán tử gán biến ở mọi nơi, trong khi =
chỉ hoạt động theo cách đó trong các câu lệnh SET và là toán tử so sánh ở mọi nơi khác.
Vì vậy, SELECT @var = 1 + 1;
sẽ @var
không thay đổi và trả về một boolean (1 hoặc 0 tùy thuộc vào giá trị hiện tại của @var), trong khi SELECT @var := 1 + 1;
sẽ thay đổi @var
thành 2 và trả về 2 .
[Nguồn]
Này, tôi chỉ cần một mẹo như vậy - tôi đã giải quyết nó theo một cách khác, có thể nó sẽ hiệu quả với bạn. Lưu ý đây không phải là một giải pháp có thể mở rộng và sẽ rất tệ cho các tập dữ liệu lớn.
Chia truy vấn của bạn thành hai phần -
đầu tiên, chọn id của các hàng bạn muốn cập nhật và lưu trữ chúng trong một bảng tạm thời.
Thứ hai, thực hiện cập nhật ban đầu với điều kiện trong câu lệnh cập nhật được đổi thành where id in temp_table
.
Và để đảm bảo đồng thời, bạn cần khóa bảng trước hai bước này và sau đó nhả khóa ở cuối.
Một lần nữa, điều này làm việc với tôi, đối với một truy vấn kết thúc bằng limit 1
, vì vậy tôi thậm chí không sử dụng bảng tạm thời, mà thay vào đó chỉ đơn giản là một biến để lưu trữ kết quả của lần đầu tiên select
.
Tôi thích phương pháp này vì tôi biết tôi sẽ luôn cập nhật chỉ một hàng và mã rất đơn giản.
SET @uids := "";
UPDATE myf___ingtable
SET id = id
WHERE id < 5
AND ( SELECT @uids := CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8), @uids) );
SELECT @uids;
Tôi đã phải CAST id (dunno why) ... hoặc tôi không thể có được nội dung @uids (đó là một blob) Btw cảm ơn rất nhiều vì câu trả lời của Pomyk!
ID của hàng được cập nhật gần nhất là cùng một ID mà bạn sử dụng trong 'updateQuery' để tìm và cập nhật hàng đó. Vì vậy, chỉ cần lưu (gọi) ID đó vào bất cứ cách nào bạn muốn.
last_insert_id()
phụ thuộc vào AUTO_INCREMENT
, nhưng ID cập nhật cuối cùng thì không.
Nếu bạn chỉ thực hiện chèn thêm và muốn một từ cùng một phiên, hãy thực hiện theo câu trả lời của peirix. Nếu bạn đang thực hiện sửa đổi, bạn sẽ cần sửa đổi lược đồ cơ sở dữ liệu của mình để lưu trữ mục nhập nào được cập nhật gần đây nhất.
Nếu bạn muốn id từ lần sửa đổi cuối cùng, có thể là từ một phiên khác (nghĩa là không phải là phiên bản vừa được thực hiện bởi mã PHP đang chạy, nhưng một lần thực hiện theo yêu cầu khác), bạn có thể thêm một yêu cầu khác Cột TIMESTAMP vào bảng của bạn được gọi là last_modified (xem http://dev.mysql.com/doc/refman/5.1/en/datetime.html để biết thông tin), sau đó khi bạn cập nhật, hãy đặt last_modified = CURRENT_TIME.
Sau khi thiết lập điều này, sau đó bạn có thể sử dụng một truy vấn như: CHỌN id TỪ bảng ĐẶT HÀNG B lastNG Last_modified DESC LIMIT 1; để có được hàng sửa đổi gần đây nhất.