首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

Java 調用 SQL Server 存儲過程:CallableStatement 實現帶輸出參數與返回值的完整範例

     編輯:關於SqlServer

存儲過程定義

CREATE PROCEDURE InsertUser
  @loginName VARCHAR(50),
  @realName VARCHAR(50),
  @passWord VARCHAR(50),
  @userId INT OUTPUT
AS
  SET NOCOUNT ON;
  IF EXISTS (SELECT userID FROM tsysuser WHERE loginName = @loginName)
    RETURN 0;  -- 已存在
  ELSE BEGIN
    INSERT INTO tsysuser (loginName, realName, password) 
    VALUES (@loginName, @realName, @passWord);
    SET @userId = @@IDENTITY;
    RETURN 1;  -- 成功
  END;
GO

Java 調用代碼

Connection conn = getConnection();  // 你的連接池獲取方法
CallableStatement proc = null;
String sql = "{? = CALL InsertUser(?, ?, ?, ?)}";  // 返回值佔位符在最前

try {
  proc = conn.prepareCall(sql);
  
  // 1. 註冊返回值(第一個參數)
  proc.registerOutParameter(1, Types.INTEGER);
  
  // 2. 設置輸入參數(對應存儲過程第 1~3 參數)
  proc.setString(2, "sa");
  proc.setString(3, "sd");
  proc.setString(4, "sd");
  
  // 3. 註冊輸出參數(存儲過程第 4 參數 @userId)
  proc.registerOutParameter(5, Types.INTEGER);
  
  // 4. 執行
  proc.execute();
  
  // 5. 獲取結果
  int returnCode = proc.getInt(1);      // RETURN 值
  int newUserId = proc.getInt(5);       // OUTPUT 參數
  
  System.out.println("Return: " + returnCode + ", New UserId: " + newUserId);
  
  if (returnCode == 1) {
    // 業務成功邏輯
  }
} catch (SQLException e) {
  e.printStackTrace();
} finally {
  if (proc != null) try { proc.close(); } catch (SQLException ignore) {}
  if (conn != null) try { conn.close(); } catch (SQLException ignore) {}
}

關鍵點總結

項目說明
SQL 語法{? = CALL proc(?, ?, ?)} 返回值佔位符在最前,參數順序與存儲過程定義一致
參數索引JDBC 參數索引從 1 開始:1=返回值,2~n=輸入,n+1~=輸出
registerOutParameter返回值與 OUTPUT 參數都必須註冊,類型對應 java.sql.Types
SET NOCOUNT ON存儲過程首行加上,避免 DONE_IN_PROC 干擾 ResultSet 處理
@@IDENTITY vs SCOPE_IDENTITY()觸發器環境下用 SCOPE_IDENTITY() 更安全
資源關閉finally 塊關閉 CallableStatement 和 Connection

與 Oracle 差異對照

特性SQL ServerOracle
返回值RETURN int,JDBC 當第一個參數無 RETURN,用第一個 OUT 參數約定
調用語法{? = CALL proc(...)}{CALL proc(...)} 或 BEGIN proc(...); END;
標識列IDENTITY / @@IDENTITYSEQUENCE / RETURNING INTO
包/重載不支持支持 Package 重載

最佳實踐

  • 連接池複用 Connection,避免頻繁創建
  • 存儲過程命名規範:usp_模塊_動作(如 usp_User_Insert)
  • 輸入參數驗證前置(長度、格式、業務規則)
  • 異常情況拋出自定義錯誤碼(RAISERROR(50001, 16, 1, 'msg')),Java 端捕獲 SQLException.getErrorCode()
  • 批量操作改用 TVP(表值參數)而非循環調用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved