Lấy ID khóa chính của bản ghi mới từ truy vấn chèn mysql?


249

Ok, vì vậy, giả sử tôi đang thực hiện một mysql INSERTvào một trong các bảng của mình và bảng có cột item_idđược đặt thành autoincrementprimary key.

Làm cách nào để có được truy vấn để xuất giá trị của khóa chính mới được tạo item_idtrong cùng một truy vấn?

Hiện tại tôi đang chạy truy vấn thứ hai để lấy id nhưng điều này dường như không thực tế tốt khi xem xét điều này có thể tạo ra kết quả sai ...

Nếu điều này là không thể thì thực tiễn tốt nhất để đảm bảo tôi lấy đúng id là gì?


1
Không có cách nào để trả về bất cứ thứ gì từ một INSERTtruy vấn như thế; Tại sao bạn nghĩ rằng nó có thể tạo ra kết quả sai?
Thuốc nổ

4
Chà, nếu quá trình này được thực hiện bởi 2 người một cách riêng biệt thì bạn có thể nhận được một danh sách quy trình chồng chéo tôi nghĩ - vì bạn phải thực hiện 2 truy vấn riêng biệt?
Amy Neville


@JimFell vâng về cơ bản là cùng một câu hỏi, nhưng câu hỏi này có câu trả lời tốt hơn nhiều nói chung
RozzA

1
Sử dụng postgresql sau đó thực hiện như thế này bảng INSERT INTO (col1, col2) VALUES (val1, val2) id RETURNING hoặc bảng INSERT INTO (col1, col2) VALUES (val1, val2) RETURNING * hoặc UPDATE bảng SET col1 = val2 Câu lệnh WHERE RETURNING id hoặc bảng UPDATE SET (col1, col2) = (val1, val2) Câu lệnh WHERE RETURNING id hoặc bảng UPDATE SET (col1, col2) = (val1, val2) Câu lệnh WHERE
RETURNING

Câu trả lời:


326

Bạn cần sử dụng LAST_INSERT_ID()chức năng: http://dev.mysql.com/doc/refman/5.0/en/inif-fifts.html#feft_last-insert-id

Ví dụ:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

Điều này sẽ giúp bạn lấy lại PRIMARY KEYgiá trị của hàng cuối cùng mà bạn đã chèn:

ID được tạo được duy trì trong máy chủ trên cơ sở mỗi kết nối . Điều này có nghĩa là giá trị được hàm trả về cho một máy khách nhất định là giá trị AUTO_INCREMENT đầu tiên được tạo cho câu lệnh gần đây nhất ảnh hưởng đến cột AUTO_INCREMENT bởi máy khách đó .

Vì vậy, giá trị được trả về LAST_INSERT_ID()là cho mỗi người dùng và không bị ảnh hưởng bởi các truy vấn khác có thể đang chạy trên máy chủ từ những người dùng khác .


8
có nhưng nếu trong tạm thời (giữa các truy vấn trong danh sách quy trình), một số hàng khác đã được chèn thì sao? Có cách nào để viết truy vấn chèn để nó xuất ra cái này không?
Amy Neville

Ok, tôi thấy ... id chèn cuối cùng của truy vấn được ghi lại ngay cả khi nó không được đăng nhập trong kết quả ... $ mysqli-> insert_id
Amy Neville

27
Điều này sẽ giúp bạn lấy lại PRIMARY KEYgiá trị của hàng cuối cùng mà bạn đã chèn, bởi vì mỗi kết nối - mỗi kết nối đến máy chủ sẽ duy trì giá trị riêng cho điều này. Tôi đã cập nhật câu trả lời để làm rõ điều này.
Khóa Duncan

Vì vậy, giả sử 3 người dùng đồng thời đăng các biểu mẫu của họ và cơ sở dữ liệu của tôi phải nhập chúng. Tôi muốn thêm một hàng tương ứng với mỗi ID mới được tạo của bảng1 trong bảng2. Là đồng thời được quan tâm hoặc tôi sẽ phải làm điều đó trong PHP bằng tay, cho các yêu cầu ghi cơ sở dữ liệu đến?
bad_keypoint

Nếu tại thời điểm bạn thực hiện chèn bảng1, cơ sở dữ liệu sẽ biết tất cả thông tin mà bạn muốn chèn vào bảng2, thì bạn có thể sử dụng trình kích hoạt để thực hiện việc này hoặc kết hợp điều này vào truy vấn. Nếu không, thì bạn cần sử dụng nhiều truy vấn - tức là thực hiện nó trong PHP. Nó phụ thuộc vào dữ liệu là gì và xuất phát từ lần chèn thứ hai.
Khóa Duncan

21

HÃY THỬ !! của "LAST_INSERT_ID ()" nếu cố gắng trả về giá trị khóa chính này trong PHP.

