使用OCI向Oracle插入Geometry数据
使用C/C++操作Oracle数据库,使用OCI可谓是最强大,当然也是最难的方式。Oracle是一个功能复杂而强大的数据库,它可以很好的支持空间数据(Oracle spatial)。如何使用OCI向Oracle数据库中插入空间数据(SDO_GEOMETRY字段)呢,本文将给出代码。
首先,给出OCI连接数据库的代码:(ph开头的变量均是OCI句柄)
//以指定的模式创建环境句柄
OCIEnvCreate(&phEnv,connMode,(dvoid *),,,,(size_t),(dvoid **));
//分配服务器句柄,注意不要少了取值符号&
OCIHandleAlloc((dvoid *)phEnv,(dvoid **)&phServer,OCI_HTYPE_SERVER,,(dvoid **));
//分配错误句柄
OCIHandleAlloc((dvoid *)phEnv,(dvoid **)&phErr,OCI_HTYPE_ERROR,,(dvoid **));
//创建服务器上下文句柄,c_str()函数将C++类型的string字符串转化为C串 char*
if(OCIServerAttach(phServer,phErr,(text *)DBname.c_str(),strlen(DBname.c_str()),OCI_DEFAULT) ==OCI_SUCCESS)
cout<<"DB "+DBname+" is connected successfully!"<<endl;
else
{
cout<<"DB "+DBname+" is fail to connect,Please check whether you type a right DB name!"<<endl;
}
//分配上下文句柄
OCIHandleAlloc((dvoid *)phEnv,(dvoid **)&phSvcCtx,OCI_HTYPE_SVCCTX,,(dvoid **));
//设置服务器上下文句柄的服务器句柄属性
OCIAttrSet((dvoid *)phSvcCtx,OCI_HTYPE_SVCCTX,(dvoid *)phServer,(ub4),OCI_ATTR_SERVER,phErr);
//分配用户会话句柄
OCIHandleAlloc((dvoid *)phEnv,(dvoid **)&phSession,OCI_HTYPE_SESSION,,(dvoid **));
//为用户会话句柄设置用户名和密码属性
OCIAttrSet((dvoid *)phSession,OCI_HTYPE_SESSION,(dvoid *)username.c_str(),(ub4)strlen(username.c_str()),OCI_ATTR_USERNAME,phErr);
OCIAttrSet((dvoid *)phSession,OCI_HTYPE_SESSION,(dvoid *)password.c_str(),(ub4)strlen(password.c_str()),OCI_ATTR_PASSWORD,phErr);
//申请描述句柄
OCIHandleAlloc((dvoid*)phEnv,(dvoid**)&phdsc,OCI_HTYPE_DESCRIBE,,(void**));
if (OCISessionBegin(phSvcCtx,phErr,phSession,OCI_CRED_RDBMS,OCI_DEFAULT)==OCI_SUCCESS)
{
cout<<"user session is created successfully!"<<endl;
}
else
{
cout<<"user session is fail to create! "<<endl;
}
//在服务器上下文环境中设置用户会话属性
OCIAttrSet((dvoid *)phSvcCtx, OCI_HTYPE_SVCCTX,(dvoid *)phSession,(ub4) ,OCI_ATTR_SESSION,phErr);
接下来进行数据插入:
//HYARRAYT型指针
OCIType * ordinates_tdo =NULL;
//HYARRAYT的类型映射OCIARRAY
OCIArray * hyarray_Point =NULL;
//HYARRAYT的类型映射OCIARRAY
OCIArray * hyarray_MBR =NULL;
OCINumber oci_number;
//声明绑定
OCIBind* bndhp1 = NULL;
OCIBind* bndhp2 = NULL;
//创建用于描述SDO_ORDINATE_ARRAY类型的描述符
ordinates_tdo = get_tdo(SDO_ORDINATE_ARRAY);
//分配语句句柄
CheckErr(phErr,OCIHandleAlloc(phEnv,(void **)&phStmt,OCI_HTYPE_STMT,,));
string sql_str ="";
sql_str = "INSERT INTO "+table+" VALUES(:1,SDO_GEOMETRY(2002,NULL,NULL,SDO_ELEM_INFO_ARRAY( 1,2,1),:ordinates))"
text * insert = (text*)sql_str.c_str();
//准备SQL语句
CheckErr(phErr,OCIStmtPrepare(phStmt,phErr,insert,strlen((char *)insert),OCI_NTV_SYNTAX,OCI_DEFAULT)); //变长数组类型的初始化,初始化SDO_ORDINATE_ARRAY
CheckErr(phErr,OCIObjectNew(phEnv,phErr,phSvcCtx,OCI_TYPECODE_VARRAY,ordinates_tdo,(dvoid*)NULL,OCI_DURATION_SESSION,FALSE,(dvoid**)&hyarray_Point));
vector<trackpoint> pointSet = track.getPointSet();
//输入坐标值 (linestring)
for (int i=;i<pointSet.size();i++)
{
CheckErr(phErr,OCINumberFromReal(phErr,(dvoid*)&pointSet[i].lon,(uword)sizeof(double),&oci_number));
CheckErr(phErr,OCICollAppend(phEnv,phErr,(dvoid*)&oci_number,(dvoid*),(OCIColl*)hyarray_Point));
CheckErr(phErr,OCINumberFromReal(phErr,(dvoid*)&pointSet[i].lat,(uword)sizeof(double),&oci_number));
CheckErr(phErr,OCICollAppend(phEnv,phErr,(dvoid*)&oci_number,(dvoid*),(OCIColl*)hyarray_Point));
}
//绑定变量
CheckErr(phErr,OCIBindByPos(phStmt,&bndhp1,phErr,,&nid,sizeof(int),SQLT_FLT,,,,,,OCI_DEFAULT));
//变量绑定,此处为坐标
CheckErr(phErr,OCIBindByName(phStmt,&bndhp1,phErr,(text*)":ordinates",(sb4)-,(dvoid*),(sb4),SQLT_NTY,(dvoid*),(ub2*),(ub2*),(ub4),(ub4*),(ub4)OCI_DEFAULT));
CheckErr(phErr,OCIBindObject(bndhp1,phErr,ordinates_tdo,(dvoid**)&hyarray_Point,(ub4*),(dvoid**),(ub4*)));
//执行SQL语句
CheckErr(phErr,OCIStmtExecute(phSvcCtx,phStmt,phErr,,,NULL,NULL,OCI_DEFAULT));
OCITransCommit(phSvcCtx,phErr,(ub4));
应该注意的是Oracle spatial的SDO_GEOMETRY字段,它的构建方式为:
SDO_GEOMETRY(
2002 --表示集合类型,此处为线串
NULL --表示坐标系
NULL -- 表示点的类型
SDO_ELEM_INFO_ARRAY(1,2,1) --表示几何的属性
SDO_ORDINATE_ARRAY --表示几何类型的坐标
(
x1,x2,
x3,x4,
.....
xn,xn+1
)
)
以上具体可查看Oracle官方文档。
使用OCI向Oracle插入Geometry数据的更多相关文章
- oracle 插入表数据的4种方式
1.往表中插入一整行数据 /*方法一*/ INSERT INTO 表名 VALUES(val1,val2,val3,...); /*方法二*/ '; 如: ,, FROM DUAL; 注意: 2. ...
- Oracle插入中文数据乱码 设置服务器编码和客户端编码一致
- oracle插入字符串数据时,字符串中有'单引号
使用insert into(field1,field2...) values('val1','val2'...)时,若值中有单引号时会报错. 处理方法:判断一下val1,val2中是否含有单引号,若含 ...
- ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法
ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法 语法 第一种: 通过使用Oracle语句块 --指定文档所有部门都能查看 declare cursor TABLE_DEPT and ...
- Oracle 插入数据效率对比
oracle插入数据有多种方式: 将从多个表中查出来的数据插入到临时表中 数据行数 5189597 1.传统方式:直接将数据插入到表中 insert into LLB_BASIC_USER_D_TEM ...
- 在mysql数据库中创建oracle scott用户的四个表及插入初始化数据
在mysql数据库中创建oracle scott用户的四个表及插入初始化数据 /* 功能:创建 scott 数据库中的 dept 表 */ create table dept( deptno int ...
- ThinkPHP 3.2.3+ORACLE插入数据BUG修复及支持获取自增Id的上次记录
TP+ORACLE插入数据BUG修复以及获取自增Id支持getLastInsID方法 这些天在做Api接口时候,发现用TP操作Oracle数据库,发现查询修改删除都能执行, 但一旦执行插入操作老是报错 ...
- Oracle 函数 “把当前的用户(审核人,审核通过后)插入到数据表中”
create or replace function mcode_apply_update_personnel(p_mca_no VARCHAR2, -- 参数(实参) p_action VARCHA ...
- 003杰信-在jsp页面输入数据,然后在oracle数据库中插入factory数据,当字段允许为空时要特殊处理
本博客的内容全部来自于传智播客,特在此说明. 业务要求如下:在jsp页面(jFactoryCreate.jsp)上输入数据时,转到后台,并输入到数据库. jFactoryCreate.jsp页面:
随机推荐
- Oracle 修改一行数据内存主要变化
向Oracle 数据库发出请求,修改一行数据,在内存中主要有以下变化: 1. 服务器进程将包含该行数据的块读取到内存中 2. 写redo日志.将内存中该数据块指向undo表空间中数据块的变更向量(Ch ...
- android UI库
https://github.com/wasabeef/awesome-android-ui List of Android UI/UX Libraries A curated list of awe ...
- 项目解析- JspLibrary - part2
banner.jsp 验证用户是否登录 <%String manager=(String)session.getAttribute("manager"); //验证用户是否登 ...
- LocalStorage在Chrome里的实现
前段时间我们在实现CanTK-Runtime时,也曾在V8基础上模拟过浏览器的LocaleStorage功能,其实现非常简单:每个domain的数据使用的单独文件存储,因为同一时间只有一个游戏运行,所 ...
- java main函数
public static void main(String[] args)[String args[]]也对 1)public :公共的权限最大,在任何情况下都可以访问. 原因:为了保证java虚拟 ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 理论与实践中的 C# 内存模型
转载自:https://msdn.microsoft.com/magazine/jj863136 这是该系列(包含两部分内容)的第一部分,这部分将以较长的篇幅介绍 C# 内存模型. 第一部分说明 C# ...
- Qt Charts
简述 Qt Charts模块提供了一套易于使用的图表组件.它采用了Qt Graphics View框架,因此图表可以很容易地集成到现代的用户界面. Qt Charts可以被用作QWidgets.QGr ...
- MyEclipse自动补全与快捷键设置
一般默认情况下,Eclipse ,MyEclipse的代码提示功能是比Microsoft Visual Studio的差很多的,主要是Eclipse ,MyEclipse本身有很多选项是默认关闭的,要 ...
- JDK1.7-LinkedList循环链表优化
最近在看jdk1.7的时候,发现LinkedList 和1.6中的变化. 首先,简单介绍一下LinkedList: LinkedList是List接口的双向链表实现.由于是链表结构,所以长度没有限制: ...