2011-01-18 37 views
5

Tôi đang thực hiện một thủ tục được lưu trữ thông qua kết nối JDBC tiêu chuẩn bằng cách sử dụng MS SQL Driver phiên bản 3.0.Các bảng tạm thời sử dụng JDBC với null ResultSet

Tôi thấy rằng khi tôi tạo và chèn dữ liệu vào bảng tạm thời, quy trình được lưu trữ không thực thi đúng cách.

Mã Java sẽ không ném ngoại lệ, nhưng javax.sql.ResultSet sẽ là null.

Mấu chốt của sự thất bại trong thủ tục lưu trữ là khi tôi bỏ bình luận các INSERT INTO #TBL CLM_NAME VALUES('VAL')

Khi tôi thực hiện báo cáo kết quả sử dụng SQL Studio Manager nó thực thi mà không gặp rắc rối và các dữ liệu như mong đợi.

Có ai biết điều này hay không biết tại sao lại là trường hợp này?

Ban đầu tôi nghĩ vì trình điều khiển SQL và tôi vẫn nghĩ đó là?

Cảm ơn.

+0

Bạn có thể đảm bảo rằng bạn đang tạo và tải bảng tạm thời và đọc từ tất cả trong cùng một kết nối không? – CoolBeans

+0

Có, bảng tạm thời được tạo từ thủ tục lưu sẵn mà tôi đã tạo. Tôi chỉ gọi thủ tục lưu sẵn từ mã Java, ví dụ connect.executeQuery ("{procName (?)}"). – Koekiebox

+1

Lệnh 'INSERT' vi phạm có nằm trong cùng thủ tục lưu trữ tạo bảng tạm thời không? –

Trả lời

13

lẽ this will help:

Đó là khuyến cáo rằng nếu bạn muốn sử dụng bảng tạm thời, bạn không nên gọi là "prepareStatement". Bạn có thể trực tiếp thực hiện truy vấn từ đối tượng câu lệnh.

Ví dụ:

String sql = "select uuid, name from Component"; 

Statement stmt = dbCon.createStatement(); 
ResultSet rs = stmt.executeQuery(sql); 

Nếu bạn phải gọi là "prepareStatement", sau đó bạn sẽ cần phải tạo một bảng thực tế và, nếu cần thiết, xóa bảng sau đó.

+0

Tất nhiên, nếu bạn có bất kỳ tham số nào, bạn nên sử dụng chuẩn bị, không phải createStatement, hoặc bạn nên rất, rất cẩn thận về tiêm sql: http://stackoverflow.com/questions/1582161/how-does-a-preparedstatement- tránh-hoặc-ngăn-sql-injection –

2

Tôi cũng đang gặp phải vấn đề tương tự. Để khắc phục điều này, tôi sẽ thiết lập một dấu vết trên máy chủ sql của tôi và xem tất cả các câu lệnh đang được điều khiển bởi trình điều khiển MS JDBC trước khi thực hiện cuộc gọi SP thực tế. Điều này sẽ giúp tôi làm rõ mọi thứ. Thật không may DBA của chúng tôi là ra ngày hôm nay vì vậy tôi sẽ phải làm điều đó vào ngày mai với sự giúp đỡ của cô ấy. Tôi sẽ cho bạn biết những gì sẽ xảy ra và sửa chữa là gì.

+0

Tôi đã từ bỏ và sử dụng truy vấn phụ thay vì các bảng tạm thời hoặc các biến bảng. –

6

Lệnh executeQuery() được dự định sẽ được sử dụng với các truy vấn trả về một ResultSet, thường là các câu lệnh SELECT.

Hàm executeUpdate() dành cho câu lệnh INSERT, UPDATE, DELETE hoặc DDL trả về số cập nhật.

Cả hai giá trị trên (ResultSets và số đếm cập nhật) đều được JDBC coi là "kết quả". Đối với các truy vấn trả về nhiều kết quả, nó yêu cầu chúng ta gọi execute().

Nếu thủ tục lưu trữ sử dụng bảng tạm thời, có thể nó trả về số đếm cập nhật trước, sau đó là ResultSet. Bạn nên sử dụng execute() để chạy truy vấn, gọi getMoreResults() để bỏ qua số đếm cập nhật và sau đó gọi getResultSet() để lấy số ResultSet mà bạn muốn. Vấn đề ở đây là chúng ta phải làm thử và lỗi bằng cách gọi hàm getMoreResults() nhiều lần để lấy tập kết quả mà chúng ta muốn bằng cách gọi hàm getResultSet().

Thay vì cách thử và lỗi trên, bạn có thể chặn tất cả "kết quả truy vấn" bổ sung bằng cách chỉ định "SET NOCOUNT ON".

Những thay đổi cần thiết,

  1. Đặt logic của bạn trong SP "SPCHILD". Thủ tục lưu sẵn này sẽ có logic cùng với việc tạo bảng tạm thời.

  2. Tạo một SP "SPPARENT" như dưới đây,

    CREATE PROCEDURE [dbo].[SPPARENT] @Id int = NULL 
    AS 
    BEGIN 
    SET NOCOUNT ON; 
    EXEC(' SPCHILD @Id = ' + @Id) 
    END 
    

    Từ SP cha mẹ "SPPARENT" bạn phải gọi SP thực tế của bạn tức là "SPCHILD".

  3. Từ mã JDBC của bạn thực hiện cuộc gọi SP tới "SPPARENT".

+0

Câu trả lời hay! Cũng làm việc với khai báo bảng tạm thời bảng. –

+0

Câu trả lời hay! anh yêu em! – Benyamin

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