C语言轻松实现Oracle中存储大文件
传统的关系型数据库在存储大型文件时表现并不出色,而Oracle数据库则可以轻松存储大文件。本文将介绍如何使用C语言轻松实现Oracle中存储大文件。
Oracle数据库支持以下两种存储大型文件的方式:
1. 通过BLOB(二进制大型对象)数据类型存储文件:BLOB是一种可以存储任意形式大型数据的数据库对象类型。它可以存储数据流(如音视频、PDF文档等)或图像数据(如JPG、PNG等)等。
2. 通过BFILE(二进制文件)数据类型存储文件:BFILE是Oracle中存储二进制文件的特殊数据类型。它是指一个数据库对象,存储在硬盘上。
下面是使用C语言存储BLOB类型文件的示例代码:
#include
#include
#include
#define DATA_SIZE 1024
void checkerr(OCIError *errhp, sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
printf("Warning: %s\n", OCIErrorGet((dvoid *)errhp, (ub4)1, (text *)NULL, &errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR));
break;
case OCI_NEED_DATA:
printf("Warning: OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
printf("Warning: OCI_NO_DATA\n");
break;
case OCI_ERROR:
OCIErrorGet((dvoid *)errhp, (ub4)1, (text *)&errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
printf("Error - Code: %d, Message: %s\n", errcode, errbuf);
exit(1);
break;
case OCI_INVALID_HANDLE:
printf("Warning: OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
printf("Warning: OCI_STILL_EXECUTE\n");
break;
case OCI_CONTINUE:
printf("Warning: OCI_CONTINUE\n");
break;
default:
break;
}
}
int mn(int argc, char *argv[])
{
OCIEnv *envhp = NULL;
OCIServer *srvhp = NULL;
OCIError *errhp = NULL;
OCISession *authp = NULL;
OCIStmt *stmthp = NULL;
OCILobLocator *lobp = NULL;
OCILobLocator *lobLen = NULL;
oratext *username = (oratext *) "username";
oratext *password = (oratext *) "password";
oratext *dbname = (oratext *) "dbname";
oratext *tblname = (oratext *) "tblname";
char * filename = "test.png";
ub4 stmttype = OCI_STMT_SELECT;
ub4 mode = OCI_DEFAULT;
ub4 prefetchrows = 1;
OCILogon2(envhp, errhp, &authp, username, strlen(username), password, strlen(password), dbname, strlen(dbname), OCI_DEFAULT);
OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, (size_t) 0, (dvoid **) 0);
checkerr(errhp, OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, (size_t) 0, (dvoid **) 0));
checkerr(errhp, OCIServerAttach(srvhp, errhp, (text *) dbname, strlen(dbname), OCI_DEFAULT));
OCIHandleAlloc(envhp, (void **)&stmthp, OCI_HTYPE_STMT, 0, NULL);
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) "select * from tablename", strlen("select * from tablename"), OCI_NTV_SYNTAX, OCI_DEFAULT));
if (OCIDefineByPos(stmthp, &defhp, errhp, 1, (dvoid *) &lobp, -1, SQLT_BLOB, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT) != OCI_SUCCESS)
{
printf("OCIDefineByPos fled\n");
exit(1);
}
checkerr(errhp, OCILogon2(envhp, errhp, &authp, username, strlen(username), password, strlen(password), dbname, strlen(dbname), OCI_DEFAULT));
if (OCIStmtExecute(srvhp, stmthp, errhp, (ub4)1, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT) != OCI_SUCCESS) {
printf("OCIStmtExecute fled\n");
exit(1);
}
FILE *pFile = fopen(filename, "rb");
fseek(pFile, 0, SEEK_END);
int file_size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
char * pBuf = (char *) malloc(file_size);
fread(pBuf, 1, file_size, pFile);
fclose(pFile);
checkerr(errhp, OCILobCreateTemporary(srvhp, errhp, &lobp, OCI_DEFAULT, SQLT_BLOB, TRUE, OCI_DURATION_SESSION));
checkerr(errhp, OCILobWrite(srvhp, errhp, lobp, &file_size, 1, (dvoid *)pBuf, (file_size > DATA_SIZE) ? DATA_SIZE : file_size, OCI_ONE_PIECE, (dvoid *)0, (sb4 (*)(void *, const void *, ub4, ub1)) 0, 0, SQLCS_IMPLICIT));
free(pBuf);
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *)"insert into tblname(blob_col) values (:1)", strlen("insert into tblname(blob_col) values (:1)"), OCI_NTV_SYNTAX, OCI_DEFAULT));
if (OCIBindByPos(stmthp, &bndhp, errhp, (ub4) 1, (dvoid *) &lobp, sizeof(OCILobLocator *), SQLT_BLOB, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)0, 0, OCI_DEFAULT) != OCI_SUCCESS)
{
printf("OCIBindByPos fled\n");
exit(1);
}
OCITransCommit(srvhp, errhp, OCI_DEFAULT);
OCILogoff(authp, envhp, errhp);
OCIHandleFree(srvhp, OCI_HTYPE_SERVER);
OCIHandleFree(stmthp, OCI_HTYPE_STMT);
OCIHandleFree(errhp, OCI_HTYPE_ERROR);
OCIHandleFree(envhp, OCI_HTYPE_ENV);
printf("Finish storing BLOB in Oracle!\n");
return 0;
}
上述代码完成了将本地test.png文件存储到Oracle的tablename表中的blob字段。
需要注意的是,在调用初始化连接函数的时候,需要注意传入的连接名称username、password和dbname都需要替换为自己的信息。
总结:
使用Oracle数据库存储大型文件可以避免数据丢失、备份快速等问题,同时Oracle数据库也提供了很多方便的API,方便我们进行使用,可以大大提高开发效率,减少出现问题的几率。