當前位置:首頁 » 編程語言 » sqlh句柄使用方法博客
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sqlh句柄使用方法博客

發布時間: 2023-06-06 03:33:42

1. sql語句解析過程

為了將用戶寫的SQL文本轉化為Oracle認識的且可執行的語句 這個過程就叫做解析過程 解析分為硬解析和軟解析 一條SQL語句在第一次被執行時必須進行硬解析

當客戶端發出一條SQL語句(也可以是一個存儲過程或者一個匿名PL/SQL塊)進入shared pool時(注意 我們從前面已經知道 Oracle對這些SQL不叫做SQL語句 而是稱為游標 因為Oracle在處理SQL時 需要很多相關的輔助信息 這些輔助信息與SQL語句一起組成了游標) Oracle首先將SQL文本轉化為ASCII值 然後根據hash函數計算其對應的hash值(hash_value) 根據計算出的hash值到library cache中找到對應的bucket 然後比較bucket里是否存在該SQL語句

如果不存在 則需要按照我們前面所描述的 獲得shared pool latch 然後在shared pool中的可用chunk鏈表(也就是bucket)上找到一個可用的chunk 之後釋放shared pool latch 在獲得了chunk以後 這塊chunk就可以認為是進入了library cache 接下來 進行硬解析過程 硬解析包括以下幾個步驟

對SQL語句進行文法檢查 看是否有文法錯誤 比如沒有寫from select拼寫錯誤等 如果存在文法錯誤 則退出解析過程

到數據字典里校驗SQL語句涉及的對象和列是否都存在 如果不存在 則退出解析過程 這個過程會載入dictionary cache

將對象進行名稱轉換 比如將同名詞翻譯成實際的對象等 比如select * from t中 t是一個同名詞 指向hr t 於是Oracle將t轉換為hr t 如果轉換失敗 則退出解析過程

檢查發出SQL語句的用戶是否具有訪問SQL語句里所引用的對象的許可權 如果沒有許可權 則退出解析過程

通過優化器創建一個最優的執行計劃 這個過程會根據數據字典里記錄的對象的統計信息 來計算最優的執行計劃 這一步牽涉大量數學運算 是最消耗CPU資源的

將該游標所產生的執行計劃 SQL文本等裝載進library cache的heap中

在硬解析的過程中 進程會一直持有library cache latch 直到硬解析結束為止 硬解析結束以後 會為SQL語句產生兩個游標 一個是父游標 另一個是子游標 父游標里主要包含兩種信息 SQL文本以及優化目標(optimizer goal) 父游標在第一次打開時被鎖定 直到其他所有的session都關閉該游標後才被解鎖 當父游標被鎖定的時候是不能被交換出library cache的 只有在解鎖以後才能被交換出library cache 父游標被交換出內存時 父游標對應的所有子游標也被交換出library cache 子游標包括游標所有的信息 比如具體的執行計劃 綁定變數等 子游標隨時可以被交換出library cache 當子游標被交換出library cache時 Oracle可以利用父游標的信息重新構建出一個子游標來 這個過程叫reload 可以使用下面的方式來確定reload的比率

select *sum(reloads)/sum(pins) Reload_Ratio from v$librarycache;

一個父游標可以對應多個子游標 子游標具體的個數可以從視圖v$sqlarea的version_count欄位體現出來 而每個具體的子游標則全都在視圖v$sql里體現 當具體綁定變數的值與上次綁定變數的值有較大差異(比如上次執行的綁定變數值的長度是 位 而這次執行綁定變數的值的長度是 位)時或者當SQL語句完全相同 但是所引用的表屬於不同的用戶時 都會創建一個新的子游標

如果在bucket中找到了該SQL語句 則說明該SQL語句以前運行過 於是進行軟解析 軟解析是相對於硬解析而言的 如果解析過程中 可以從硬解析的步驟中去掉一個或多個的話 這樣的解析就是軟解析 軟解析分為以下三種類型

第一種是某個session發出的SQL語句與library? cache里其他session發出的SQL語句一致 這時 該解析過程中可以去掉硬解析中的 和 但是仍然要進行硬解析過程中的 也就是表名和列名檢查 名稱轉換和許可權檢查