Tôi biết chủ đề này không được gắn thẻ php, nhưng đối với bất kỳ ai bắt gặp câu trả lời này đang tìm cách trả lại id chèn MySQL từ một đoạn mã được viết theo kịch bản PHP bằng cách sử dụng các cuộc gọi mysql_query tiêu chuẩn - nó không hoạt động và không rõ ràng nếu không bắt lỗi SQL.

Mysqli mới hơn hỗ trợ nhiều truy vấn - mà LAST_INSERT_ID () thực sự là truy vấn thứ hai từ bản gốc.

IMO một CHỌN riêng để xác định khóa chính cuối cùng an toàn hơn hàm mysql_insert_id () tùy chọn trả về ID AUTO_INCREMENT được tạo từ hoạt động INSERT trước đó.


7
LAST_INSERT_IDlà một chức năng MySQL trên mỗi kết nối. Nếu bạn truy vấn ID chèn cuối cùng, có thể một kết nối riêng sẽ thực hiện ghi và bạn sẽ có ID sai.
Thuốc nổ

@ExplumpingPills mysql_insert_id()cũng hoạt động trên cơ sở mỗi kết nối, nhưng nó cũng chịu các hành vi lạ như đã thấy ở đây stackoverflow.com/a/897374/1305910 trong nhận xét của Cliffordlife - không bao giờ chúng ta nên sử dụngmysqli
RozzA

bạn có thể nói rõ ý của bạn khi bạn ở lại 'nó không hoạt động' không?
john ktejik

18

Từ LAST_INSERT_ID()tài liệu:

ID được tạo được duy trì trong máy chủ trên cơ sở mỗi kết nối

Đó là nếu bạn có hai yêu cầu riêng biệt đối với tập lệnh thì chúng sẽ không ảnh hưởng đến nhau LAST_INSERT_ID()(trừ khi bạn có thể sử dụng kết nối liên tục).


2
Tôi nghĩ thật đáng ngờ nếu bảng của bạn có một trình kích hoạt mà nó chèn vào một bảng khác .... LAST_INSERT_ID () sẽ trả về giá trị id của bảng khác ..
bgies

15

Đây là những gì bạn đang tìm kiếm !!!

select LAST_INSERT_ID()

Đây là sự thay thế tốt nhất của SCOPE_IDENTITY()chức năng đang được sử dụng trong SQL Server.

Bạn cũng cần lưu ý rằng điều này sẽ chỉ hoạt động nếu Last_INSERT_ID()được Inserttruy vấn theo yêu cầu của bạn . Đó là truy vấn trả về id được chèn trong lược đồ. Bạn không thể lấy id được chèn cuối cùng của bảng cụ thể.

Để biết thêm chi tiết, vui lòng truy cập liên kết Tương đương với hàm SQLServer SCOPE_IDENTITY () trong myQuery?


6

Nếu bạn cần giá trị trước khi chèn một hàng:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

Bạn có thể sử dụng điều này trong một chèn:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
Điều này dường như không phải là một ý tưởng tốt? Nếu 2 khách hàng gọi chức năng đó cùng một lúc, họ sẽ nghĩ rằng họ đang chèn cùng một id khi thực tế họ không .... một người sẽ chậm hơn một chút khi chèn và nhận ID tiếp theo mà không biết.
CarCar

5

Bạn sẽ nhận được các tham số này trên kết quả truy vấn của mình:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

Đây insertIdchính xác là những gì bạn cần.

(NodeJS-mySql)


4

Nếu trong python sử dụng pymysql, từ con trỏ, bạn có thể sử dụng con trỏ.lastrowid


2

chỉ cần sử dụng "$ last_id = mysqli_insert_id ($ Conn);"


2
Tôi thực sự tình cờ tìm thấy phiên bản php của câu trả lời này nhờ vào google, vì vậy tôi đã bỏ phiếu cho câu trả lời này. Mặc dù về mặt kỹ thuật, OP không yêu cầu php, điều này có thể hữu ích cho nhiều người cũng vấp ngã ở đây.
Nhiếp ảnh gia Britt

Cảm ơn bạn rất nhiều Arnav! Tôi
JuanSedano

1

Nếu bạn đang sử dụng PHP: Trên một đối tượng PDO, bạn có thể đơn giản gọi phương thức lastInsertId sau khi chèn.

Mặt khác, với LAST_INSERT_ID, bạn có thể nhận được giá trị như thế này:SELECT LAST_INSERT_ID();



0

Tôi chỉ muốn chia sẻ cách tiếp cận của tôi với điều này trong PHP, một số bạn có thể thấy nó không phải là một cách hiệu quả nhưng đây là một cách tốt hơn 100 so với các tùy chọn có sẵn khác.

tạo một khóa ngẫu nhiên và chèn nó vào bảng tạo một hàng mới. sau đó bạn có thể sử dụng khóa đó để lấy khóa chính. sử dụng bản cập nhật để thêm dữ liệu và làm những thứ khác.

làm theo cách này giúp bảo mật một hàng và có khóa chính chính.

Tôi thực sự không khuyến nghị điều này trừ khi bạn không có lựa chọn nào khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.