2009-01-02 37 views
18

Tôi có một truy vấn để chèn một hàng vào một bảng có một trường được gọi là ID, được điền bằng cách sử dụng AUTO_INCREMENT trên cột. Tôi cần phải nhận được giá trị này cho các bit tiếp theo của chức năng, nhưng khi tôi chạy sau, nó luôn luôn trả về 0 mặc dù giá trị thực tế không phải là 0:Lấy id của hàng được chèn bằng C#

MySqlCommand comm = connect.CreateCommand(); 
comm.CommandText = insertInvoice; 
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', " + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ")"; 
int id = Convert.ToInt32(comm.ExecuteScalar()); 

Theo hiểu biết của tôi, điều này sẽ trả lại ID cột, nhưng nó chỉ trả về 0 mỗi lần. Bất kỳ ý tưởng?

EDIT:

Khi tôi chạy:

"INSERT INTO INVOICE (INVOICE_DATE, BOOK_FEE, ADMIN_FEE, TOTAL_FEE, CUSTOMER_ID) VALUES ('2009:01:01 10:21:12', 50, 7, 57, 2134);last_insert_id();" 

tôi nhận được:

{"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'last_insert_id()' at line 1"} 
+0

1. Bạn có thể gửi CommandText thức đó được thực hiện? 2.Các hồ sơ có thực sự được chèn vào không? –

+0

Tôi đã đăng truy vấn, lỗi và có, các hàng đang được chèn. – Elie

+0

OK, làm thế nào về "SELECT last_insert_id();" cuối cùng? –

Trả lời

15

[Edit: thêm "chọn" trước khi tham chiếu đến last_insert_id()]

Điều gì về việc chạy "select last_insert_id();" sau khi quảng cáo của bạn t?

MySqlCommand comm = connect.CreateCommand(); 
comm.CommandText = insertInvoice; 
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', " 
    + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ");"; 
    + "select last_insert_id();" 

int id = Convert.ToInt32(comm.ExecuteScalar()); 

Edit: Như duffymo đề cập, bạn sẽ thực sự được phục vụ tốt sử dụng các truy vấn tham số like this.


Edit: Cho đến khi bạn chuyển sang một phiên bản tham số, bạn có thể tìm thấy hòa bình với string.Format:

comm.CommandText = string.Format("{0} '{1}', {2}, {3}, {4}, {5}); select last_insert_id();", 
    insertInvoice, invoiceDate.ToString(...), bookFee, adminFee, totalFee, customerID); 
+0

Tôi sẽ thử truy vấn mà không có nó. Các hồ sơ có thực sự được chèn vào không? –

+0

có, các bản ghi sẽ được chèn vào. – Elie

+0

OK, làm thế nào về "SELECT last_insert_id();" cuối cùng? –

0

Nó làm tôi bực mình để xem ai tham gia một ngày và lưu trữ nó trong một cơ sở dữ liệu dưới dạng Chuỗi. Tại sao không có loại cột phản ánh thực tế?

Tôi cũng ngạc nhiên khi thấy truy vấn SQL đang được xây dựng bằng cách sử dụng nối chuỗi. Tôi là một nhà phát triển Java, và tôi không biết C# ở tất cả, nhưng tôi tự hỏi nếu không có một cơ chế ràng buộc dọc theo dòng java.sql.PreparedStatement một nơi nào đó trong thư viện? Nó được khuyến khích để bảo vệ chống lại các cuộc tấn công SQL injection. Một lợi ích khác là lợi ích hiệu suất có thể, bởi vì SQL có thể được phân tích cú pháp, xác minh, lưu trữ một lần và được tái sử dụng.

+0

OP có thể đang sử dụng cột ngày trong DB-- chúng ta không thể thấy phần đó. Tôi đồng ý rằng bạn nên sử dụng truy vấn tham số, mặc dù. Rất may nó không giống như bạn đang chèn bất kỳ văn bản để nói đúng bạn có thể an toàn trên này (mặc dù hiệu suất có thể được tốt hơn). –

+0

cột thực sự là một ngày, nhưng nếu tôi cố gắng chèn đối tượng ngày trực tiếp, tôi đã có vấn đề với nó đặt lại ngày thành một bộ 0. Tôi mới đến C#, nhưng tôi đồng ý với bạn, có khả năng là một phiên bản của PreparedStatement cho C#, và tôi sẽ thay đổi điều đó. – Elie

+0

Nếu cột thực sự là một ngày, cuộc gọi "toString" đó với mẫu định dạng đang thực hiện trong mã là gì? – duffymo

0

Thực ra, phương thức ExecuteScalar trả về cột đầu tiên của hàng đầu tiên của Số liệu đang được trả về. Trong trường hợp của bạn, bạn chỉ làm một Chèn, bạn không thực sự truy vấn bất kỳ dữ liệu nào. Bạn cần truy vấn scope_identity() sau khi bạn chèn (đó là cú pháp của SQL Server) và sau đó bạn sẽ có câu trả lời. Xem ở đây:

Linkage

EDIT: Như Michael Haren chỉ ra, bạn đề cập đến trong thẻ của bạn, bạn đang sử dụng MySql, sử dụng last_insert_id(); thay vì scope_identity();

+0

Câu trả lời của tôi bao gồm phiên bản scope_identity cho Mysql, theo các thẻ. –

+0

Ồ, lỗi của tôi, tôi không nhận thấy thẻ MySql. Tôi sẽ chỉnh sửa bài đăng của mình. – BFree

+0

Không vấn đề gì - tôi nhớ họ thường xuyên đủ. –

32
MySqlCommand comm = connect.CreateCommand(); 
comm.CommandText = insertStatement; // Set the insert statement 
comm.ExecuteNonQuery();    // Execute the command 
long id = comm.LastInsertedId;  // Get the ID of the inserted item 
+4

* LastInsertedId không phải là chủ đề an toàn. * Nếu một luồng khác đang chèn vào, thì LastInsertedId sẽ trả về id được chèn cuối cùng trên kết nối với db. Vì vậy, nếu một số chủ đề làm điều đó (hoặc thậm chí các quá trình riêng biệt với cùng một người dùng đến db), nó sẽ bị lỗi. – Ted

+0

Tuyệt vời .. Tôi thậm chí không nghĩ về điều đó MysqlData sẽ cung cấp nó. tuyệt quá. – Sami

+1

Có thể là cmd.LastInsertedId không phải là chủ đề an toàn ..... nhưng tôi cho rằng ID được truy lục trong cùng một cuộc gọi ExecuteNonQuery, không phải là hai cuộc gọi truy vấn như bạn phải làm với SELECT LAST_INSERT_ID(). Có thực sự có thể cho một cuộc gọi khác từ một chuỗi khác để nhận được "ở giữa" hàng đã chèn và truy xuất ID. Tôi đoán máy chủ làm nhiệm vụ này và do đó làm ngay lập tức. Chuỗi LAST_INSERT_ID có an toàn không? – MrCalvin

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