小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【ODBC】ODBC連接數(shù)據(jù)庫詳細(xì)說明

 行走在理想邊緣 2018-12-26

ODBC

一、ODBC簡介

開放數(shù)據(jù)庫互連(ODBC)是微軟提出的數(shù)據(jù)庫訪問接口標(biāo)準(zhǔn)。開放數(shù)據(jù)庫互連定義了訪問數(shù)據(jù)庫的API一個規(guī)范,這些API獨立于不同廠商的DBMS,也獨立于具體的編程語言。通過使用ODBC,應(yīng)用程序能夠使用相同的源代碼和各種各樣的數(shù)據(jù)庫進行交互。這使得開發(fā)者不需要以特殊的數(shù)據(jù)庫管理系統(tǒng)DBMS為目標(biāo),或者了解不同支撐背景的數(shù)據(jù)庫的詳細(xì)細(xì)節(jié),就能夠開發(fā)和發(fā)布客戶/服務(wù)器應(yīng)用程序。下面是ODBC應(yīng)用系統(tǒng)的體系結(jié)構(gòu)。

二、ODBC句柄

應(yīng)用程序運行后,為維護執(zhí)行的狀態(tài),ODBC 管理器和ODBC 驅(qū)動程序中必須保持足夠的控制信息。應(yīng)用程序要求ODBC 管理器和ODBC 驅(qū)動程序為ODBC環(huán)境、每個連接以及每個SQL語句分配描述/控制信息存儲空間,并返回指向各個存儲區(qū)的句柄供其使用。

  1)環(huán)境句柄:整個ODBC上下文的根句柄。標(biāo)識全程數(shù)據(jù)訪問控制信息的內(nèi)存結(jié)構(gòu),包括有效連接句柄以及當(dāng)前活動連接句柄。ODBC將環(huán)境句柄定義為HENV類型的變量。應(yīng)用程序使用單一的環(huán)境句柄,在連接到數(shù)據(jù)源以前必須申請該句柄。

  2)連接句柄:管理有關(guān)數(shù)據(jù)庫會話的所有信息。連接句柄標(biāo)識每個特定的連接信息的內(nèi)存結(jié)構(gòu)。ODBC將環(huán)境句柄定義為HDBC類型的變量。應(yīng)用程序在連接數(shù)據(jù)源之前申請連接句柄。每個連接句柄與環(huán)境句柄有關(guān),環(huán)境句柄上可以有多個與其有關(guān)的連接句柄。

  3)語句句柄:ODBC語句包括應(yīng)用訪問數(shù)據(jù)源的SQL語句和語句相關(guān)的管理信息,語句句柄標(biāo)識每個語句管理信息的內(nèi)存結(jié)構(gòu)。ODBC將語句句柄定義為HSTMT類型的變量。應(yīng)用程序在提交SQL請求之前也必須申請語句句柄。每個語句句柄與一個連接句柄有關(guān),每個連接句柄上可以有多個與其有關(guān)的語句句柄。

三、ODBC程序執(zhí)行流程

分配環(huán)境句柄

基于ODBC3.X版本的應(yīng)用統(tǒng)一使用SQLAllocHandle來分配句柄。調(diào)用時設(shè)計不同的句柄類型就可以獲得該類型的句柄。但在API內(nèi)部實現(xiàn)上一般重新轉(zhuǎn)換為執(zhí)行SQLAllocEnv,SQLAllocConnectSQLAllocStmt,這樣可以達(dá)到兼容和代碼重用作用。SQLAllocEnv:用來分配環(huán)境句柄。

例如:ret = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &oraclehenv);

分配連接句柄

  SQLAllocConnect:用來分配連接句柄。連接句柄提供對一些信息的訪問,例如,在連接上的有效語句及標(biāo)識符句柄,以及當(dāng)前是否打開一些一個事務(wù)處理。調(diào)用SQLAllocConnect 函 數(shù) 獲 取 連 接 句 柄。例如:

 ret = SQLAllocHandle(SQL_HANDLE_DBC, oraclehenv, &oraclehdbc);

