眾所周知,資料是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; //SRIDsrid_null.setNull();sdo_point_type *point_type = new sdo_point_type(); //SDO_POINT_TYPEpoint_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;}