2010-08-23 36 views
18

PLSQL (Oracle) tương đương với đoạn mã máy chủ SQL này là gì?PLSQL JDBC: Cách nhận ID hàng cuối cùng?

BEGIN TRAN 
INSERT INTO mytable(content) VALUES ("test") -- assume there's an ID column that is autoincrement 
SELECT @@IDENTITY 
COMMIT TRAN 

Trong C#, bạn có thể gọi myCommand.ExecuteScalar() để truy xuất ID của hàng mới.

Làm cách nào để chèn một hàng mới trong Oracle và có JDBC lấy bản sao của id mới?

EDIT: BalusC cung cấp điểm khởi đầu rất tốt. Vì một số lý do JDBC không thích ràng buộc tham số có tên. Điều này cho biết "SQLException" được thiết lập hoặc đăng ký không chính xác. Tại sao chuyện này đang xảy ra?

 OracleConnection conn = getAppConnection(); 
     String q = "BEGIN INSERT INTO tb (id) values (claim_seq.nextval) returning id into :newId; end;" ; 
     CallableStatement cs = (OracleCallableStatement) conn.prepareCall(q); 
     cs.registerOutParameter("newId", OracleTypes.NUMBER); 
     cs.execute(); 
     int newId = cs.getInt("newId"); 
+0

Chọn tối đa của các trường id + 1? – Aren

+4

@Aren - 'max (n) + 1' không mở rộng và không hoạt động trong môi trường nhiều người dùng. – APC

Trả lời

33

thường bạn sẽ sử dụng Statement#getGeneratedKeys() cho điều này (xem thêm this answer cho một ví dụ), nhưng điều này là như xa (vẫn) không được hỗ trợ bởi trình điều khiển Oracle JDBC.

Tốt nhất là để hoặc làm sử dụng CallableStatement với một điều khoản RETURNING:

String sql = "BEGIN INSERT INTO mytable(id, content) VALUES (seq_mytable.NEXTVAL(), ?) RETURNING id INTO ?; END;"; 

Connection connection = null; 
CallableStatement statement = null; 

try { 
    connection = database.getConnection(); 
    statement = connection.prepareCall(sql); 
    statement.setString(1, "test"); 
    statement.registerOutParameter(2, Types.NUMERIC); 
    statement.execute(); 
    int id = statement.getInt(2); 
    // ... 

Hoặc lửa SELECT sequencename.CURRVAL sau INSERT trong cùng một giao dịch:

String sql_insert = "INSERT INTO mytable(content) VALUES (?)"; 
String sql_currval = "SELECT seq_mytable.CURRVAL FROM dual"; 

Connection connection = null; 
PreparedStatement statement = null; 
Statement currvalStatement = null; 
ResultSet currvalResultSet = null; 

try { 
    connection = database.getConnection(); 
    connection.setAutoCommit(false); 
    statement = connection.prepareStatement(sql_insert); 
    statement.setString(1, "test"); 
    statement.executeUpdate(); 
    currvalStatement = connection.createStatement(); 
    currvalResultSet = currvalStatement.executeQuery(sql_currval); 
    if (currvalResultSet.next()) { 
     int id = currvalResultSet.getInt(1); 
    } 
    connection.commit(); 
    // ... 
+0

Bạn có nghĩa là "CHỌN seq_mytable.CURRVAL từ kép" thay vì "SELECT CURRVAL (seq_mytable)"? –

+0

@Patrick: Oh drat, tôi đã có cú pháp SQL PostgreSQL trong tâm trí, tôi sẽ cập nhật (trước đây, PostgreSQL đã từng có cùng một vấn đề không hỗ trợ ['Statement # getGeneratedKeys()'] (http://stackoverflow.com/ Các câu hỏi/1915166/jdbc-how-can-chúng ta-get-insert-record-id-in-java/1915197 # 1915197) để cùng một "workaround" là cần thiết, nhưng kể từ khoảng một năm trước họ cuối cùng đã sửa trình điều khiển JDBC của chúng để hỗ trợ nó). – BalusC

+0

Xin chào BalusC, cảm ơn sự giúp đỡ. Bạn có thể xem bản chỉnh sửa của tôi xem liệu bạn có thể giải quyết bí ẩn khác đó không? – Haoest

8

Bạn có thể sử dụng mệnh đề returning của Oracle.

insert into mytable(content) values ('test') returning your_id into :var; 

Kiểm tra this link để lấy mẫu mã. Bạn cần Oracle 10g hoặc mới hơn, và một phiên bản mới của trình điều khiển JDBC.

1

Bạn có thể sử dụng getGeneratedKeys(), Bằng cách chọn một cách rõ ràng trường khóa. Dưới đây là một đoạn trích:

// change the string to your connection string 
    Connection connection = DriverManager.getConnection("connection string"); 

    // assume that the field "id" is PK, and PK-trigger exists 
    String sql = "insert into my_table(id) values (default)"; 
    // you can select key field by field index 
    int[] colIdxes = { 1 }; 
    // or by field name 
    String[] colNames = { "id" }; 

    // Java 1.7 syntax; try-finally for older versions 
    try (PreparedStatement preparedStatement = connection.prepareStatement(sql, colNames)) 
    { 
     // note: oracle JDBC driver do not support auto-generated key feature with batch update 
     //   // insert 5 rows 
     //   for (int i = 0; i < 5; i++) 
     //   { 
     //    preparedStatement.addBatch(); 
     //   } 
     //   
     //   int[] batch = preparedStatement.executeBatch(); 
     preparedStatement.executeUpdate(); 

     // get generated keys 
     try (ResultSet resultSet = preparedStatement.getGeneratedKeys()) 
     { 
      while (resultSet.next()) 
      { 
       // assume that the key's type is BIGINT 
       long id = resultSet.getLong(1); 
       assertTrue(id != 0); 

       System.out.println(id); 
      } 
     } 
    } 

tham khảo để biết chi tiết: http://docs.oracle.com/cd/E16655_01/java.121/e17657/jdbcvers.htm#CHDEGDHJ

+1

Điều này hoạt động miễn là câu lệnh chèn có tối đa 7 tham số, khi có nhiều hơn 7 tham số, một ngoại lệ ArrayIndexOutofBound được ném. Trông giống như một lỗi với trình điều khiển jdbc oracle. # Oracle_11g_R2. Trả lời từ BalusC là tốt hơn vì lý do này. –

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