?  建立數(shù)據(jù)源

使用已分配的連接句柄來建立應(yīng)用程序和數(shù)據(jù)源/數(shù)據(jù)庫系統(tǒng)的連接,進行句柄和數(shù)據(jù)源的綁定。綁定也由目標(biāo)數(shù)據(jù)源的ODBC驅(qū)動程序完成。

如:ret = SQLConnect(oraclehdbc,                                                    

"conn",SQL_NTS, //ODBCDNS名稱

"scott",SQL_NTS, //用戶賬號

"123",SQL_NTS);     //密碼

分配語句句柄

   用戶對DBC數(shù)據(jù)源的存取操作,都是通過SQL語句實現(xiàn)的。在這個過程中,應(yīng)用程序 將通過連接向ODBC數(shù)據(jù)庫提交SQL語句,以完成用戶請求的操作。即通過執(zhí)行SQLAllocHandleSQLAllocStmt來分配語句句柄。調(diào)用SQLAllocStmt 函數(shù)獲取語句句柄。例如:

SQLstmt= "SELECT * FROM authors"

rc= SQLAllocStmt(hdbc, hstmt)

?  執(zhí)行SQL語句

執(zhí)行SQL語句。 執(zhí)行SQL 語 句 的方法比較多, 最簡單明了的方法是調(diào)用SQLAllocStmt函數(shù),例如:

SQLstmt= "SELECT * FROM authors"

rc= SQLExecDirect(hstmt, SQLstmt, Len(SQLstmt))

    如果SQL語句被順利提交并正確執(zhí)行,那么就會產(chǎn)生一個結(jié)果集。檢索結(jié)果集的方法有很多,最簡單最直接的方法是調(diào)用SQLFetch SQLGetData 函 數(shù)。

SQLFetch函數(shù)的功能是將結(jié)果集的當(dāng)前記錄指針移至下一個記錄;

SQLGetData函數(shù)的功能是提取結(jié)果集中當(dāng)前記錄的某個字段值。通常可以采用一個循環(huán)以提取結(jié)果集中所有記錄的所有字段值,該循環(huán)重復(fù)執(zhí)行SQLFetchSQLGetData函數(shù),直至SQLFetch函數(shù)返回SQL_NO_DATA_FOUND, 這表示已經(jīng)到達(dá)結(jié)果集的末尾。

DimColVal As String * 225

ColVal= String(255, 0)

結(jié)束應(yīng)用程序

在應(yīng)用程序完成數(shù)據(jù)庫操作, 退出運行之前,必須釋放程序中使用的系統(tǒng)資源。這些系統(tǒng)資源包括:語句句柄、連接句柄和ODBC環(huán)境句柄。完成這個過程的如下:

 調(diào)用SQLFreeStmt 函數(shù)釋放語句句柄及其相關(guān)的系統(tǒng)資源。例如:

rc= SQLFreeStmt(hstmt, SQL_DROP)

 調(diào)用SQLDisconnect 函數(shù)關(guān)閉連接。 例 如:

rc= SQLDisconnect(hdbc)

調(diào)用SQLFreeConnect函數(shù)釋放連接句柄及其相關(guān)的系統(tǒng)資源。例如:

rc= SQLFreeConnect(hdbc)

調(diào)用SQLFreeEnv函數(shù)釋放環(huán)境句柄及其相關(guān)的系統(tǒng)資源,停止ODBC 操作。 例如:

rc= SQLFreeEnv(henv)

7)錯 誤 處 理

所有DBCAPI函 數(shù), 若在執(zhí)行期間發(fā)生錯誤, 都將返回一個標(biāo)準(zhǔn)錯誤代碼SQL_ERROR。

