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