同时修改某一个数据库中所有表的所有字段的编码格式(mysql)

最近在进行源码的二次开发,突然之间有了一个小的需求,就这么悄悄的突然出现了。

需求原因就不说了,只说这个怎么实现的。我是用的是mysql数据库,其他的略有不同,具体到哪一点就只能具体变化了。

看网上有的说直接把数据库或者表的编码做改变就行了,可是这样对字段来说都没有影响。想改字段的话,直接对字段进行alter修改。可是把每一个字段写一遍挺烦人的,于是乎找到了一个语句:

alter table 表名 convert to character set utf8;
可以同时修改这个表的所有字段为u8,但是想改所有的表难道我要把所有的表名输入一遍吗?我那么懒的人怎么可能这么做。就算是花点时间也要找一个一劳永逸的方法。又于是乎,找到了一个查询所有表名的语句:

select table_name from information_schema.`TABLES` where TABLE_SCHEMA = '数据库名';

mysql的表信息都保存在了 information_schema 数据库的 TABLES 表里面,其中的字段 TABLE_SCHEMA 保存了数据库名,打开看看就是这样的:


针对这样的两句 sql 进行操作就行了。问题也来了,我得设计一个思路啊。

最先想到的是 把alter语句中表名作为参数的,而查询出来的表名作为变量传进去,再执行alter语句不就行了吗?

又于是乎,想到循环这种东西。用到循环的话,那写个存储过程吧,在其中声明变量,弄个循环,查询的表名赋值给变量,再往alter语句中一传,美美的。

结果,你妹的,各种报错!!!!

至于为什么,很简单:我不是太擅长数据库的操作……,其中的规则也只能一边做一边查询怎么做。别说,各种百度之后我居然搞了两种方式实现最初的需求:

A方案: 循环 + 变量赋值 + 动态sql语句拼接执行     和     B方案 :游标 + 循环 + 变量赋值 + 动态sql语句拼接

没错,其中的区别就是有没有用游标。可是涉及到的问题就不一样了。

循环,得有结束条件吧。看看网上的资料,各种条件都是以数字的大小为条件。当然我的A方案也是这样的,但是循环体不同。我这查询的数据中可不涉及数字啊,而且一下子查出来多行,就声明一个变量(声明多个也没用,都是一列对应一个变量)

要么说知道的多一点总是没错的:我每循环一次,不查出来多行,就查出一行,赋给变量去拼接sql执行不就行了。

每次查指定行数,循环时还继续往下查询,这不还是专门为一个关键字设计的嘛:limit 。就是它,一般用于分页查询所以上面的查询表名的语句就多了点东西:

select table_name from information_schema.`TABLES` where TABLE_SCHEMA = '数据库名'limit 起始位置, 每次查询的数量;
至此我就可以让声明的变量被依次赋予所有表的名称了,到这先把这部分整合下,存储过程的内容如下:

begin

	DECLARE cnt VARCHAR(100); -- 声明变量用来记录查询出的表名
	DECLARE i int;  -- 循环条件,同时可以用来标记表第几张表
	set i = 0;

-- 循环开始
	while i < 32 do -- 这里是32是因为我的数据库中表的数量是32,想不写死可以通过再定义一个变量,动态赋值
		select table_name into @cnt from information_schema.`TABLES` where TABLE_SCHEMA = 'xxx' limit i,1;
		select @cnt; -- mysql的打印语句
		-- 这里添加 alter 语句
		set i = i + 1;
	end while;  
-- 循环结束,注意分号

end
稍微说明下,其中的变量 i 循环条件的同时,也可以充当 limit 的起始位置;into 关键字是把查询结果赋值给 cnt 变量;32用变量代替就是:声明一个变量,比如: num,循环开始前:
select count(table_name) into @num from information_schema.`TABLES` where TABLE_SCHEMA = '数据库名'
这个语句的查询结果赋值给num,循环条件变成: while i < num do ……即可。

到这可以看到打印出来的该数据库中的所有表名。那这样,把之前 alter 语句中的表名替换为 @cnt 不就完成了吗?就这样,我有进坑了。

原因是:标准的 alter 语句中是没有@这个东西的,而把@去掉的话,它又会认为我想修改的表名就是 cnt ,而不是变量 cnt 。

所以需要动态拼接sql来执行,完整版

A方案:

begin

	DECLARE cnt VARCHAR(100); -- 声明变量用来记录查询出的表名
	DECLARE i int;  -- 循环条件,同时可以用来标记表第几张表
	set i = 0;

-- 循环开始
	while i < 32 do -- 这里是32是因为我的数据库中表的数量是32,想不写死可以通过再定义一个变量,动态赋值
		select table_name into @cnt from information_schema.`TABLES` where TABLE_SCHEMA = '数据库名' limit i,1;
		-- select @cnt; -- mysql的打印语句
		-- alter table @cnt convert to character set utf8; -- 这一句报错,必须动态拼接才行
		
		set @sql = concat("alter table ", @cnt, " convert to character set utf8");  -- 拼接,注意语句中的空格
		prepare stmt from @sql;  -- 预处理
			execute stmt;  -- 执行
		deallocate prepare stmt;  -- 释放

		set i = i + 1;
	end while;  
-- 循环结束,注意分号

end
反正就是这个意思,而带有游标的

B方案:

BEGIN


  DECLARE a VARCHAR(100);	-- 定义接收游标数据的变量 
  DECLARE SQL_FOR_SELECT varchar(500); -- 定义接收游标数据的变量 
 
  DECLARE done INT DEFAULT FALSE; -- 遍历数据结束标志
  DECLARE cur CURSOR FOR (select table_name from information_schema.`TABLES` where TABLE_SCHEMA = 'demo_survey');  -- 游标
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;  -- 将结束标志绑定到游标
 
 -- 打开游标
  OPEN cur; 
		-- 开始循环(loop循环)
		read_loop: LOOP
			-- 提取游标里的数据,这里只有一个,多个的话也一样;
			FETCH cur INTO a;
			
			-- 声明结束的时候
			IF done THEN
				LEAVE read_loop;
			END IF;

			-- 要循环的事件,使用了动态sql拼接alter语句,直接写的话报错		
			set SQL_FOR_SELECT = concat("alter table ", a, " convert to character set utf8"); -- 拼接
			set @sql = SQL_FOR_SELECT;  
			prepare stmt from @sql; 	-- 预处理
				execute stmt;  		-- 执行
			deallocate prepare stmt;	-- 释放prepare

		END LOOP;

  -- 关闭游标
  CLOSE cur;


END
B方案中用了 loop 循环,这样我可以学习下不同循环的使用方法嘛。对比两种方案可以看出来循环条件的不同,而且由于游标的特性,B方案中的查询结果不需要limit限制

两种方案的思路是一样的,手段不同而已。

当然了,我这个最初的需求很少遇到。

不过里面用到的东西很多我之前是没怎么用过的,所以记录下。


总结:

1.一次性修改表中所有字段的字符集语句:alter table `表名` convert to character set utf8;

2.查询某个数据库中所有表的信息语句:select * from information_schema.`TABLES` where TABLE_SCHEMA = '该数据库名';

3.查询结果赋值给变量可以用 into 关键字(也有其他的)。游标中没有@

4.变量赋值可以不用先声明,如A方案中的@sql ,直接使用 set @sql = xxx。

5.存储过程中可以直接使用 alter语句 ,也就是静态sql语句。但是需要传递参数的话,要使用动态sql拼接来执行(小慢,就循环了30多次,就能感觉出来比静态的慢,可能是因为我循环的是ddl语句吧)。

6.循环,游标,动态sql用完之后,都有个结束的语句和分号




LG

  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 如果你想在 MySQL 批量修改字段编码格式,你可以使用以下步骤: 1. 使用 `SHOW FULL COLUMNS FROM table_name` 命令查看字段编码格式。 2. 使用 `ALTER TABLE table_name MODIFY column_name VARCHAR(length) CHARACTER SET charset_name COLLATE collation_name;` 命令修改某个字段编码格式。 3. 重复步骤 2,修改所有需要修改字段编码格式。 例如,如果你想将 `customers` 的 `name` 字段编码格式修改为 `utf8mb4`,你可以使用以下命令: ``` ALTER TABLE customers MODIFY name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` 希望这能帮到你! ### 回答2: 批量修改字段编码格式需要以下步骤: 1. 连接数据库:使用数据库的连接工具,如MySQL Workbench或Navicat等,连接到需要修改编码格式数据库。 2. 备份数据:在进行任何修改之前,务必先备份需要修改的数据,以防止数据丢失。可以通过导出数据为.sql文件的方式进行备份。 3. 查看当前编码格式:通过执行"SHOW CREATE TABLE 名"的SQL语句,查看当前需要修改字段编码格式。例如,如果需要修改名为"students"的字段编码格式,可以执行"SHOW CREATE TABLE students"。 4. 修改字段编码格式:根据查看到的字段编码格式,可以使用"ALTER TABLE 名 MODIFY COLUMN 字段名 新编码格式"的SQL语句来进行修改。例如,如果需要将字段名为"name"的编码格式修改为UTF-8,可以执行"ALTER TABLE students MODIFY COLUMN name VARCHAR(100) CHARACTER SET utf8"。 5. 批量修改所有需要修改字段:根据需要修改字段数量,逐个执行步骤4的SQL语句,将所有需要修改字段编码格式进行修改。 6. 验证修改结果:可以执行"SHOW CREATE TABLE 名"等SQL语句,再次查看修改后的字段编码格式是否已经正确修改。 7. 测试数据:在完成字段编码格式修改后,可以随机选择部分数据进行测试,确保数据在修改编码格式后能够正确显示和存储。 8. 数据恢复:如果在修改过程发生了错误或者数据不符合预期,可以使用之前备份的.sql文件进行数据恢复,使数据回到修改之前的状态。 通过以上步骤,可以批量修改字段编码格式。 ### 回答3: 批量修改字段编码格式可通过以下步骤实现: 1. 首先,确定需要修改字段。可以使用数据库管理工具(如MySQL Workbench)连接到数据库,并选择相应的。 2. 探索字段编码格式。可以使用SHOW COLUMNS语句查询结构,找到需要修改编码格式字段。 3. 建立备份。在进行批量修改之前,务必对进行备份,以防止意外删除或修改。 4. 创建修改的SQL语句。根据需要修改字段编码格式,使用ALTER TABLE语句来更改结构。例如,如果要将字段编码格式从UTF-8更改为UTF-16,可以使用以下SQL语句: ALTER TABLE 名 MODIFY 字段字段类型 CHARACTER SET utf16 COLLATE utf16_unicode_ci; 5. 执行SQL语句。在数据库管理工具,将修改的SQL语句复制并粘贴到查询编辑器,然后执行语句。 6. 检查修改结果。执行完SQL语句后,可以使用SHOW COLUMNS语句再次查询结构,验证字段编码格式是否已成功修改。 7. 若需要批量修改多个字段,重复步骤4-6,直至所有需要修改编码格式字段都完成修改。 8. 最后,确认所有的修改已正确完成,并根据需要清除备份。 总结:批量修改字段编码格式需要通过数据库管理工具连接及查询结构,根据需要创建修改的SQL语句,并在执行后检查结果以确保修改正确完成。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LUNG108

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值