* 第二種是某個session發出的SQL語句是該session之前發出的曾經執行過的SQL語句 這時 該解析過程中可以去掉硬解析中的 和 這四步 但是仍然要進行許可權檢查 因為可能通過grant改變了該session用戶的許可權

* 第三種是當設置了初始化參數session_cached_cursors時 當某個session第三次執行相同的SQL時 則會把該SQL語句的游標信息轉移到該session的PGA里 這樣 該session以後再執行相同的SQL語句時 會直接從PGA里取出執行計劃 從而跳過硬解析的所有步驟 這種情況下 是最高效的解析方式 但是會消耗很大的內存

我們舉一個例子來說明解析SQL語句的過程 在該測試中 綁定變數名稱相同 但是變數類型不同時 所出現的解析情況 如下所示

首先 執行下面的命令 清空shared pool里所有的SQL語句

SQL> alter system flush shared_pool;

然後 定義一個數值型綁定變數 並為該綁定變數賦一個數值型的值以後 執行具體的查詢語句

SQL> variable v_obj_id number;

SQL> exec :v_obj_id := ;

SQL> select object_id object_name from sharedpool_test

where object_id=:v_obj_id;

OBJECT_ID OBJECT_NAME

AGGXMLIMP

接下來 定義一個字元型的綁定變數 變數名與前面相同 為該綁定變數賦一個字元型的值以後 執行相同的查詢

SQL> variable v_obj_id varchar ( );

SQL> exec :v_obj_id := ;

SQL> select object_id object_name from sharedpool_test

where object_id=:v_obj_id;

OBJECT_ID OBJECT_NAME

AGGXMLIMP

然後我們到視圖v$sqlarea里找到該SQL的父游標的信息 並到視圖v$sql里找該SQL的所有子游標的信息

SQL> select sql_text version_count from v$sqlarea where

sql_text like %sharedpool_test% ;

SQL_TEXT

VERSION_COUNT

select object_id object_name from sharedpool_test where

object_id=:v_obj_id

SQL> select sql_text child_address address from v$sql

where sql_text like %sharedpool_test% ;

SQL_TEXT

CHILD_ADDRESS ADDRESS

select object_id object_name from sharedpool_test where

object_id=:v_obj_id F

B D

select object_id object_name from sharedpool_test where

object_id=:v_obj_id FC

B D

從記錄父游標的視圖v$sqlarea的version_count列可以看到 該SQL語句有 個子游標 而從記錄子游標的視圖v$sql里可以看到 該SQL文本確實有兩條記錄 而且它們的SQL文本所處的地址(ADDRESS列)也是一樣的 但是子地址(CHILD_ADDRESS)卻不一樣 這里的子地址實際就是子游標所對應的heap 的句柄

lishixin/Article/program/Oracle/201311/18653

2. 怎樣用vc++ 6.0訪問SQL Server資料庫