一般來講,在每次調(diào)用ODBC API 函 數(shù) 之 后, 都應(yīng)該檢查該函數(shù)返回值,確定該函數(shù)是否成功地執(zhí)行,再決定是否繼續(xù)后續(xù)過程。 而詳細(xì)的錯誤信息,可以調(diào)用SQLError 函數(shù)獲得。SQLError 函數(shù)將返回下列信息: 標(biāo)準(zhǔn)的ODBC錯誤狀態(tài)碼 ODBC 數(shù)據(jù)源提供的內(nèi)部錯誤編碼錯誤信息串

四、開發(fā)環(huán)境的配置

1.創(chuàng)建Oracle ODBC數(shù)據(jù)源

對于WIN 7系統(tǒng)來說,打開控制面板,找到ODBC,具體位置如下圖所示,如果沒有找到,可以在右上角搜索欄里面輸入ODBC,就可以找到了。

對于WIN XP系統(tǒng)來說,打開控制面板,找到管理工具,找到數(shù)據(jù)源(ODBC),顯示ODBC數(shù)據(jù)源管理器對話框。對話框如下圖所示。

2.設(shè)置和配置一個系統(tǒng)DSN,單擊“系統(tǒng)DSN標(biāo)簽”,選擇“添加”。

 


 


 

3.找到需要配置的數(shù)據(jù)源,單擊完成,彈出如下對話框,

 

4.輸入數(shù)據(jù)源的名稱,一個簡單的描述,用戶名和網(wǎng)絡(luò)連接名。點擊確認(rèn)。

 

 

 

五、學(xué)生表創(chuàng)建

1.首先創(chuàng)建stu

create table stu(

sno char(11) ,

sname varchar2(10),

sex char(2),

sage number,

sdepart varchar2(30)

);

 

 

 

 

 

六、數(shù)據(jù)類型

 

 



 

 

七、參考資料

數(shù)據(jù)庫系統(tǒng)概論 第四版 王珊 薩師煊 高等教育出版社

電子資料鏈接:http://pan.baidu.com/s/1su9c5


ODBC程序

開發(fā)工具vs2017

<database.h>

#pragma once

#ifndef _DATABASE_H
#define _DATABASE_H
#include <sql.h>
#include<sqlext.h>
#include<sqltypes.h>
typedef struct {
	SQLHENV oraclehenv;						//環(huán)境句柄
	SQLHDBC oraclehdbc;						//連接句柄
	SQLHSTMT oraclehsmt;					//語句句柄
	SQLRETURN ret;							//結(jié)果集
}DATABASE;


DATABASE getConnection();					//獲取連接
void init(DATABASE *d);						//初始化
void freeConnection(DATABASE d);			//釋放連接資源


#endif // !_DATABASE_H

<student.h>

#pragma once
#include "DATABASE.h"

#ifndef _STUDENT_H
#define _STUDENT_H
#include <sql.h>
#include<sqlext.h>
#include<sqltypes.h>

#define sno_length 11
#define sname_length 10
#define sdepart_length 30
#define ssex_length 5

typedef struct {
	SQLCHAR sno[sno_length], sname[sname_length], sdepart[sdepart_length], ssex[ssex_length];
	SQLSMALLINT sage;
	SQLINTEGER cbsno, cbsname, cbdepart, cbsage, cbsex;
}STUDENT;

SQLCHAR *get(SQLCHAR *p, char *s);		//將char數(shù)組轉(zhuǎn)換SQLCHAR類型
void processSQL(SQLCHAR *sql, SQLHSTMT oraclehsmt);
void display(DATABASE d);
void getStu(char *sno, SQLHSTMT oraclehsmt);
int insert(STUDENT, DATABASE);
void deleteStu(char *sno, DATABASE d);
SQLRETURN  updateStu(STUDENT s, DATABASE d);
STUDENT inputStu();
void error(SQLRETURN err, int n);

#endif // !_DATABASE_H

<getConnection.cpp>

