分享方式:


處理傳回碼和輸出參數 (ODBC)

SQL Server 預存程式可以有整數傳回碼和輸出參數。 傳回碼和輸出參數會從伺服器傳送到最後一個封包中,而且在 SQLMoreResults 傳回SQL_NO_DATA之前,應用程式無法使用。 如果從預存程式傳回錯誤,請呼叫 SQLMoreResults 以前進到下一個結果,直到傳回SQL_NO_DATA為止。

這很重要

盡可能使用 Windows 驗證。 如果 Windows 驗證無法使用,請提示使用者在運行時間輸入其認證。 避免將認證儲存在檔案中。 如果您必須保存認證,您應該使用 Win32 加密 API 來加密認證。

處理傳回碼和輸出參數

  1. 建構使用 ODBC CALL 逸出序列的 SQL 語句。 語句應該針對每個輸入、輸入/輸出和輸出參數使用參數標記,以及程式傳回值(如果有的話)。

  2. 針對每個輸入、輸入/輸出和輸出參數,以及程式傳回值呼叫 SQLBindParameter (如果有的話)。

  3. 使用 SQLExecDirect執行語句。

  4. 處理結果集直到 SQLFetchSQLFetchScroll 傳回SQL_NO_DATA處理最後一個結果集,或直到 SQLMoreResults 傳回SQL_NO_DATA為止。 此時,系結至傳回碼和輸出參數的變數會填入傳回的數據值。

範例

此範例示範處理傳回碼和輸出參數。 IA64 不支援此範例。 此範例是針對 ODBC 3.0 版或更新版本所開發。

您將需要名為 AdventureWorks 的 ODBC 數據源,其預設資料庫是 AdventureWorks 範例資料庫。 (您可以從 Microsoft SQL Server 範例和社群專案 首頁下載 AdventureWorks 範例資料庫。此數據源必須以作系統提供的 ODBC 驅動程式為基礎(驅動程式名稱為 “SQL Server” )。 如果您要在 64 位作系統上建置並執行此範例作為 32 位應用程式,您必須在 %windir%\SysWOW64\odbcad32.exe中使用 ODBC 系統管理員建立 ODBC 數據來源。

此範例會連線到計算機的預設 SQL Server 實例。 若要連線到具名實例,請變更 ODBC 數據源的定義,以使用下列格式指定實例:伺服器\namedinstance。 根據預設,SQL Server Express 會安裝至具名實例。

第一個 (Transact-SQL) 程式代碼清單會建立這個範例所使用的預存程式。

使用 odbc32.lib 編譯第二個 (C++) 程式代碼清單。 然後,執行程式。

第三個 (Transact-SQL) 程式代碼清單會刪除此範例所使用的預存程式。

use AdventureWorks  
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'TestParm')  
   DROP PROCEDURE TestParm  
GO  
  
CREATE PROCEDURE TestParm   
@OutParm int OUTPUT   
AS  
SELECT Name FROM Purchasing.Vendor  
SELECT @OutParm = 88  
RETURN 99  
go  
// compile with: odbc32.lib  
#include <stdio.h>  
#include <string.h>  
#include <windows.h>  
#include <sql.h>  
#include <sqlext.h>  
#include <odbcss.h>  
  
#define MAXBUFLEN 255  
  
SQLHENV henv = SQL_NULL_HENV;  
SQLHDBC hdbc1 = SQL_NULL_HDBC;       
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;  
  
void Cleanup() {  
   if (hstmt1 != SQL_NULL_HSTMT)  
      SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);  
  
   if (hdbc1 != SQL_NULL_HDBC) {  
      SQLDisconnect(hdbc1);  
      SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);  
   }  
  
   if (henv != SQL_NULL_HENV)  
      SQLFreeHandle(SQL_HANDLE_ENV, henv);  
}  
  
int main() {  
   RETCODE retcode;  
   // SQLBindParameter variables.  
   SWORD sParm1 = 0, sParm2 = 1;  
   SQLLEN cbParm1 = SQL_NTS;  
   SQLLEN cbParm2 = SQL_NTS;  
  
   // Allocate the ODBC environment and save handle.  
   retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);  
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {  
      printf("SQLAllocHandle(Env) Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Notify ODBC that this is an ODBC 3.0 app.  
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);  
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {  
      printf("SQLSetEnvAttr(ODBC version) Failed\n\n");  
      Cleanup();  
      return(9);      
   }  
  
   // Allocate ODBC connection handle and connect.  
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);  
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {  
      printf("SQLAllocHandle(hdbc1) Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // This sample use Integrated Security. Create the SQL Server DSN by using the Windows NT authentication.   
   retcode = SQLConnect(hdbc1, (UCHAR*)"AdventureWorks", SQL_NTS, (UCHAR*)"",SQL_NTS, (UCHAR*)"", SQL_NTS);  
  
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {  
      printf("SQLConnect() Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Allocate statement handle.  
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);  
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {  
      printf("SQLAllocHandle(hstmt1) Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Bind the return code to variable sParm1.  
   retcode = SQLBindParameter(hstmt1, 1, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &sParm1, 0, &cbParm1);  
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {  
      printf("SQLBindParameter(sParm1) Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Bind the output parameter to variable sParm2.  
   retcode = SQLBindParameter(hstmt1, 2, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &sParm2, 0, &cbParm2);  
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {  
      printf("SQLBindParameter(sParm2) Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Execute the command.   
   retcode = SQLExecDirect(hstmt1, (UCHAR*)"{? = call TestParm(?)}", SQL_NTS);  
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {  
      printf("SQLExecDirect Failed\n\n");  
      Cleanup();  
      return(9);  
   }  
  
   // Show parameters are not filled.  
   printf("Before result sets cleared: RetCode = %d, OutParm = %d.\n", sParm1, sParm2);  
  
   // Clear any result sets generated.  
   while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA )  
      ;  
  
   // Show parameters are now filled.  
   printf("After result sets drained: RetCode = %d, OutParm = %d.\n", sParm1, sParm2);  
  
   // Clean up.   
   SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);  
   SQLDisconnect(hdbc1);  
   SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);  
   SQLFreeHandle(SQL_HANDLE_ENV, henv);  
}  
use AdventureWorks  
DROP PROCEDURE TestParm  
GO  

另請參閱

執行預存程式作說明主題 (ODBC)