Oracle是一個(gè)功能強(qiáng)大的數(shù)據(jù)庫(kù)管理系統(tǒng),它能夠處理海量數(shù)據(jù),并提供強(qiáng)大而穩(wěn)定的基礎(chǔ)功能。在
C語(yǔ)言中,我們可以通過(guò)
ODBC或者
OCI這些接口來(lái)操作 Oracle 數(shù)據(jù)庫(kù)。
比如,下面這段程序就演示了如何連接 Oracle 數(shù)據(jù)庫(kù),并且執(zhí)行一條 SQL 語(yǔ)句:
#include <stdio.h>
#include <stdlib.h>
#include <oci.h>
void checkerr(errhp, status)
OCIError *errhp;
sword status;
{
if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) {
oratext errbuf[512];
OCIErrorGet((dvoid*)errhp, (ub4)1, (text*)NULL, &errcode,
errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
printf("%s\n", errbuf);
exit(1);
}
}
int main()
{
OCIEnv *envhp;
OCIServer *srvhp;
OCIError *errhp;
OCISession *usrhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIResultSet *rsetp;
OCIDateTime *datetime;
OCILobLocator *lob;
OCIDefine *dfnhp;
OCIBind *bndhp;
oratext *username = (oratext*) "scott";
oratext *password = (oratext*) "tiger";
ub4 username_len = strlen(username);
ub4 password_len = strlen(password);
oratext *stmt = (oratext*) "SELECT * FROM emp";
ub4 stmt_len = strlen(stmt);
sword status;
checkerr(errhp, OCIEnvCreate(&envhp, OCI_DEFAULT, (dvoid *)0,
(dvoid * (*)(dvoid *, size_t))0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *))0,
(size_t)0, (dvoid **)0));
checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&srvhp,
OCI_HTYPE_SERVER, (size_t)0, (dvoid **)0));
checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,
OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0));
checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&usrhp,
OCI_HTYPE_SESSION, (size_t)0, (dvoid **)0));
checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&svchp,
OCI_HTYPE_SVCCTX, (size_t)0, (dvoid **)0));
checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&stmthp,
OCI_HTYPE_STMT, (size_t)0, (dvoid **)0));
checkerr(errhp, OCILogon2(envhp, errhp, &svchp, username, username_len,
password, password_len, NULL, 0));
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, stmt, stmt_len,
OCI_NTV_SYNTAX, OCI_DEFAULT));
checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4)0, (ub4)0,
(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT));
checkerr(errhp, OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT));
checkerr(errhp, OCIDescribe(svchp, errhp, stmt, stmt_len,
OCI_NTV_SYNTAX, OCI_DEFAULT, NULL));
// ...
}
在上面這段代碼中,我們第一步創(chuàng)建了一個(gè)數(shù)據(jù)庫(kù)環(huán)境,并分配了一些 handler,比如
OCIServer、
OCIError等。然后調(diào)用
OCILogon2函數(shù)鏈接到了我們的數(shù)據(jù)庫(kù),并準(zhǔn)備了一條 SQL 語(yǔ)句,最后執(zhí)行它。
除了常規(guī)的 SQL 基本操作,Oracle 還提供了許多功能擴(kuò)展的操作,比如大對(duì)象(
LOB)、
BLOB、
CLOB等特殊的類型。另外,Oracle 還支持一些特殊的函數(shù)和操作,比如
UNISTR、
HEXTORAW等,可以幫助我們更方便地對(duì)字符和二進(jìn)制數(shù)據(jù)進(jìn)行操作。
最后,值得一提的是,Oracle 代碼的編寫(xiě)需要非常注重安全性,尤其是SQL注入漏洞。一般來(lái)說(shuō),我們需要對(duì)查詢語(yǔ)句中變化的地方進(jìn)行參數(shù)化,而不是直接拼接字符串。比如:
char *name = "smith";
ub4 name_len = strlen(name);
char stmt[1000];
strcpy(stmt, "SELECT * FROM emp WHERE name = :name");
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, stmt, strlen(stmt),
OCI_NTV_SYNTAX, OCI_DEFAULT));
checkerr(errhp, OCIBindByName(stmthp, bndhp, errhp, (const oratext *) ":name",
strlen(":name"), buf, name_len,
SQLT_STR, NULL, NULL, NULL, 0, NULL,
OCI_DEFAULT));
將查詢語(yǔ)句中涉及到的參數(shù)用 ":param" 的形式替換,然后通過(guò)
OCIBindByName將參數(shù)傳遞進(jìn)去,這樣可以防止 SQL 注入攻擊。