#include"DATABASE.h"
#include <sql.h>
#include<sqlext.h>
#include<sqltypes.h>
#include<stdlib.h>
#include <stdio.h>
#include<windows.h>
#include<string.h>
DATABASE getConnection() {
	DATABASE d;
	/****分配環(huán)境句柄********/
	d.ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &d.oraclehenv);
	d.ret = SQLSetEnvAttr(d.oraclehenv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
	/********建立連接*********/
	d.ret = SQLAllocHandle(SQL_HANDLE_DBC, d.oraclehenv, &d.oraclehdbc);
	d.ret = SQLConnect(d.oraclehdbc, (SQLCHAR *)"con", SQL_NTS, (SQLCHAR *)"HR", SQL_NTS, (SQLCHAR *)"oracle", SQL_NTS);
	if (SQL_SUCCEEDED(d.ret))
	{
		puts("Connect Sucess!");
		init(&d);
	}
	else
	{
		//連接失敗時返回錯誤值
		puts("Conect Fail!");
	}
	return d;
}

void init(DATABASE *d)
{
	/***初始化句柄*/
	SQLEndTran(SQL_HANDLE_DBC, d->oraclehdbc, SQL_COMMIT);						//提交事務(wù)
	d->ret = SQLAllocHandle(SQL_HANDLE_STMT, d->oraclehdbc, &d->oraclehsmt);			//初始化語句句柄
	d->ret = SQLSetStmtAttr(d->oraclehsmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)SQL_BIND_BY_COLUMN, SQL_IS_INTEGER);//設(shè)置語句選項
}


void freeConnection(DATABASE d)
{
	SQLEndTran(SQL_HANDLE_DBC, d.oraclehdbc, SQL_COMMIT);				//提交事務(wù)
	SQLFreeHandle(SQL_HANDLE_STMT, d.oraclehsmt);
	SQLDisconnect(d.oraclehdbc);
	SQLFreeHandle(SQL_HANDLE_DBC, d.oraclehdbc);
	SQLFreeHandle(SQL_HANDLE_ENV, d.oraclehenv);
	printf("釋放連接\n\n");
}

<operateStudent.cpp>

#include "DATABASE.h"
#include "STUDENT.h"
#include <sql.h>
#include<sqlext.h>
#include<sqltypes.h>
#include<stdlib.h>
#include <stdio.h>


void processSQL(SQLCHAR *sql, SQLHSTMT oraclehsmt)
{
	STUDENT s;
	int count = 1;
	s.cbsno = SQL_NTS;
	s.cbsname = SQL_NTS;
	s.cbdepart = SQL_NTS;
	s.cbsage = 0;
	s.cbsex = SQL_NTS;
	SQLRETURN ret = SQLExecDirect(oraclehsmt, sql, SQL_NTS);
	if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
	{
		ret = SQLBindCol(oraclehsmt, 1, SQL_C_CHAR, s.sno, sno_length, &s.cbsno);
		ret = SQLBindCol(oraclehsmt, 2, SQL_C_CHAR, s.sname, sname_length, &s.cbsname);
		ret = SQLBindCol(oraclehsmt, 3, SQL_C_CHAR, s.ssex, ssex_length, &s.cbsex);
		ret = SQLBindCol(oraclehsmt, 4, SQL_C_LONG, &s.sage, 0, &s.cbsage);
		ret = SQLBindCol(oraclehsmt, 5, SQL_C_CHAR, s.sdepart, sdepart_length, &s.cbdepart);
	}
	/***處理結(jié)果**/
	while ((ret = SQLFetch(oraclehsmt)) != SQL_NO_DATA_FOUND )
	{
		if (ret == SQL_ERROR)
		{
			printf("erro!\n");
		}
		else
		{
			printf("\t%-3d    %s   %s   %s  %4d  %s\n", ++count, s.sno, s.sname, s.ssex, s.sage, s.sdepart);
		}
	}
}

