存储过程——循环复制分表

本文旨在介绍如何使用MySQL存储过程将ejex_questions_jn表的数据复制到ejex_questions_item1和ejex_questions1两个表中。过程中涉及字段拼接、拆分、排序及处理中文字符长度计算、max_allowed_packet错误等问题。存储过程中要注意避免变量名与查询字段冲突,并解决报错问题。

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

  • 目的

把表(ejex_questions_jn)的数据分别添加到表(ejex_questions_item1)与表(ejex_questions1)中

数据格式

ejex_questions_jn(表A)

ejex_questions_item1(表B)

ejex_questions1(表C)

把表A数据中的first、second、third字段拼接成一个字段与topic、type、diff数据复制到表C中;表A数据中的options以##拆分开复制到表B中,并把ABCD提出来以及排序,表B表C相关联

  • 存储过程
drop procedure if exists insert_questions;
DELIMITER $$
CREATE PROCEDURE insert_questions()
BEGIN
	DECLARE qt_type VARCHAR(10);
	DECLARE qt_diff VARCHAR(20);
	DECLARE qt_topic TExt;
	DECLARE qt_options TExt;
    DECLARE qt_point1 TEXT; -- 知识点
    DECLARE qt_point2 TEXT;
    DECLARE qt_point3 TEXT;
    DECLARE qt_points TEXT;
	
	DECLARE item_title TExt;
	DECLARE qt_id int;
	declare item_abc varchar(20);-- A B C D
	declare item_seq int(10);-- 选项顺序

	-- 遍历数据结束标志
	DECLARE done INT DEFAULT FALSE;
	-- 游标
	DECLARE cur_que CURSOR FOR (select topic,type,diff,options,first,second,third from ejex_questions_jn);
	-- 将结束标志绑定到游标
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
	-- 打开游标
	OPEN  cur_que;      
		-- 遍历
		my_loop: LOOP
			FETCH cur_que INTO qt_topic,qt_type,qt_diff,qt_options,qt_point1,qt_point2,qt_point3;  -- 取值 取多个字段
            SET qt_points = concat(qt_point1,'、',qt_point2,'、',qt_point3); -- 知识点拼接成一个字符串
            
			IF done THEN
				LEAVE my_loop;
			END IF;

			-- 插入试题
			INSERT INTO ejex_questions1(title,questions_type,degree,point) values(qt_topic,qt_type,qt_diff,qt_points);
            SET qt_id = LAST_INSERT_ID(); -- 试题id
            
            # 选项
			set item_seq = 1;-- 选项顺序
			SET item_title = SUBSTRING_INDEX(qt_options,'##',1);
			WHILE trim(qt_options) is not null && char_length(trim(qt_options)) <> 0
				DO 
				# set item_abc = substring_index(item_title,'、',1);
                set item_abc = LEFT(item_title,1); -- 截取选项中第一个字符,(A,B,C,D)
				SET qt_options = RIGHT(qt_options,char_length(qt_options)-char_length(item_title)-2); -- 剩余值
				set item_title = RIGHT(item_title,char_length(item_title)-2);-- 去掉前面的 A、B、 等
				INSERT INTO ejex_questions_item1(question_id,title,abc,seq) VALUES (qt_id,item_title,item_abc,item_seq);
				SET item_title = SUBSTRING_INDEX(qt_options,'##',1);
				set item_seq = item_seq + 1;
			END WHILE;
            
		END LOOP my_loop;
	CLOSE cur_que;

END$$
DELIMITER 

call insert_questions(); -- 调用
  • 期间遇到问题
  1. 中文字符计算长度:char_length() 并非 length()
  2. 不能使定义的变量(declare)与select中查询的字段名相同,否则数据为空
  3. 报错:Result of replace() was larger than max_allowed_packet(1024)-truncated:解决办法

    直接用sql命令修改:set global max_allowed_packet = 25600;再show VARIABLES like '%max_allowed_packet%';重启mysqld服务

  4. 报错:Commands out of sync; you can't run this command now,未解决,

  5. 快速删除数据:delete from table_name;

  6. 自增字段重置:alter table table_name auto_increment= 1;

### 实现 MySQL 分库分表后的联合查询及数据检索 #### 利用 Sharding-JDBC 进行 SQL 改写 对于分页查询,在分库分表场景下,直接使用 `LIMIT` 子句会带来性能问题。例如,当执行如下 SQL 查询时: ```sql select * from user order by username limit 30, 10; ``` 此查询会在每个分片中独立执行并返回各自的结果集,之后再由应用程序汇总成最终结果[^3]。 为了提高效率,建议采用中间件如 Sharding-JDBC 来自动改写 SQL 语句。该工具能够识别特定模式的查询并将它们转换为适合分布式环境的形式,同时保持应用层逻辑不变。 #### 处理大规模数据量下的复杂查询 针对含有大量记录的大(比如超过一亿条),即使已经建立了良好的索引机制和优化过的查询方式,仍然可能遭遇 I/O 或者 CPU 的瓶颈。此时可以考虑将跨多个时间段的数据分布于不同物理甚至不同的数据库实例之中。具体策略包括但不限于按日期范围划分表格,并且在每次请求时动态决定访问哪些具体的子来获取所需信息[^2]。 一种常见的实践方案是在内存中创建临时存储区域用于累积来自各个片段化单元的部分成果;接着基于这些缓存好的局部解答构建全局视角下的完整答案集合。这通常涉及到先期准备阶段——即预先计算好所有涉及的目标分区列,随后逐一发起针对性读取动作直至收集齐备全部必要素材为止[^4]。 ```python import pandas as pd from sqlalchemy import create_engine def fetch_data_from_shards(start_date, end_date): engine = create_engine('mysql+pymysql://user:password@host/dbname') temp_table_name = "temp_results" query_template = """ INSERT INTO {tmp} SELECT * FROM daily_records_{date_part} WHERE record_date BETWEEN '{start}' AND '{end}' """ dates_range = pd.date_range(start=start_date, end=end_date) with engine.connect() as connection: try: # Create temporary table once at the beginning connection.execute(f"CREATE TEMPORARY TABLE IF NOT EXISTS {temp_table_name}(LIKE daily_records_YYYYMMDD)") for single_date in dates_range.strftime('%Y%m%d'): formatted_query = query_template.format( tmp=temp_table_name, date_part=single_date, start=start_date, end=end_date ) connection.execute(formatted_query) final_result = pd.read_sql(f'SELECT * FROM {temp_table_name}', con=connection) return final_result finally: # Clean up after finishing operations on shards connection.execute(f'DROP TEMPORARY TABLE IF EXISTS {temp_table_name}') ``` 上述 Python 脚本展示了如何利用 Pandas 和 SQLAlchemy 库连接至 MySQL 数据源并对指定期间内的日志条目实施批量加载过程。这里的关键在于通过循环迭代每一天的具体情况进而拼接出完整的 SQL 命令字符串序列,最后统一提交给服务器端处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值