抽取CLOB字段中XML的特定元素的VALUE值

在ORACLE数据库中,有时XML文件会被保存在CLOB字段中。

这时候,若是我们要获取此字段XML中特定元素的VALUE值,就需要用到xmltype 这个函数。

如下面的 XML文件,保存在 TABLE_A 的CLOB_K 字段,若是我们要获取其中的

YEAR 的VALUE 值,可以用下面的方式获取。

---获取clob_k 字段中XML 的year 值。
select xmltype(clob_k).extract('//note/date/year/text()').getstringval()
from table_a ;

 如此,便可以得到XML中特定元素的值。

完。

这段代码是做什么的import sys from dataclasses import field from difflib import SequenceMatcher import pandas as pd import cx_Oracle import json import pymysql import os def find_similar_pairs(list_long, list_short, threshold=0.85): list_short = [i.upper() for i in list_short] list_long = [i.upper() for i in list_long] field_output = [] for str1 in list_long: for str2 in list_short: ratio = SequenceMatcher(None, str1, str2).ratio() if ratio >= threshold: field_output.append(str1) break return field_output def change_word(row): values=[] for value in row: if pd.isna(value): values.append('NULL') elif isinstance(value, str): # 处理字符串中的单引号 value = value.replace('"',"'") #values.append(f"'{value}'") values.append(value) else: values.append(str(value)) result_str = "(" + ", ".join(f"'{item}'" if item != 'NULL' else item for item in values) + ")" return result_str def get_clob_columns(cursor, table_name): """ 获目标表中的 CLOB 字段 :param connection: 数据库连接对象 :param table_name: 目标表名 :return: CLOB 字段列表 """ query = f"SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE OWNER = USER AND TABLE_NAME = UPPER('{table_name}') AND DATA_TYPE = 'CLOB'" cursor.execute(query) clob_columns = [row[0] for row in cursor.fetchall()] cursor.close() return clob_columns def data_insert(path_csv, table_name, conn, cursor, fields_csv, order_fields): """ path_csv 文件地址 table_name 表名 conn, cursor 用于 orcale 连接 fields_csv 对应csv中的字段,df重排序 order_fields 对应数据库字段名,insert中用 """ # 获clob字段 clob_columns = get_clob_columns(cursor, table_name) output = [] output.append(order_fields) num = 0 df = pd.read_csv(path_csv, encoding='utf8') df = df[fields_csv].iloc[:] # 不存在clob字段,正常插 if not clob_columns: field = "(" + ", ".join(order_fields) + ")" for line in df.values.tolist(): try: ins=f"INSERT INTO {table_name} {field} values {change_word(line)};" #print(ins) cursor.execute(ins) conn.commit() #print(ins) num+=1 #except cx_Oracle.DatabaseError as e: except: #output.append(pd.DataFrame([line[:-1]], columns=df.columns)) output.append(line[:]) #print(f"插入失败: {e}") print(f"{table_name}一共插入{num}条数据") # 返回插入失败数据 return output # 出现clob字段 else: clob_indices = [order_fields.index(col) for col in clob_columns] columns_str = ', '.join(order_fields) placeholders = ', '.join([f':{i + 1}' for i in range(len(order_fields))]) insert_query = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})" for row in df.values.tolist(): row = change_word(row) new_row = [] for i, value in enumerate(row): if i in clob_indices: clob = conn.createlob(cx_Oracle.CLOB) clob.write(value) new_row.append(clob) else: new_row.append(value) try: cursor.execute(insert_query, new_row) conn.commit() num+=1 except Exception as e: print(f"插入行 {row} 失败: {e}") output.append(row) conn.rollback() print(f"{table_name}一共插入{num}条数据") if __name__=='__main__': # with open('conf.json', 'r', encoding='utf-8') as file: # # 加载 JSON 数据 # conf = json.load(file) # # user=conf['user'] # password=conf['password'] # host=conf['host'] # port=conf['port'] # database=conf['database'] # datas=conf['datas'] # 放表名和字段名{} # path_file = r'./files/import' # # cx_Oracle.init_oracle_client(lib_dir=r"D:\instantclient-basic-windows.x64-19.26.0.0.0dbru\instantclient_19_26") # conn = cx_Oracle.connect(user, password, cx_Oracle.makedsn(host, port, None, database)) # cursor = conn.cursor() # 建立数据库连接 conn = pymysql.connect( host='localhost', port=3306, user='root', passwd='wan177242', database='test3' ) cursor = conn.cursor() datas = {"tem_test":["id","manager","name1"]} path_file = r'./files/import' table_list=list(datas.keys()) for table_name in table_list: fields_csv = datas[table_name] #csv中的字段 #cursor.execute(f"SELECT * FROM {table_name} WHERE ROWNUM = 1") cursor.execute(f"SELECT * FROM {table_name}") fields_orc = [desc[0] for desc in cursor.description] #orc中的字段 # print(fields_csv) # print(fields_orc) order_fields = find_similar_pairs(fields_orc,fields_csv) print(order_fields) # 判断两个列表长度是否一致,不一致证明有的字段没对应上 if len(fields_csv)!=len(order_fields): print('字段对应有误') sys.exit() file_csv = table_name+'.csv' path_csv = os.path.join(path_file, file_csv) output = data_insert(path_csv,table_name ,conn, cursor, fields_csv, order_fields) if len(output)>1: df = pd.DataFrame(output) df.to_csv(f"./files/except/{file_csv}", index=False, header=False)
06-06
### 从 Oracle XML 字段中提特定节点的方法 在 Oracle 数据库中,若字段以 `XMLType` 或 `CLOB` 类型存储 XML 数据,可以通过内置的 XML 函数提中的节点。常用的函数包括 `EXTRACT()` 和 `XMLTABLE()`,其中 `XMLTABLE` 更适合结构化提,尤其在处理命名空间时更为灵活。 #### 使用 `EXTRACT()` 方法提节点XML 数据结构简单且不包含命名空间,可以直接使用 `EXTRACT()` 函数提节点内容。例如,从 `CLOB` 类型的字段 `clob_k` 中提 `<year>` 节点: ```sql SELECT xmltype(clob_k).extract('//note/date/year/text()').getstringval() FROM table_a; ``` 该方法适用于快速提单个节点内容,但不支持命名空间处理,也不适合提多个字段[^2]。 #### 使用 `XMLTABLE()` 方法提节点XML 数据中包含命名空间或需要提多个字段时,推荐使用 `XMLTABLE()` 函数。例如,若 XML 中包含命名空间并需提多个节点,可按如下方式处理: ```sql SELECT x.* FROM your_table yt, XMLTABLE( XMLNAMESPACES('http://example.com/ns' AS "e"), '//e:Document/e:DocumentHeader' PASSING yt.xml_data COLUMNS service_id VARCHAR2(200) PATH 'e:DocumentServiceID', factext VARCHAR2(100) PATH 'e:FacText', fac VARCHAR2(100) PATH 'e:Fac', street_name VARCHAR2(100) PATH 'e:StreetName', zipcode VARCHAR2(10) PATH 'e:PostalCode' ) x; ``` 此方法支持命名空间定义,可通过 `XMLNAMESPACES` 指定默认命名空间或多个命名空间,并通过 `COLUMNS` 子句将 XML 节点映射为 SQL 查询的字段,适用于结构化提和复杂查询场景[^1]。 #### 处理无命名空间的 XML 数据 如果 XML 数据中不包含命名空间,则可以省略 `XMLNAMESPACES`,直接使用 XPath 表达式进行提: ```sql SELECT x.* FROM your_table yt, XMLTABLE( '//Document/DocumentHeader' PASSING yt.xml_data COLUMNS service_id VARCHAR2(200) PATH 'DocumentServiceID', factext VARCHAR2(100) PATH 'FacText', fac VARCHAR2(100) PATH 'Fac', street_name VARCHAR2(100) PATH 'StreetName', zipcode VARCHAR2(10) PATH 'PostalCode' ) x; ``` 该方法适用于未使用命名空间的 XML 数据,语法更为简洁。 #### 处理 CLOB 类型的 XML 数据 若 XML 数据存储为 `CLOB` 类型,需先通过 `XMLType()` 函数将其转换为 `XMLType`,再进行解析: ```sql SELECT x.* FROM your_table yt, XMLTABLE( '//Document/DocumentHeader' PASSING XMLType(yt.clob_data) COLUMNS service_id VARCHAR2(200) PATH 'DocumentServiceID', factext VARCHAR2(100) PATH 'FacText', fac VARCHAR2(100) PATH 'Fac', street_name VARCHAR2(100) PATH 'StreetName', zipcode VARCHAR2(10) PATH 'PostalCode' ) x; ``` 此方法可确保从 `CLOB` 字段中提结构化数据,并转换为关系表形式输出。 ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值