sql 多个id拼接成对一条数据某字段关联查询

本文档展示了如何通过SQL查询从申请表(appetable)中筛选出与报告表(reporttable)匹配的五官科体检记录,包括APPID、姓名和具体检查部位,如眼睛、口腔和耳朵。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

申请表apptable:

APPID APPNAME

1 眼睛

2 口腔

3 耳朵

报告表reporttable:

repid APPID reportNAME name

1 1,2,3 五官科体检 张三

结果:查出三条记录

1 眼睛 1 五官科体检 张三

2 口腔 1 五官科体检 张三

3 耳朵 1 五官科体检 张三

select app.*, r.* from apptable APP LEFT JOIN reporttable r ON R.APPID like '%' || app.appid || '%'

<think>好的,我现在需要帮用户解决一个Oracle存储过程的问题,用户想把一个表中的多个字段拼接成JSON串,然后插入到另一个表的一个字段中。之前用户已经询问过如何将多个字段组成JSON存入同一张表,现在需求变成了跨表插入,所以需要调整之前的解决方案。 首先,我需要确认用户的具体需求。用户有两个表,源表和目标表,需要从源表读取多个字段,生成JSON,然后插入到目标表的某个字段中。可能的场景是数据迁移或者ETL处理。用户可能希望这个存储过程能够灵活处理不同的表结构,或者只是针对特定的表。 接下来,我需要考虑Oracle的版本。用户之前的例子中提到了JSON_OBJECT函数,这需要Oracle 12c R2及以上版本。如果用户使用的是旧版本,可能需要手动拼接JSON字符串,但这样容易出错且不安全。所以需要确认用户的环境,但用户没有说明,所以我应该提供两种方案,或者至少提到版本要求。 然后,我需要设计存储过程的结构。基础版可能针对固定的表和字段,而增强版可能允许动态指定源表、目标表、字段映射等。但用户的需求是跨表插入,所以可能需要参数来指定源表、目标表、关联字段等。例如,用户可能需要传入源表名、目标表名、关联条件,以及JSON字段的映射方式。 还要考虑数据类型转换,特别是日期、时间戳等,需要格式化成字符串。此外,特殊字符的处理,比如双引号、反斜杠,Oracle的JSON_OBJECT会自动转义,但如果是手动拼接,就需要用REPLACE函数处理。 然后,我需要考虑性能问题。如果处理大量数据,逐条处理可能会很慢,应该建议批量操作,比如使用FORALL或者BULK COLLECT。此外,事务管理,确保在插入过程中出现错误时回滚,所以存储过程中需要异常处理,包括ROLLBACK和RAISE。 另外,用户可能需要将多个记录的JSON插入到目标表中,或者每次处理一条记录。根据示例代码,之前的存储过程是针对单条记录的,所以需要确认用户是否需要处理单条还是批量。如果用户需要批量处理,存储过程可能需要游标来遍历源表的数据。 安全方面,动态SQL的使用可能会有SQL注入的风险,特别是当表名或字段名来自用户输入时。需要提醒用户验证输入参数,或者使用绑定变量,但Oracle中表名不能绑定,所以只能拼接,需要注意过滤参数中的非法字符。 最后,需要编写示例代码,分基础版和增强版。基础版固定表结构和字段,增强版允许动态指定表和字段。同时,提供调用示例和注意事项,比如版本要求、性能优化、异常处理等。 现在,我需要检查是否覆盖了所有可能的问题点,比如跨表插入、数据类型处理、动态字段、批量操作等。确保存储过程结构正确,使用正确的SQL语句,如INSERT INTO ... SELECT ... FROM ... 或者动态执行。同时,在增强版中使用游标获取字段列表,构建JSON_OBJECT动态生成。 可能还需要处理目标表的主键或唯一约束,确保插入或更新时不会冲突。用户可能需要MERGE语句,但根据问题描述,可能只是简单的插入,所以暂时按插入处理。 总结,我需要分步骤说明存储过程的实现,包括参数定义、JSON生成、插入目标表、异常处理,并提供两种版本的代码,以及使用注意事项。</think>以下是一个将源表多字段拼接为JSON并插入目标表的Oracle存储过程实现方案,包含基础版和增强版两种实现方式: --- ### **一、基础版(固定表结构)** 适用于明确知道表结构的场景 ```sql CREATE OR REPLACE PROCEDURE insert_json_between_tables ( p_source_id IN source_table.source_id%TYPE ) IS v_json CLOB; BEGIN -- 生成JSON数据 SELECT JSON_OBJECT( 'id' VALUE s.source_id, 'name' VALUE s.customer_name, 'amount' VALUE s.transaction_amount, 'date' VALUE TO_CHAR(s.trans_date, 'YYYY-MM-DD HH24:MI:SS'), 'status' VALUE s.order_status ) INTO v_json FROM source_table s WHERE s.source_id = p_source_id; -- 插入目标表 INSERT INTO target_table( target_id, json_data, create_time ) VALUES ( p_source_id, v_json, SYSTIMESTAMP ); COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE_APPLICATION_ERROR(-20001, '插入失败: ' || SQLERRM); END; / ``` **调用方式**: ```sql EXEC insert_json_between_tables(1001); ``` --- ### **二、增强版(动态表结构)** 支持动态配置表名和字段的通用方案 ```sql CREATE OR REPLACE PROCEDURE dynamic_json_insert ( p_source_table IN VARCHAR2, p_target_table IN VARCHAR2, p_key_column IN VARCHAR2, p_key_value IN VARCHAR2, p_json_column IN VARCHAR2 ) IS v_sql VARCHAR2(4000); v_json CLOB; v_column VARCHAR2(100); TYPE cur_t IS REF CURSOR; c_columns cur_t; BEGIN -- 获取源表字段列表(排除LOB类型) OPEN c_columns FOR SELECT column_name FROM user_tab_columns WHERE table_name = p_source_table AND data_type NOT IN ('BLOB','CLOB','NCLOB'); -- 构建动态JSON_OBJECT v_sql := 'SELECT JSON_OBJECT('; LOOP FETCH c_columns INTO v_column; EXIT WHEN c_columns%NOTFOUND; v_sql := v_sql || '''' || LOWER(v_column) || ''' VALUE ' || v_column || ','; END LOOP; CLOSE c_columns; v_sql := RTRIM(v_sql, ',') || ') FROM ' || p_source_table || ' WHERE ' || p_key_column || ' = :1'; -- 执行动态SQL获取JSON EXECUTE IMMEDIATE v_sql INTO v_json USING p_key_value; -- 插入目标表 v_sql := 'INSERT INTO ' || p_target_table || '(' || p_key_column || ', ' || p_json_column || ', create_time)' || ' VALUES (:1, :2, SYSTIMESTAMP)'; EXECUTE IMMEDIATE v_sql USING p_key_value, v_json; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE_APPLICATION_ERROR(-20002, '动态插入失败: ' || SQLERRM); END; / ``` **调用方式**: ```sql EXEC dynamic_json_insert( 'SOURCE_TABLE', 'TARGET_TABLE', 'SOURCE_ID', '1001', 'JSON_DATA' ); ``` --- ### **三、批量处理版(高性能方案)** 适用于大规模数据迁移 ```sql CREATE OR REPLACE PROCEDURE batch_json_insert IS TYPE t_data IS TABLE OF CLOB; v_json_array t_data; BEGIN -- 批量生成JSON SELECT JSON_OBJECT( 'id' VALUE source_id, 'name' VALUE customer_name, 'details' VALUE transaction_details ) BULK COLLECT INTO v_json_array FROM source_table WHERE trans_date > SYSDATE - 30; -- 批量插入目标表 FORALL i IN 1..v_json_array.COUNT INSERT INTO target_table(json_data, create_time) VALUES (v_json_array(i), SYSTIMESTAMP); COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END; / ``` --- ### **四、关键注意事项** 1. **版本要求** - 最低要求:Oracle 12c Release 2(12.2)支持`JSON_OBJECT` - 推荐版本:Oracle 19c+ 支持完整JSON功能 2. **数据类型处理建议** ```sql -- 日期格式化 TO_CHAR(date_column, 'YYYY-MM-DD"T"HH24:MI:SS') -- 处理特殊字符 JSON_QUERY(REPLACE(text_column, '"', '\"')) ``` 3. **性能优化技巧** - 为源表查询条件字段建立索引 - 使用`PARALLEL`提示加速大数据量处理 ```sql SELECT /*+ PARALLEL(4) */ JSON_OBJECT(...) ``` 4. **安全建议** - 对动态SQL的输入参数进行白名单验证 - 限制`DBMS_SQL`权限 - 使用`UTL_I18N.ESCAPE_REFERENCE`处理XSS --- ### **五、新旧版本兼容方案** 适用于Oracle 11g等旧版本 ```sql CREATE OR REPLACE PROCEDURE legacy_json_insert IS BEGIN INSERT INTO target_table(json_data) SELECT '{' || '"transactionId":"' || txn_id || '",' || '"amount":' || amount || ',' || '"description":"' || REPLACE(REPLACE(description, '\', '\\'), '"', '\"') || '",' || '"time":"' || TO_CHAR(create_time, 'YYYY-MM-DD HH24:MI:SS') || '"' || '}' FROM source_table WHERE status = 'COMPLETED'; COMMIT; END; / ``` --- ### **六、典型应用场景** 1. 数据归档:将历史表数据转为JSON存入归档库 2. 日志记录:将交易流水转为JSON格式日志 3. API数据准备:为前端接口准备复合数据 4. 数据同步:异构数据库之间的格式转换 建议根据实际业务需求选择合适的实现方案,对于生产环境推荐使用动态SQL版本配合审计日志记录操作轨迹。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值