從功能簡單的資料庫(如Jet Engine)到復雜的大型資料庫系統(如oracle),VC++6.0都提供了一些編程介面。本文主要介紹以下五種: 1.ODBC API;2.MFC ODBC類;3.MFC DAO類;(數據訪問對象)4.MFC的OLE/DB;5.ActiveX數據對象(ADO)。6.RDO遠程數據訪問
1.開放資料庫連接(ODBC API):提供了一個通用的編程介面,允許程序與多種不同的資料庫連接。它為Oracle,SQL Server,MS Excel等都提供了驅動程序,使得用戶可以使用SQL語句對資料庫進行直接的底層功能操作。在使用ODBC API時,用戶須引入的頭文件為 "sql.h ", "sqlext.h ", "sqltypes.h "。用ODBC API創建資料庫應用程序遵循一定的基本步驟:
第一步是分配ODBC環境,使一些內部結構初始化。完成這一步,須分配一個SQLHENV類型的變數在ODBC環境中做句柄使用。
第二步是為將要使用的每一個數據源分配一個連接句柄,由函數SQLALLocHandle()完成。
第三步是使用SQLConnect()把連接句柄與資料庫連接,可以先通過SQLSetConnectAttr()設置連接屬性。
然後就可以進行SQL語句的操作,限於篇幅,相關的函數就不具體介紹了,讀者可以參考相關書籍。
操作完成後,用戶取回相應的結果,就可以取消與資料庫的連接。
最後需要釋放ODBC環境。
ODBC API的特點是功能強大豐富,提供了非同步操作,事務處理等高級功能,但相應的編程復雜,工作量大。
2.MFC ODBC類:MFC1.5後的版本里引入封裝了ODBC功能的類。通過這些類提供與ODBC的介面,使得用戶可以不須處理ODBC API中的繁雜處理就可以進行資料庫操作。主要的MFC ODBC類如下。
CDatabase類:一個CDatabase對象表示一個到數據源的連接,通過它可以操作數據源。應用程序可使用多個CDatabase對象:構造一個對象並調用OpenEx()成員函數打開一個連接。接著構造CRecordSet對象以操作連接的數據源,並向CDatabase對象傳遞記錄集構造程序指針。完成使用後用Close()成員函數銷毀CDatabase對象。一般情況下並不需要直接使用CDatabase對象,因為CRecordSet對象可以實現大多數的功能。但是在進行事務處理時,CDatabase就起到關鍵作用。事務(Transaction)指的是將一系列對數據源的更新放在一起,同時提交或一個也不提交,為的是確保多用戶對數據源同時操作時的數據正確性。
CRecordSet類:一個CRecordSet對象代表一個從數據源選擇的一組記錄的集合-記錄集。記錄集有兩種形式:snapshot和dynaset。前者表示數據的靜態視圖,後者表示記錄集與其他用戶對資料庫的更新保持同步。通過CRecordSet對象,用戶可以對資料庫中的記錄進行各種操作。
CRecordView類:CRecordView對象是在空間中顯示資料庫記錄的視圖。這種視圖是一種直接連到一個CRecordSet對象的格式視圖,它從一個對話框模板資源創建,並將CRecordSet對象的欄位顯示在對話框模板的控制項里。對象利用DDX和RFX機制,使格式上的控制項和記錄集的欄位之間數據移動自動化,也就是說,用戶甚至不要編寫一行代碼就可以實現簡單的資料庫記錄查看程序。
CDBException類:由Cexception類派生,以三個繼承的成員變數反映對資料庫操作時的異常:
m_nRetCode:以ODBC返回代碼(SQL_RETURN)的形式表明造成異常的原因。
m_strError:字元串,描述造成拋出異常的錯誤原因。
m_strStateNativeOrigin:字元串,用以描述以ODBC錯誤代碼表示的異常錯誤。
MFC資料庫類成員函數都能拋出CDBException類型的異常,所以在代碼對資料庫進行操作後監測異常是正確做法。
MFC ODBC類在實際開發中應用最廣,因為它功能豐富,操作相對簡便。
3.MFC DAO(數據訪問對象)編程:DAO用於和微軟的Access資料庫介面。在資料庫應用程序如果只需與Access資料庫介面時,使用DAO編程較方便。其主要類如下。
CDaoWorkspace:CDaoWorkspace對象可以讓一個用戶管理從登陸到離開期間,指定的密碼保護的資料庫會話全過程。大多數情況下不要多個工作區也不要創建明確的工作區對象。因為在打開資料庫和記錄集對象時,它們可以使用DAO預設工作區。
CDaoDatabase:代表一個連接,類似上述CDatabase類。
CDaoRecordSet:用來選擇記錄集並操作,類似上述CRecordSet類。
CDaoRecordView:類似上述CRecordView類。
CDaoException:類似上述CDBException類。
CDaoTableDef:表示基本表或附加表的定義。每個DAO資料庫對象包括一個稱為TableDef的收集,包含所有存儲的DAO表定義對象。CDaoTableDef對象可以用來控製表定義。
CDaoQueryDef:CDaoQueryDef對象表示了一個查詢定義(querydef)。
CDaoFieldExchange:支持資料庫類使用的DAO欄位交換(DFX)常式。也可處理事務,類似MFC ODBC類。
MFC DAO僅用來支持Access資料庫,應用范圍相對固定。
4.OLE DB:OLE DB在數據提供程序和用戶之間提供了靈活的組件對象模型(COM)介面,這種靈活性有時會使得操作復雜化。OLE DB框架定義了應用的三個基本類。
數據提供程序Data Provider:擁有自己的數據並以表格形式顯示數據的應用程序。提供OLE DB的行集COM介面,期顯示範圍可以從單一數據表格的簡單提供者知道更復雜的分布式資料庫系統。
使用者Consumers:使用OLE DB介面對存儲在數據提供程序中的數據進行控制的應用程序。用戶應用程序歸為使用類。
服務提供程序Service Provider:是數據提供程序和使用者的組合。服務提供程序沒有自己的數據,但使用
OLE DB使用者介面來訪問存儲在數據提供程序中的數據。然後,服務提供程序通過打開數據提供程序介面使得數據對使用者有效。服務提供程序常用於向應用程序提供高層次服務,比如高級分布式查詢。
OLE DB編程時,用戶使用組件對象開發應用程序。這些組件有:
枚舉器:用於列出可用的數據源;
數據源:代表單獨的數據和服務提供程序,用於創建對話;
對話:用於創建事務和命令;
事務:用於將多個操作歸並為單一事務處理;
命令:用於向數據源發送文本命令(SQL),返回行集;
錯誤:用於獲得錯誤信息。
5.ActiveX數據對象(ADO):是微軟提供的面向對象的介面,與OLE DB類似,但介面更簡單,具有更廣泛的特徵數組和更高程度的靈活性。ADO基於COM,提供編程語言可利用的對象,除了面向VC++,還提供面向其他各種開發工具的應用,如VB,VJ等。ADO在伺服器應用方面非常有用,特別是對於動態伺服器頁面ASP(Active Server Page)。
ADO對象結構類似於OLE DB,但並不依靠對象層次。大多數情況下,用戶只需要創建並只使用需要處理的對象。下面的對象類組成了ADO介面。
Connection:用於表示與資料庫的連接,以及處理一些命令和事務。
Command:用於處理傳送給數據源的命令。
Recordset:用於處理數據的表格集,包括獲取和修改數據。
Field:用於表示記錄集中的列信息,包括列值和其他信息。
Parameter:用於對傳送給數據源的命令之間來回傳送數據。
Property:用與操作在ADO中使用的其他對象的詳細屬性。
Error:用於獲得可能發生的錯誤的詳細信息。
在VC++使用ADO需要進行COM操作,詳細方法在此就不贅述了。
在當今流行的分布式開發環境下,VC++6.0在資料庫開發方面有較強的優勢,學會
在不同的場合選用不同的技術,對開發人員來說是必要的技術。