void display(DATABASE d)
{
	SQLCHAR *sql = (SQLCHAR *)"select * from stu";
	processSQL(sql, d.oraclehsmt);
}
/*****插入********/
int insert(STUDENT s, DATABASE d)
{
	char str[100] = "insert into stu values(";
	
	char *age = (char *)malloc(sizeof(s.sage) + 1);
	_itoa_s((int)s.sage, age, 10, 10);

	strcat_s(str, sizeof(str), "'");
	strcat_s(str, sizeof(str), (char *)s.sno);
	strcat_s(str, sizeof(str), "',");

	strcat_s(str, sizeof(str), "'");
	strcat_s(str, sizeof(str), (char *)s.sname);
	strcat_s(str, sizeof(str), "',");

	strcat_s(str, sizeof(str), "'");
	strcat_s(str, sizeof(str), (char*)s.ssex);
	strcat_s(str, sizeof(str), "',");

	strcat_s(str, sizeof(str), "'");
	strcat_s(str, sizeof(str), age);
	strcat_s(str, sizeof(str), "',");

	strcat_s(str, sizeof(str), "'");
	strcat_s(str, sizeof(str), (char *)s.sdepart);
	strcat_s(str, sizeof(str), "')");

	d.ret = SQLExecDirect(d.oraclehsmt, (SQLCHAR *)str, SQL_NTS);
	error(d.ret, 77);
	return 0;

}


SQLCHAR *get(SQLCHAR *p, char *s)
{
	if ((s == NULL) || (p == NULL))
	{
		return NULL;
	}
	SQLCHAR *r = p;
	while ((*r++ = *s++) != '\0');
	return p;
}

void getStu(char *sno, SQLHSTMT oraclehsmt)
{
	SQLCHAR *sql;
	char str[100] = "select * from stu where sno = \'";
	strcat_s(str, sizeof(str), sno);
	strcat_s(str, sizeof(str), "'");
	sql = (SQLCHAR *)str;
	printf("getStu()函數(shù)\n");
	getchar();
	processSQL(sql, oraclehsmt);
}

void deleteStu(char *sno, DATABASE d)
{
	SQLCHAR *sql = NULL;
	char str[100] = "delete from stu where sno = \'";
	strcat_s(str, sizeof(str), sno);
	strcat_s(str, sizeof(str), "'");
	sql = (SQLCHAR *)str;
	d.ret = SQLExecDirect(d.oraclehsmt, sql, SQL_NTS);
	error(d.ret, 114);
}

SQLRETURN updateStu(STUDENT s, DATABASE d)
{
	SQLRETURN ret;
	SQLCHAR *sql = NULL;
	char str[100] = "update stu set ";
	char *age = (char *)malloc(sizeof(s.sage) + 1);
	_itoa_s((int)s.sage, age, 10, 10);
	strcat_s(str, sizeof(str), "sname = \'");
	strcat_s(str, sizeof(str), (char *)s.sname);
	strcat_s(str, sizeof(str), "', ");

	strcat_s(str, sizeof(str), "sex = \'");
	strcat_s(str, sizeof(str), (char *)s.ssex);
	strcat_s(str, sizeof(str), "', ");

	strcat_s(str, sizeof(str), "sage = \'");
	strcat_s(str, sizeof(str), age);
	strcat_s(str, sizeof(str), "', ");

	strcat_s(str, sizeof(str), "sdepart = \'");
	strcat_s(str, sizeof(str), (char *)s.sdepart);
	strcat_s(str, sizeof(str), "' ");

	strcat_s(str, sizeof(str), "where sno =  \'");
	strcat_s(str, sizeof(str), (char *)s.sno);
	strcat_s(str, sizeof(str), "'");
	for (int i = 0; i < sizeof(str); i++)
	{
		printf("%c", str[i]);
	}
	printf("\n");
	sql = (SQLCHAR *)str;
	ret = SQLExecDirect(d.oraclehsmt, sql, SQL_NTS);
	error(ret, 150);
	return ret;
}


