众所周知,数据是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; }