ฉันจะรับ ID ของแถวที่อัปเดตล่าสุดใน MySQL โดยใช้ PHP ได้อย่างไร
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
เหรอ?
ฉันจะรับ ID ของแถวที่อัปเดตล่าสุดใน MySQL โดยใช้ PHP ได้อย่างไร
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
เหรอ?
คำตอบ:
ฉันพบคำตอบสำหรับปัญหานี้แล้ว :)
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;
แก้ไขโดย aefxx
เทคนิคนี้สามารถขยายเพิ่มเติมเพื่อดึง ID ของทุกแถวที่ได้รับผลกระทบจากคำสั่งอัพเดต:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
สิ่งนี้จะส่งคืนสตริงที่มี ID ทั้งหมดเชื่อมต่อกันด้วยลูกน้ำ
WHERE
อนุประโยคคุณสามารถใช้WHERE
ประโยคเดียวกันในการสืบค้นถัดไปของคุณได้SELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
LAST_INSERT_ID()
ตัวอย่างเช่น: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. ตอนนี้SELECT LAST_INSERT_ID();
จะส่งคืน id ที่อัปเดตแล้ว ดูคำตอบของ newtover สำหรับรายละเอียดเพิ่มเติม
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
UPDATE: อย่างไรก็ตามมันไม่ได้ดึงหลายรหัสดังนั้นคำตอบนี้ดีกว่า
ฉันแปลกใจที่ในบรรดาคำตอบฉันไม่เห็นวิธีแก้ปัญหาที่ง่ายที่สุด
สมมติว่าitem_id
เป็นคอลัมน์ข้อมูลประจำตัวจำนวนเต็มในitems
ตารางและคุณอัปเดตแถวด้วยคำสั่งต่อไปนี้:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
จากนั้นหากต้องการทราบแถวที่ได้รับผลกระทบล่าสุดหลังจากคำสั่งคุณควรอัปเดตข้อความต่อไปนี้เล็กน้อย:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
หากคุณต้องการอัปเดตเฉพาะแถวที่มีการเปลี่ยนแปลงจริงๆคุณจะต้องเพิ่มการอัปเดตตามเงื่อนไขของ item_id ผ่านทาง LAST_INSERT_ID เพื่อตรวจสอบว่าข้อมูลกำลังจะเปลี่ยนแปลงในแถวหรือไม่
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
นี่เป็นเรื่องง่ายอย่างเป็นทางการ แต่ใช้งานง่ายอย่างน่าทึ่ง หากคุณกำลังทำ:
update users set status = 'processing' where status = 'pending'
limit 1
เปลี่ยนเป็นสิ่งนี้:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
การเพิ่มlast_insert_id(user_id)
ในwhere
ประโยคเป็นการบอกให้ MySQL ตั้งค่าตัวแปรภายในเป็น ID ของแถวที่พบ เมื่อคุณส่งค่าไปlast_insert_id(expr)
เช่นนี้มันจะส่งกลับค่านั้นซึ่งในกรณีของ ID เช่นนี้จะเป็นจำนวนเต็มบวกเสมอดังนั้นจึงประเมินค่าเป็นจริงเสมอไม่รบกวนกับประโยคที่ สิ่งนี้ใช้ได้เฉพาะเมื่อพบบางแถวเท่านั้นดังนั้นอย่าลืมตรวจสอบแถวที่ได้รับผลกระทบ จากนั้นคุณสามารถรับ ID ได้หลายวิธี
คุณสามารถสร้างลำดับได้โดยไม่ต้องเรียก LAST_INSERT_ID () แต่ยูทิลิตี้ของการใช้ฟังก์ชันด้วยวิธีนี้คือค่า ID จะถูกคงไว้ในเซิร์ฟเวอร์เป็นค่าสุดท้ายที่สร้างขึ้นโดยอัตโนมัติ ปลอดภัยสำหรับผู้ใช้หลายคนเนื่องจากไคลเอนต์หลายรายสามารถออกคำสั่ง UPDATE และรับค่าลำดับของตนเองด้วยคำสั่ง SELECT (หรือ mysql_insert_id ()) โดยไม่ส่งผลกระทบหรือได้รับผลกระทบจากไคลเอนต์อื่นที่สร้างค่าลำดับของตนเอง
ส่งคืนค่าที่สร้างขึ้นสำหรับคอลัมน์ AUTO_INCREMENT โดยคำสั่ง INSERT หรือ UPDATE ก่อนหน้า ใช้ฟังก์ชันนี้หลังจากที่คุณดำเนินการคำสั่ง INSERT ในตารางที่มีฟิลด์ AUTO_INCREMENT หรือใช้ INSERT หรือ UPDATE เพื่อตั้งค่าคอลัมน์ด้วย LAST_INSERT_ID (expr)
สาเหตุของความแตกต่างระหว่าง LAST_INSERT_ID () และ mysql_insert_id () คือ LAST_INSERT_ID () ใช้งานง่ายในสคริปต์ในขณะที่ mysql_insert_id () พยายามให้ข้อมูลที่แน่นอนมากขึ้นเกี่ยวกับสิ่งที่เกิดขึ้นกับคอลัมน์ AUTO_INCREMENT
การดำเนินการคำสั่ง INSERT หรือ UPDATE โดยใช้ฟังก์ชัน LAST_INSERT_ID () จะแก้ไขค่าที่ส่งคืนโดยฟังก์ชัน mysqli_insert_id ()
วางมันทั้งหมดเข้าด้วยกัน:
$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 ที่คลาส DB อยู่ที่นี่ )
นี่เป็นวิธีเดียวกับคำตอบของ Salman A แต่นี่คือรหัสที่คุณต้องทำจริงๆ
ขั้นแรกแก้ไขตารางของคุณเพื่อให้ติดตามโดยอัตโนมัติเมื่อใดก็ตามที่มีการแก้ไขแถว ลบบรรทัดสุดท้ายหากคุณต้องการทราบเมื่อมีการแทรกแถวครั้งแรกเท่านั้น
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
จากนั้นหากต้องการทราบแถวที่อัปเดตล่าสุดคุณสามารถใช้รหัสนี้
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
รหัสนี้คือทั้งหมดที่ยกมาจากMySQL เทียบกับ PostgreSQL: การเพิ่ม 'เวลาที่แก้ไขล่าสุด' คอลัมน์กับตารางและMySQL คู่มือการใช้งาน: การเรียงลำดับแถว ฉันเพิ่งประกอบมัน
คำถาม:
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
ฟังก์ชัน PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
มันได้ผลสำหรับฉัน;)
เพิ่มเติมจากคำตอบที่ยอมรับข้างต้น
สำหรับผู้ที่สงสัยเกี่ยวกับ:=
&=
ความแตกต่างที่สำคัญระหว่าง:=
และ=
และนั่นคือ:=
ทำงานเป็นตัวดำเนินการกำหนดตัวแปรได้ทุกที่ในขณะที่=
ทำงานในลักษณะนั้นในคำสั่ง SET เท่านั้นและเป็นตัวดำเนินการเปรียบเทียบที่อื่น
ดังนั้นSELECT @var = 1 + 1;
จะออก@var
ไม่เปลี่ยนแปลงและกลับมาเป็นบูลีน (1 หรือ 0 ขึ้นอยู่กับมูลค่าปัจจุบันของ @var) ในขณะที่SELECT @var := 1 + 1;
จะมีการเปลี่ยนแปลง@var
ไป2และกลับ 2
[ที่มา]
เฮ้ฉันแค่ต้องการเคล็ดลับแบบนั้น - ฉันแก้ไขด้วยวิธีอื่นบางทีมันอาจจะได้ผลสำหรับคุณ โปรดทราบว่านี่ไม่ใช่โซลูชันที่ปรับขนาดได้และจะไม่ดีสำหรับชุดข้อมูลขนาดใหญ่
แบ่งคำถามของคุณออกเป็นสองส่วน -
ขั้นแรกให้เลือกรหัสของแถวที่คุณต้องการอัปเดตและเก็บไว้ในตารางชั่วคราว
ประการที่สองทำการอัปเดตดั้งเดิมโดยมีเงื่อนไขในคำสั่งอัพเดตเปลี่ยนเป็น where id in temp_table
.
และเพื่อให้แน่ใจว่าการทำงานพร้อมกันคุณต้องล็อกตารางก่อนสองขั้นตอนนี้จากนั้นจึงคลายล็อกในตอนท้าย
อีกครั้งสิ่งนี้ใช้ได้กับฉันสำหรับแบบสอบถามที่ลงท้ายด้วยlimit 1
ดังนั้นฉันจึงไม่ได้ใช้ตาราง temp แต่เป็นเพียงตัวแปรเพื่อเก็บผลลัพธ์ของครั้งแรกselect
แต่เพียงตัวแปรในการจัดเก็บผลมาจากครั้งแรก
ฉันชอบวิธีนี้เนื่องจากฉันรู้ว่าฉันจะอัปเดตเพียงแถวเดียวเสมอและรหัสก็ตรงไปตรงมา
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;
ฉันต้องแคสต์รหัส (ไม่รู้ทำไม) ... หรือฉันไม่สามารถรับเนื้อหา @uids (มันเป็นหยด) ขอบคุณมากสำหรับคำตอบของ Pomyk!
ID ของแถวที่อัปเดตล่าสุดคือ ID เดียวกับที่คุณใช้ใน 'updateQuery' เพื่อค้นหาและอัปเดตแถวนั้น ดังนั้นเพียงบันทึก (โทร) ID นั้นตามที่คุณต้องการ
last_insert_id()
ขึ้นอยู่กับAUTO_INCREMENT
แต่ ID ที่อัปเดตล่าสุดไม่ใช่
วิธีแก้ปัญหาของฉันคือก่อนอื่นให้เลือก "id" (@uids) ด้วยคำสั่ง select และหลังจากอัปเดต id นี้ด้วย @uids
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
มันทำงานในโครงการของฉัน
หากคุณทำเฉพาะส่วนแทรกและต้องการหนึ่งจากเซสชันเดียวกันให้ทำตามคำตอบของ peirix หากคุณกำลังทำการแก้ไขคุณจะต้องแก้ไขสคีมาฐานข้อมูลของคุณเพื่อจัดเก็บว่ารายการใดที่อัปเดตล่าสุด
หากคุณต้องการรหัสจากการแก้ไขครั้งล่าสุดซึ่งอาจมาจากเซสชันอื่น (เช่นไม่ใช่รหัสที่เพิ่งทำโดยโค้ด PHP ที่ทำงานอยู่ในปัจจุบัน แต่ทำเพื่อตอบสนองคำขออื่น) คุณสามารถเพิ่ม TIMESTAMP ในตารางของคุณที่เรียกว่า last_modified (ดูข้อมูลที่http://dev.mysql.com/doc/refman/5.1/th/datetime.html ) จากนั้นเมื่อคุณอัปเดตให้ตั้งค่า last_modified = CURRENT_TIME
เมื่อตั้งค่านี้แล้วคุณสามารถใช้แบบสอบถามเช่น: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; เพื่อรับแถวที่แก้ไขล่าสุด
ไม่จำเป็นต้องใช้รหัส Mysql ที่ยาวมาก ใน PHP แบบสอบถามควรมีลักษณะดังนี้:
$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error');
$lastUpdatedId = mysql_insert_id();