sql T_sql 利用NOW_NUMBER和CTE 去除表中重复记录行

本文通过创建一个名为tbtest的表格并插入多条记录来演示SQL数据处理。使用了row_number()函数进行行编号,并展示了如何筛选出每个分组中的第一条记录。

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

create table tbtest

(

tid int null,

tname varchar(20) null

)

 

insert into tbtest values(1, 'aaa')

insert into tbtest values(2, 'aaa')

insert into tbtest values(2, 'aaa')

insert into tbtest values(2, 'aaa')

insert into tbtest values(3, 'bbb')

insert into tbtest values(3, 'bbb')

insert into tbtest values(4, 'ccc')

insert into tbtest values(4, 'ddd')

insert into tbtest values(5, 'eee')

 

select * from tbtest

 

go

 

with temp as

(

    select tid,tname,row_number() OVER (PARTITION BY tid, tname ORDER BY tid) as rownumber from tbtest

)

select * from temp where rownumber=1

 

CREATE DEFINER=`zd_shiwenchao`@`10.212.1.15` PROCEDURE `JGJS_RADS_EAST_CHECK`() BEGIN -- 1、声明变量 DECLARE DONE INT DEFAULT FALSE; DECLARE V_SERIAL VARCHAR(50); -- 标记游标循环是否完成 DECLARE V_TABLE VARCHAR(255); -- 存储从CHECKRULES中获取的名 DECLARE V_SQL TEXT; -- 存储从CHECKRULES中获取的SQL语句 DECLARE V_DATAITEMNAME VARCHAR(255); -- 存储列名(COLUMNNAME) DECLARE V_COMMIT INT DEFAULT 1; -- 定义事务用,1为正常,-10为失败 DECLARE V_MSG TEXT; -- 记录错误信息 DECLARE V_CNT INT; -- 用于记录成功时的数据量 DECLARE V_ENDDATE DATETIME DEFAULT NOW(); -- 记录当前时间 DECLARE CUR CURSOR FOR SELECT SERIALNUMBER, TABLENAME, DATAITEMNAME, SQLSTATEMENT FROM JGJS_RADS_CHECKSQL WHERE ISACTIVE = 1; -- 2、异常处理 DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = TRUE; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 V_MSG = MESSAGE_TEXT; SET V_COMMIT = -10; ROLLBACK; -- 发生异常时回滚事务 END; -- 3、开始事务 START TRANSACTION; -- 4、打开游标 OPEN CUR; READ_LOOP: LOOP FETCH CUR INTO V_SERIAL, V_TABLE, V_DATAITEMNAME, V_SQL; IF DONE THEN LEAVE READ_LOOP; END IF; -- 5、动态执SQL并统计错误数 SET @DYNAMIC_SQL = CONCAT( 'INSERT INTO JGJS_RADS_CHECKRESULT (SERIALNUMBER, TABLENAME, COLUMNNAME, ERROR_COUNT) ', 'SELECT ''', V_SERIAL, ''', ''', V_TABLE, ''', ''', V_DATAITEMNAME, ''', COUNT(*) ', 'FROM (', V_SQL, ') AS VALIDATION_RESULTS' ); PREPARE STMT FROM @DYNAMIC_SQL; EXECUTE STMT; DEALLOCATE PREPARE STMT; END LOOP; CLOSE CUR; -- 6、根据事务状态提交或回滚 IF V_COMMIT = -10 THEN ROLLBACK; -- 事务异常回滚 -- 7、记录报错信息到日志 INSERT INTO JGJS_RADS_CHECKRESULT (SERIALNUMBER, TABLENAME, COLUMNNAME, ERROR_COUNT, DEALSTATUS, REMARK, CHECKTIME) VALUES ('SYSTEM', 'SYSTEM', 'SYSTEM', 0, 'ERROR', V_MSG, NOW()); ELSE -- 事务正
最新发布
03-11
<think>嗯,用户问的是如何调试优化MySQL存储过程JGJS_RADS_EAST_CHECK,特别是游标操作动态SQL部分。首先,我需要回忆一下存储过程调试优化的基本方法。调试的话,MySQL不像其他数据库有内置的调试工具,可能需要用SELECT或者日志来输出变量值,逐步排查问题。优化方面,游标通常性能较差,特别是当处理大量数据时,可以考虑用集合操作代替游标循环。另外,动态SQL如果拼接不当,可能会有注入风险或者效率问题,需要检查是否使用了预处理语句,或者是否有不必要的重复解析。 然后,我需要结合用户提供的引用内容。引用1提到有很多嵌套判断临时,导致查询速度慢,子查询多。这可能意味着存储过程中存在类似的复杂结构,导致性能问题。所以优化时要注意减少临时的使用,简化查询结构。引用3是关于Java导出Excel的,可能当前问题无关,但引用5提到分数傅里叶变换用于加密,可能也不相关。引用24可能也不直接相关,但需要确保回答不涉及这些内容。 接下来,思考具体步骤。调试部分应该包括如何设置断点,输出变量状态,检查游标是否正常打开获取数据。动态SQL部分需要检查拼接是否正确,是否有语法错误,或者执计划是否合理。优化部分可能需要将游标改为批量处理,使用JOIN或者临时来替代逐处理,同时分析执计划,添加合适的索引。 另外,用户提到的存储过程名称JGJS_RADS_EAST_CHECK可能涉及特定的业务逻辑,比如数据校验或报告生成,可能需要考虑业务场景下的优化,比如是否所有数据处理都是必要的,或者是否可以分批处理。 还需要考虑存储过程中的事务管理,是否有不必要的长时间锁定,或者是否可以减少事务的范围来提高性能。动态SQL的执是否可以使用绑定变量来减少解析开销,或者是否有重复执的动态SQL可以缓存。 最后,生成相关问题时要围绕存储过程调试、游标优化、动态SQL效率、索引优化等方面展开,确保问题有针对性,帮助用户深入理解可能的优化方向。</think>### 调试优化MySQL存储过程JGJS_RADS_EAST_CHECK的步骤 #### 一、调试方法 1. **逐段隔离执** 将存储过程拆分为多个独立代码块,通过`SELECT`语句输出中间变量值或游标状态。例如: ```sql SELECT CONCAT('游标状态:', @cursor_status); -- 输出游标状态 ``` 若涉及动态SQL,可先单独执拼接后的SQL语句,验证其正确性[^1]。 2. **错误日志追踪** 使用`DECLARE CONTINUE HANDLER`捕获异常并记录到日志: ```sql CREATE TABLE error_log (msg TEXT, time TIMESTAMP); DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN INSERT INTO error_log VALUES (CONCAT('错误代码:', SQLSTATE), NOW()); END; ``` 3. **动态SQL调试** 将动态SQL字符串暂存到变量后打印: ```sql SET @dynamic_sql = CONCAT('SELECT * FROM ', table_name); SELECT @dynamic_sql; -- 输出检查拼接结果 PREPARE stmt FROM @dynamic_sql; ``` #### 二、游标优化策略 1. **避免嵌套游标** 多层游标会导致时间复杂度呈指数增长。若必须使用,尝试: - 限制数据集规模(如添加`WHERE`条件) - 使用临时存储中间结果,例如: ```sql CREATE TEMPORARY TABLE temp_data AS SELECT ...; -- 减少实时计算 ``` 2. **批量处理替代逐操作** 将游标的逐处理改为集合操作。例如原游标逻辑: ```sql OPEN cur; read_loop: LOOP FETCH cur INTO var; UPDATE table SET col = var WHERE ...; END LOOP; ``` 可优化为: ```sql UPDATE table JOIN source_table ON ... SET table.col = source_table.value; -- 单语句完成批量更新 ``` 3. **索引优化** 确保游标查询涉及的字段已建立索引: ```sql EXPLAIN SELECT ...; -- 分析游标基础查询的执计划 ``` #### 三、动态SQL优化建议 1. **预编译语句** 使用`PREPARE`/`EXECUTE`减少解析开销: ```sql SET @sql = 'SELECT * FROM table WHERE id = ?'; PREPARE stmt FROM @sql; SET @param = 100; EXECUTE stmt USING @param; -- 参数化避免重复解析 ``` 2. **减少临时嵌套** 动态SQL中过多的临时会导致内存压力。参考引用[1]中提到的嵌套问题,可通过`WITH`子句(CTE)简化复杂查询: ```sql WITH temp1 AS (SELECT ...), temp2 AS (SELECT ... FROM temp1) SELECT * FROM temp2; -- 替代多级临时 ``` 3. **字符串拼接优化** 使用`CONCAT_WS`代替多次`CONCAT`,避免NULL值问题: ```sql SET @where_clause = CONCAT_WS(' AND ', IF(param1 IS NOT NULL, 'col1 = param1', NULL), IF(param2 IS NOT NULL, 'col2 = param2', NULL) ); ``` #### 四、性能验证工具 1. **执时间分析** ```sql SET profiling = 1; CALL JGJS_RADS_EAST_CHECK(); SHOW PROFILES; -- 显示各步骤耗时 ``` 2. **锁监控** 通过`SHOW ENGINE INNODB STATUS`检查是否存在锁竞争。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值