sde for Oracle 与 shp 、oralce spatial 的数据读写

为了项目需要,需要研究一下 sde for oracle(以下简称 sde)和 shp 的数据读写功能,以及从 oralce spatial 读取后,写入 sde。为了简化本次尝试,所有空间数据均为二维坐标点数据。线和面的内容,以后补上。

一、目录:

  • 将 shp 文件批量增量写入 sde 空间数据表
  • 将 sde 空间数据表数据批量另存为 shp 文件
  • 将 sde 空间数据表数据批量增量存入已有的 shp 文件
  • 将 oracle spatial 数据逐条写入 sde 空间数据表

二、环境搭建:

(一)软件环境

  • VMware Workstation 15 Pro
  • Microsoft Windows XP Professional x64 Edition 版本 2003 Service Pack 2
  • ArcGIS Desktop 10.1
  • ArcSDE for Oracle 11g
  • Oracle11g R2 win64 database
  • Oracle11g R2 win32 client
  • Python 2.7.2
  • cx_Oracle 7.0.0

(二)测试数据

ArcObject java 自带测试数据 C:\Program Files (x86)\ArcGIS\DeveloperKit10.1\java\samples\data\usa

  • GCS_North_American_1983
  • WKID: 4269 权限: EPSG
  • 点:wind.shp
  • 点:wind_Append.shp(该文件由原 usa 的 wind.shp 改名,且清空记录得到)

三、测试内容

(一)将 shp 文件批量增量写入 sde 空间数据表

首先先在sde中创建一个空的空间数据表:

导入wind_Append.shp数据(该文件由原usa的wind.shp改名得到):

import arcpy
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )

inputs = r'C:\TEMP\data\wind.shp'
target = r'数据库连接\连接到 localhost.sde\SDE.wind_Append'
schema_type = 'TEST'
arcpy.Append_management(inputs, target, schema_type)

运行结果:

 

(二)将 sde 空间数据表数据批量另存为 shp 文件

源码:

import arcpy

inputs = r'数据库连接\连接到 localhost.sde\SDE.wind_Append'
target = r'C:\TEMP\data\wind_copy.shp'
arcpy.CopyFeatures_management(inputs, target)

结果:

(三)将 sde 空间数据表数据批量增量存入已有的 shp 文件

shp 文件准备,编辑模式下,清空上一节中的shp文件数据:

源码:

import arcpy

inputs = r'数据库连接\连接到 localhost.sde\SDE.wind_Append'
target = r'C:\TEMP\data\wind_copy.shp'
schema_type = 'TEST'
arcpy.Append_management(inputs, target, schema_type)

结果:

(四)将 oracle spatial 数据逐条写入 sde 空间数据表

参考博客:https://blog.csdn.net/neweastsun/article/details/51852304

基础 oracle 操作函数:

import cx_Oracle
 