STUDENT inputStu()
{
	STUDENT s;
	char sno[sno_length], sname[sname_length], ssex[ssex_length], sdepart[sdepart_length], ssage[5];
	int sage;
	fflush(stdin);
	printf("請輸入一個學(xué)號:");
	gets_s(sno, sizeof(sno));
	printf("\n請輸入一個姓名:");
	gets_s(sname, sizeof(sname));
	printf("\n請輸入一個性別:");
	gets_s(ssex, sizeof(ssex));
	printf("\n請輸入一個年齡:");
	sage = atoi(gets_s(ssage));
	printf("\n請輸入一個部門:");
	gets_s(sdepart, sizeof(sdepart));
	get(s.sno, sno);
	get(s.sname, sname);
	get(s.ssex, ssex);
	s.sage = sage;
	get(s.sdepart, sdepart);
	return s;
}

void error(SQLRETURN err, int n) {
	printf("%d ", n);
	switch (err) {
	case	SQL_SUCCESS:puts("****SQL_SUCCESS*****"); break;
	case	SQL_SUCCESS_WITH_INFO:puts("SQL_SUCCESS_WITH_INFO"); break;
	case	SQL_ERROR:puts("SQL_ERROR"); break;
	case	SQL_INVALID_HANDLE:puts("SQL_INVALID_HANDLE"); break;
	case	SQL_NO_DATA_FOUND:puts("SQL_NO_DATA_FOUND"); break;
	case	SQL_NEED_DATA:puts("SQL_NEED_DATA"); break;
	default:puts("err");
	}
}

<Test.cpp>

#include "STUDENT.h"
#include "DATABASE.h"
#include <sql.h>
#include<sqlext.h>
#include<sqltypes.h>
#include<stdlib.h>
#include <stdio.h>
#include<windows.h>
#include<string.h>

char menu()
{
	char choice;
	printf("\t a.查詢4所有人的信息\n");
	printf("\t s.查詢個人信息指定學(xué)號\n");
	printf("\t i.插入\n");
	printf("\t d.刪除\n");
	printf("\t u.修改\n");
	printf("\t q.退出\n");
	printf("\n **********************\n \t請輸入你的選項:");
	choice = getchar();
	return choice;

}

void deal(char choice, DATABASE d)
{
	getchar();
	switch (choice)
	{
		init(&d);
		case 'a':display(d);break;
		case 's': {
			char sno[10];
			fflush(stdin);
			printf("\n請輸入學(xué)號:");
			gets_s(sno);
			printf("sno = %s\n", sno);
			getStu(sno, d.oraclehsmt); break;
		}
		case 'i': {
			STUDENT s = inputStu();
			insert(s, d);break;
		}
		case 'd': {
			char sno[10];
			printf("請輸入學(xué)號:");
			gets_s(sno);
			deleteStu(sno, d); break;
		}
		case 'u': {
			STUDENT s = inputStu();
			updateStu(s, d);break;
		}
		case 'q': freeConnection(d); exit(0);
		default:printf("輸入錯誤,請從新輸入\n"); break;
	}
		printf("\n\t***************處理結(jié)束******************\n");
}


int main()
{	
	DATABASE database = getConnection();
	do
	{
		char c;
		c = menu();
		deal(c,database);
		getchar();
		system("cls");
	} while (true); 

	return 0;
}




<sql>

drop table stu;
create table stu(
       sno char(10),
       sname varchar2(10),
       sex char(5),
       sage number,
       sdepart varchar2(30),
       primary key(sno)
);

insert into stu values('201500730','張三','男',20,'計算機系' );
insert into stu values('201500731','李四','男',20,'計算機系' );
insert into stu values('201500732','王五','男',20,'計算機系' );
insert into stu values('201500733','趙六','男',20,'計算機系' );
commit;

select * from stu;



    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多