众所周知,数据是GIS的血液,一个GIS系统最重要的是数据,而且在整个系统的建设过程中的花费也比较大。为此,许多GIS厂商和数据库厂商逐渐推出空间数据的存储解决方案。
其中Oracle Spatial是目前最大的数据库厂商Oracle公司推出的新一代空间数据库,它采用对象关系型数据存储模式来存储空间数据。
空间数据在Oracle中是以SDO_GEOMETRY数据类型来存储的,它的定义为:
SQL> desc sdo_geometry
名称 是否为空?类型
----------------------------------------- -------- -------------------------
SDO_GTYPE NUMBER
SDO_SRID NUMBER
SDO_POINT MDSYS.SDO_POINT_TYPE
SDO_ELEM_INFO MDSYS.SDO_ELEM_INFO_ARRAY
SDO_ORDINATES MDSYS.SDO_ORDINATE_ARRAY
具体的字段解释在这里就不详细说明,可以参见oracle的官方文档或者有关书籍。
首先,用oracle类型转换工具(OTT)把SDO_GEOMETRY数据类型转换成高级语言源程序文件。
D:\>ott userid=scott/tiger intype=demoin.tpy outtype=demoout.tpy code=cpp hfile=
sdogeometry.h cppfile=sdogeometry.cpp mapfile=mappings.cpp attraccess=private
转换后生成了四个C++源文件和头文件。
下面的代码是插入一个矩形。
#include <iostream>
#include <occi.h>
#include <assert.h>
#include "mappings.h"
#include "sdogeometry.h"
using namespace oracle::occi;
using namespace std;
const int SDO_GTYPE = 2003;
int main ()
{
Environment *env = NULL;
Connection *conn = NULL;
Statement *stmt = NULL;
ResultSet *rs = NULL;
string username = "scott"; //用户名
string password = "tiger"; //密码
string connstring = "//localhost:1521/ORCL"; //连接字符串
string sql,strname;
int errNum = 0;
string errMsg = "";
env = Environment::createEnvironment(Environment::OBJECT); //创建一个环境变量
mappings(env); //注册函数
try
{
assert(env != NULL);
conn = env->createConnection(username,password,connstring); //创建一个数据库连接对象
stmt = conn->createStatement(); //创建一个Statement对象
}
catch (SQLException ex)
{
errNum = ex.getErrorCode();
errMsg = ex.getMessage();
cout << "Error Number : "<< errNum << endl; //取出异常代码
cout << "Error Message :" <<errMsg << endl; //取出异常信息
}
//数据处理部分
sql = "Insert Into spatial(geoloc) VALUES (:1)";
try
{
Number srid_null; //SRID
srid_null.setNull();
sdo_point_type *point_type = new sdo_point_type(); //SDO_POINT_TYPE
point_type->setNull();
vector<Number> sdo_elem_info,sdo_ordinates; //元素信息和坐标数据
sdo_elem_info.clear();
sdo_ordinates.clear();
sdo_elem_info.push_back(1);
sdo_elem_info.push_back(1003);
sdo_elem_info.push_back(3);
sdo_ordinates.push_back(1);
sdo_ordinates.push_back(1);
sdo_ordinates.push_back(5);
sdo_ordinates.push_back(7);
SDO_GEOMETRY *sdo_geometry = new SDO_GEOMETRY();
sdo_geometry->setsdo_gtype(SDO_GTYPE);
sdo_geometry->setsdo_srid(srid_null);
sdo_geometry->setsdo_point(point_type);
sdo_geometry->setsdo_elem_info(sdo_elem_info);
sdo_geometry->setsdo_ordinates(sdo_ordinates);
stmt->setSQL(sql);
stmt->setObject(1,sdo_geometry); //设置对象
stmt->executeUpdate(); //执行更新操作
delete sdo_geometry;
}
catch (SQLException ex)
{
errNum = ex.getErrorCode();
errMsg = ex.getMessage();
cout << "Error Number : "<< errNum << endl; //取出异常代码
cout << "Error Message :" <<errMsg << endl; //取出异常信息
}
conn->terminateStatement(stmt); //终止Statement对象
env->terminateConnection(conn); //断开数据库连接
Environment::terminateEnvironment(env); //终止环境变量
return 1;
}
插入后,查询的结果如下:
SQL> select * from spatial;
GEOLOC(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------------------------------------------------
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3), SDO_ORDINATE_ARRAY(1, 1, 5, 7))
这只是对示例数据进行上载,还需要对实际的地理空间数据进行测试,比如shapefile文件的上载。
读取和一般的关系型数据读取一样,只不过看成是一个对象就可以了。
//以下代码是读取数据代码
string sqlQuery = "SELECT * FROM spatial";
stmt->setSQL(sqlQuery);
rs = stmt->executeQuery(sqlQuery);
while (rs->next())
{
SDO_GEOMETRY* geometry = (SDO_GEOMETRY*)rs->getObject(1);
cout<<"SDO_GTYPE: "<<unsigned int(geometry->getsdo_gtype())<<endl;
//cout<<"SRID: "<<unsigned int(geometry->getsdo_srid())<<endl;
}