3. 關於C語言連接SQL資料庫…

1、配置ODBC數據源。
2、使用SQL函數進行連接。
對於1、配置數據源,配置完以後就可以編程操作資料庫了。
對於2、使用SQL函數進行連接,參考代碼如下:

#include<windows.h>
#include<sql.h>
#include<sqlext.h>
void main()
{
HENV henv; //環境句柄
HDBC hdbc; //數據源句柄
HSTMT hstmt; //執行語句句柄
unsigned char datasource[]="數據源名稱"; //即<a href="https://www..com/s?wd=ODBC&tn=44039180_cpr&fenlei=_5y9YIZ0lQzqlpA-" target="_blank" class="-highlight">ODBC</a>源中設置的源名稱
unsigned char user[]= "用戶名"; //資料庫的帳戶名
unsigned char pwd[]= "密碼"; //資料庫的密碼
unsigned char search[]="select xm from stu where xh=0";
SQLRETURN retcode; //記錄各SQL函數的返回情況
// 分配環境句柄
retcode= SQLAllocEnv(&henv); // 等介於 SQLAllocHandle(SQL_HANDLE_ENV, SQL_<a href="https://www..com/s?wd=NULL&tn=44039180_cpr&fenlei=_5y9YIZ0lQzqlpA-" target="_blank" class="-highlight">NULL</a>_HANDLE, &henv);
// 設置ODBC環境版本號為3.0
retcode= SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// 分配連接句柄
retcode= SQLAllocConnect(henv,&hdbc); // 等介於 SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
//設置連接屬性,登錄超時為*rgbValue秒(可以沒有)
// SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)(rgbValue), 0);

//直接連接數據源
// 如果是windows身份驗證,第二、三參數可以是<a href="https://www..com/s?wd=NULL&tn=44039180_cpr&fenlei=_5y9YIZ0lQzqlpA-" target="_blank" class="-highlight">NULL</a>,也可以是任何字串
//SQL_NTS 即 "<a href="https://www..com/s?wd=Null&tn=44039180_cpr&fenlei=_5y9YIZ0lQzqlpA-" target="_blank" class="-highlight">Null</a>-Terminated String"
retcode= SQLConnect(hdbc,datasource, SQL_NTS, user, SQL_NTS , pwd, SQL_NTS );
//分配語句句柄
retcode= SQLAllocStmt(hdbc,&hstmt); // 等介於 SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
//直接執行查詢語句
retcode=SQLExecDirect(hstmt,search,SQL_NTS);
//將數據緩沖區綁定資料庫中的相應欄位(i是查詢結果集列號,queryData是綁定緩沖區,BUFF_LENGTH是緩沖區長度)
SQLBindCol(hstmt, i, SQL_C_CHAR, queryData[i-1], BUFF_LENGTH, 0);
//遍歷結果集到相應緩沖區 queryData
SQLFetch(hstmt);
/*
*對遍歷結果的相關操作,如顯示等
*/
//注意釋放順序,否則會造成未知錯誤!
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

代碼看上去很復雜,其實都可以直接復制。其中需要改的是數據源名稱、資料庫用戶名、資料庫密碼和SQL語句。
然後就是SQLFetch後得到結果集後,如何使用的問題了。
在下面的注釋部分 填寫你的處理代碼即可。

/*
*對遍歷結果的相關操作,如顯示等
*/

4. 有高人告一下c語實際操作sql server的select *from mytables 我IP埠庫名分別是127.0.0.1:1433 mydb;

1、埠的寫法錯誤,應為:127.0.0.1,1433

2、C/C++可以使用ODBC連接MSSQL數纖租據庫,大致如下:

1)創建ODBC數據源

