備妥的執行
ODBC API 會定義備妥的執行,將它當做減少與重複執行 Transact-SQL 陳述式有關之剖析和編譯負擔的一個方式。應用程式會建立一個包含 SQL 陳述式的字元字串,然後在兩個階段執行此字串。它會呼叫 SQLPrepare 一次,好讓 Database Engine 剖析此陳述式並將它編譯成執行計畫。然後每一次執行已備妥的執行計畫時,它就會呼叫 SQLExecute。這樣會省下每次執行時的剖析和編譯負擔。應用程式通常會使用備妥的執行來重複執行相同且參數化的 SQL 陳述式。
對於大多數的資料庫而言,備妥的執行要比直接執行已執行三次或四次的陳述式更為快速,主要是因為該陳述式只會編譯一次,而直接執行的陳述式則會在每次執行時進行編譯。備妥的執行也可以讓網路流量減少,因為每次執行該陳述式時,此驅動程式都可以將執行計畫識別碼和參數值 (而非整個 SQL 陳述式) 傳送給資料來源。
SQL Server 2000 及更新版本可減少直接執行與備妥的執行之間的效能差異,其方式是透過改良過的演算法來偵測及重複使用 SQLExecDirect 中的執行計畫。如此可讓備妥的執行得到的某些效能優點可供直接執行的陳述式使用。如需詳細資訊,請參閱<直接執行>。
SQL Server 2000 及更新的版本也會針對備妥的執行提供原生支援。執行計畫是建立在 SQLPrepare 之上,而且之後會在呼叫 SQLExecute 時加以執行。因為在 SQLPrepare 上建立暫存預存程序並不需要 SQL Server 2000 及更新版本,所以 tempdb 中的系統資料表上不會有額外負擔。
基於效能的理由,陳述式準備會延遲到呼叫 SQLExecute 或執行中繼屬性 (metaproperty) 作業 (例如 ODBC 中的 SQLDescribeCol 或 SQLDescribeParam) 為止。這是預設行為。要等到執行此陳述式或執行中繼屬性作業之後,才可得知正在準備之陳述式中的任何錯誤。將 SQL Server Native Client ODBC 驅動程式特有的陳述式屬性 SQL_SOPT_SS_DEFER_PREPARE 設定為 SQL_DP_OFF 可以關閉這項預設行為。
如果是延遲的準備,請先呼叫 SQLDescribeCol 或 SQLDescribeParam,然後呼叫 SQLExecute 才會產生額外的伺服器往返。在 SQLDescribeCol 上,此驅動程式會從查詢中移除 WHERE 子句,並使用 SET FMTONLY ON 將它傳送給伺服器,以便取得該查詢傳回之第一個結果集中的資料行描述。在 SQLDescribeParam 上,此驅動程式會呼叫伺服器,以便取得此查詢中任何參數標記所參考之運算式或資料行的描述。這個方法也有一些限制,例如無法解析子查詢中的參數。
搭配 SQL Server Native Client ODBC 驅動程式過度使用 SQLPrepare 將會降低效能,尤其是連接到舊版的 SQL Server 時。備妥的執行不應該用於單次執行的陳述式。備妥的執行要比直接執行單次執行的陳述式更緩慢,因為它需要從用戶端到伺服器的額外網路往返。在舊版的 SQL Server 上,它也會產生暫存預存程序。
如果產生預存程序的選項為使用中,備妥的陳述式無法在 SQL Server 2000 或更新版本或是舊版 SQL Server 上用來建立暫存物件。當這個選項開啟時,備妥的陳述式會建立到暫存預存程序中,而當呼叫 SQLExecute 時會執行此預存程序。在執行預存程序時所建立的任何暫存物件都會在此程序完成時自動卸除。如果針對準備產生預存程序的選項為使用中,下列其中一個範例會造成暫存資料表 #sometable 無法建立:
SQLPrepare(hstmt,
"CREATE TABLE #sometable(cola int, colb char(8))",
SQL_NTS);
SQLExecute(hstmt);
或
SQLPrepare(hstmt,
"SELECT * FROM Authors INTO #sometable",
SQL_NTS);
SQLExecute(hstmt);
之前某些 ODBC 應用程式會在每次使用 SQLBindParameter 時使用 SQLPrepare。SQLBindParameter 不需要使用 SQLPrepare,它可以搭配 SQLExecDirect 一起使用。例如,搭配 SQLBindParameter 使用 SQLExecDirect 可從僅限一次執行的預存程序中擷取傳回碼或輸出參數。請勿搭配 SQLBindParameter 使用 SQLPrepare,除非相同的陳述式將會執行多次。