class Oracle(object):
    """  oracle db operator  """
    def __init__(self,userName,password,host,instance):
        self._conn = cx_Oracle.connect("%s/%s@%s/%s" % (userName,password,host,instance))
        self.cursor = self._conn.cursor()
        
    def queryTitle(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
 
        colNames = []
        for i in range(0,len(self.cursor.description)):
            colNames.append(self.cursor.description[i][0])
        
        return colNames
    
    # query methods
    def queryAll(self,sql):
        self.cursor.execute(sql)
        return self.cursor.fetchall()
    
    def queryOne(self,sql):
        self.cursor.execute(sql)
        return self.cursor.fetchone()
    
    def queryBy(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
            
        return self.cursor.fetchall()
    
    def insertBatch(self,sql,nameParams=[]):
        """batch insert much rows one time,use location parameter"""
        self.cursor.prepare(sql)
        self.cursor.executemany(None, nameParams)
        self.commit()
    
    def commit(self):
        self._conn.commit()
    
    def __del__(self):
        if hasattr(self,'cursor'): 
            self.cursor.close()
            
        if hasattr(self,'_conn'): 
            self._conn.close()

在基础函数下添加如下代码,测试oracle spatial 的点空格表生成,成功后,注释掉删表sql语句:

def test3():
    oraDb = Oracle('sde','sde','localhost','orcl')
    cursor = oraDb.cursor
    
    create_table = """
	CREATE TABLE test_sp_restaurants_new
	(
	id number,
	poi_name NVARCHAR2(65),
	location SDO_GEOMETRY -- New column to store locations
	)
    """
      
    cursor.execute(create_table)
      
    #sql = "INSERT INTO python_modules(module_name, file_path) VALUES (:1, :2)"
    sql = """
	INSERT INTO test_sp_restaurants_new
	VALUES
	  (:1,
	   :2,
	   SDO_GEOMETRY(2001, -- SDO_GTYPE attribute: "2" in 2001 specifies dimensionality is 2.
					NULL, -- other fields are set to NULL.
					SDO_POINT_TYPE -- Specifies the coordinates of the point
					(:3, -- first ordinate, i.e., value in longitude dimension
					 :4, -- second ordinate, i.e., value in latitude dimension
					 NULL -- third ordinate, if any
					 ),
					NULL,
					NULL))
	"""
    M = []
    M.append((1, 'PIZZA HUT', -87, -78))
    M.append((2, 'PIZZA HUT2', -88, -79))
    M.append((3, 'PIZZA HUT3', -89, -80))
    M.append((4, 'PIZZA HUT3', -85, -76))
    oraDb.insertBatch(sql,M)
      
    cursor.execute("SELECT COUNT(*) FROM test_sp_restaurants_new")
    print(cursor.fetchone())
    print('insert batch ok.')
    
    #cursor.execute("DROP TABLE test_sp_restaurants_new PURGE")
     
test3()

验证 oracle spatial 空间表中存插入记录成功:

准备空的 sde 空间表。

该步骤强制设置表的地理坐标系的 wkid 为 4269,即 GCS_North_American_1983,然而在 pl/sql 客户端进行 sql 验证的时候,一直报错,直到按提示,将参数由 4269 改为 30000 以后,才没有问题,具体原因,以后再分析。如图:

为 class Oracle(object): 增加一个通用函数,解决 oracle 的 clob 字段字符串化问题:

    def queryClobBy(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
        str_list=[]
        for i in self.cursor:
            text = i[0].read()
            str_list.append(text)

        return ''.join(str_list)

实现从oralce spatial空间表中读取空间点坐标,然后直接写入 sde 表中的 python 语句:

def test4():
    oraDb = Oracle('sde','sde','localhost','orcl')
    cursor = oraDb.cursor
	
    sql = "select sdo_geometry.get_wkt(location) shape from test_sp_restaurants_new t where id = 1"
    shpstr = oraDb.queryClobBy(sql)
    spls = shpstr[7:-1].split(' ')
      
    sql = """
	INSERT INTO WIND_append (objectid, id, velocity, direction, shape)
    VALUES (3,3, 23,96, sde.st_geometry (:1,  :2 , null, null, 300000))
	"""
    M = []
    M.append((float(spls[0]), float(spls[1])))
    oraDb.insertBatch(sql,M)
     
test4()

结果:

 

以上,本次任务基本完成。

 

以下附上本次 oracle spatial 与 sde 互操作使用的 python 完整脚本:

'''
Created on 2016年7月7日
@author: Tommy(基础源码作者)
Modify on 2018年12月26日
@author: 蚩尤紫馨(修改)
'''
import cx_Oracle
 
class Oracle(object):
    """  oracle db operator  """
    def __init__(self,userName,password,host,instance):
        self._conn = cx_Oracle.connect("%s/%s@%s/%s" % (userName,password,host,instance))
        self.cursor = self._conn.cursor()
        
    def queryTitle(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
 
        colNames = []
        for i in range(0,len(self.cursor.description)):
            colNames.append(self.cursor.description[i][0])
        
        return colNames
    
    # query methods
    def queryAll(self,sql):
        self.cursor.execute(sql)
        return self.cursor.fetchall()
    
    def queryOne(self,sql):
        self.cursor.execute(sql)
        return self.cursor.fetchone()
    
    def queryBy(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
            
        return self.cursor.fetchall()
	
    def queryClobBy(self,sql,nameParams={}):
        if len(nameParams) > 0 :
            self.cursor.execute(sql,nameParams)
        else:
            self.cursor.execute(sql)
        str_list=[]
        for i in self.cursor:
            text = i[0].read()
            str_list.append(text)

        return ''.join(str_list)
    
    def insertBatch(self,sql,nameParams=[]):
        """batch insert much rows one time,use location parameter"""
        self.cursor.prepare(sql)
        self.cursor.executemany(None, nameParams)
        self.commit()
    
    def commit(self):
        self._conn.commit()
    
    def __del__(self):
        if hasattr(self,'cursor'): 
            self.cursor.close()
            
        if hasattr(self,'_conn'): 
            self._conn.close() 
 
 
def test1():
    sql = """select LAYER_ID,table_name from LAYERS where layer_id = :id """
    oraDb = Oracle('sde','sde','localhost','orcl')
    
    fields = oraDb.queryTitle(sql, {'id':'1'})
    print(fields)
    
    print(oraDb.queryBy(sql, {'id':'1'}))
 
def test2():
    oraDb = Oracle('sde','sde','localhost','orcl')
    cursor = oraDb.cursor
    
    create_table = """
    CREATE TABLE python_modules (
    module_name VARCHAR2(50) NOT NULL,
    file_path VARCHAR2(300) NOT NULL
    )
    """
    from sys import modules
      
    cursor.execute(create_table)
    M = []
    for m_name, m_info in modules.items():
        try:
            M.append((m_name, m_info.__file__))
        except AttributeError:
            pass
      
    sql = "INSERT INTO python_modules(module_name, file_path) VALUES (:1, :2)"
    oraDb.insertBatch(sql,M)
      
    cursor.execute("SELECT COUNT(*) FROM python_modules")
    print(cursor.fetchone())
    print('insert batch ok.')
    
    cursor.execute("DROP TABLE python_modules PURGE")
 
def test3():
    oraDb = Oracle('sde','sde','localhost','orcl')
    cursor = oraDb.cursor
    
    create_table = """
	CREATE TABLE test_sp_restaurants_new
	(
	id number,
	poi_name NVARCHAR2(65),
	location SDO_GEOMETRY -- New column to store locations
	)
    """
      
    cursor.execute(create_table)
      
    sql = """
	INSERT INTO test_sp_restaurants_new
	VALUES
	  (:1,
	   :2,
	   SDO_GEOMETRY(2001, -- SDO_GTYPE attribute: "2" in 2001 specifies dimensionality is 2.
					NULL, -- other fields are set to NULL.
					SDO_POINT_TYPE -- Specifies the coordinates of the point
					(:3, -- first ordinate, i.e., value in longitude dimension
					 :4, -- second ordinate, i.e., value in latitude dimension
					 NULL -- third ordinate, if any
					 ),
					NULL,
					NULL))
	"""
    M = []
    M.append((1, 'PIZZA HUT', -87, -78))
    M.append((2, 'PIZZA HUT2', -88, -79))
    M.append((3, 'PIZZA HUT3', -89, -80))
    M.append((4, 'PIZZA HUT3', -85, -76))
    oraDb.insertBatch(sql,M)
      
    cursor.execute("SELECT COUNT(*) FROM test_sp_restaurants_new")
    print(cursor.fetchone())
    print('insert batch ok.')
    
	
def test4():
    oraDb = Oracle('sde','sde','localhost','orcl')
    cursor = oraDb.cursor
	
    sql = "select sdo_geometry.get_wkt(location) shape from test_sp_restaurants_new t where id = 1"
    shpstr = oraDb.queryClobBy(sql)
    print shpstr
    print shpstr[7:-1]
    spls = shpstr[7:-1].split(' ')
    print spls
    print float(spls[0])
    print float(spls[1])
      
    sql = """
	INSERT INTO WIND_append (objectid, id, velocity, direction, shape)
    VALUES (3,3, 23,96, sde.st_geometry (:1,  :2 , null, null, 300000))
	"""
    M = []
    M.append((float(spls[0]), float(spls[1])))
    oraDb.insertBatch(sql,M)
     
# test1()
# test2()
# test3()
test4()

 

转载自:https://blog.csdn.net/firefly2123/article/details/85243964

You may also like...