2)C/C++程序鏈接資料庫

#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<sql.h>
#include<sqlext.h>
#include<sqltypes.h>
#include<odbcss.h>
#defineMAXBUFLEN255
SQLHENVhenv=SQL_NULL_HENV;
SQLHDBChdbc1=SQL_NULL_HDBC;
SQLHSTMThstmt1=SQL_NULL_HSTMT;

/*cpp文件功能說明:
1.資料庫操作中的添加,修改,刪除,主要體現在SQL語句上a
2.採用直接執行方式和參數預編譯執行方式兩種
*/

intmain()
{
RETCODEretcode;

UCHARszDSN[15]="mydb";//數據源名稱
UCHARuserID[6]="sa";//資料庫用戶ID
UCHARpassWORD[29]="123456";//用戶密碼

//1.連接數據源
//1.環境句柄
retcode=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
retcode=SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
//2.連接句柄
retcode=SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc1);
retcode=SQLConnect(hdbc1,szDSN,SQL_NTS,userID,SQL_NTS,passWORD,SQL_NTS);
//判斷連接是否成功
if((retcode!=SQL_SUCCESS)&&(retcode!=SQL_SUCCESS_WITH_INFO))
{
printf("連接失敗! ");
}
else
{
/*
1.分配一個語句句柄(statementhandle)
2.創建SQL語句
3.執行語句
4.銷毀語毀鍵兆句
*/
retcode=SQLAllocHandle(SQL_HANDLE_STMT,hdbc1,&hstmt1);
char亮並sql[100]="insertintotestvalues(22,22)";