1. 程式人生 > >同時修改某一個數據庫中所有表的所有欄位的編碼格式(mysql)

同時修改某一個數據庫中所有表的所有欄位的編碼格式(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

相關推薦

同時修改個數所有所有編碼格式mysql

最近在進行原始碼的二次開發,突然之間有了一個小的需求,就這麼悄悄的突然出現了。 需求原因就不說了,只說這個怎麼實現的。我是用的是mysql資料庫,其他的略有不同,具體到哪一點就只能具體變化了。 看網上有的說直接把資料庫或者表的編碼做改變就行了,可是這樣對欄位來說都沒有影響。

sql語句怎麼在個數查詢擁有同一名的所有

1. SELECT TABLE_NAME  FROM INFORMATION_SCHEMA.COLUMNS  WHERE COLUMN_NAME = '欄位名' 2. SELECT COLUMN_NAME,TABLE_NAME FROM INFORMATION_SCHE

Sql Server 導入還有個數

數據庫 tex .net mark manage alt img 資源管理 一個數據庫 在涉及到SQL Server編程或是管理時一定會用到數據的導入與導出, 導入導出的方法有多種,此處以SQL Server導入表數據為例。闡述一下:1、打開SQL Server Mana

SQL SERVER 將個數和資料複製到另個數

第一種情況:將A資料庫.dbo.A表的資料追加到B資料庫.dbo.B表中 (條件:此時B資料庫中已建立好了B表) insert into B資料庫.dbo.B表 select * from A資料庫.dbo.A表 [where條件] 此T-SQL語句會有異常   &n

sqlyog,將個數資料複製到另個數

第一步:右鍵源資料庫名,單擊“將資料庫複製到不同的主機/資料庫”,檢視圖一,圖二。                                                                                  (圖一)           

mysql 如何將個數某個某個匯入另外個數裡指定表裡

如果在同一個例項下,也就是在同一個資料庫裡面,mysql很方便實現。insert into B.table2(c)select b from A.table1; -------------------

SQLSERVER復制數一個到另個數可跨服務器

led 數據 rom msdb pan 錯誤 ons 數據庫 ble 一、復制數據庫某一個表到另一個數據庫中(同一服務器) SELECT * INTO 表1 FROM 表2 --復制表2如果只復制結構而不復制內容或只復制某一列只要加WHERE條件就好了 例子:SELECT

基本原理# 3:個數有什麽?

決定 完整 存在 相關 recipe 信息 插入 是什麽 window 數據庫基本原理# 3:一個數據庫中有什麽? 值得一提的是很多人將不需要去創建他們自己的數據庫。你可能從不會去創建你自己的表格或者是其他的一些數據結構。你可能是安裝應用系統為你創建數據庫,你也只是做一些備

python資料庫 資料存入另個數

把'aa'資料庫中資料存入default ##############################################  student =Student.objects.using('aa').order_by('id').filter(pk__gt=1)

java實現從個數查詢資料經過處理匯入另外個數

            當資料庫表中有clob欄位或要對錶中資料做較複雜處理時就不太好用指令碼從一個數據庫匯入資料到另外一個數據庫中了,這時就要通過程式碼實現了,下面以orale資料庫為例程式碼如下: import java.sql.Connection; import j

MS SQL複製到另外個數

--複製結構+資料 select * into 資料庫名.dbo.新表名 from 資料庫名.dbo.原表名 select * into Stockholder.dbo.SHInfo from dspring.dbo.HIREMEN --只複製結構

統計個數庫內所有的記錄條數總和,統計個數有多少張的SQL語句

--統計一個數據庫內所有表的記錄條數總和select SUM(rowcounts)from (SELECT OBJECT_NAME(id) AS [TBName],MAX(rowcnt)[rowcounts]       FROM sys.sysindexes GROUP B

SQL 怎麼查詢個數共有多少個

使用者表:select count(*) 總表數 from sysobjects where xtype='u'    剛才那個是使用者表,下面這個是系統表加使用者表: select count(*) 總表數 from sysobject s where xtype in(

觸發器問題怎樣在個數的觸發器訪問另個數裡面的

--如果兩個庫在同一個sql例項中           select   *   from   另一庫.dbo.表             --如果兩個庫在不同的sql例項中           select   *   from   openrowset('sqlole

MySQL資料庫,從個數複製指定到另個數

需求: 這幾天專案中遇到一個問題,需要將一個mysql資料庫中某些表的資料複製到另一個數據庫中,這個資料庫是不存在的,也需要在程式碼中動態建立資料庫,然後將表直接複製到這個動態建立的資料庫中。 網上

SQL如何獲取個數所有的名稱、一個所有的名稱

1.查詢資料庫中的所有資料庫名: SELECT Name FROM Master..SysDatabases ORDER BY Name 2.查詢某個資料庫中所有的表名: SELECT Name FROM SysObjects Where XType='U' ORDER BY

使用python3將mysql資料庫資料轉移到另個數

需求 將mysql中查詢到的資料匯入到另一個數據庫表中 程式碼 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # import pymysql

sql server 2008 如何將個數已建好的匯入到另個數

將一個數據表從一個數據庫匯入到另一個數據庫可以按如下步驟操作:(1)啟動Microsoft SQL Server Management Studio程式(2)按提示操作進入系統(3)選擇那個建好表的資料庫(4)點選滑鼠右鍵,會彈出一個選單,選擇選單命令:任務/匯出資料(5)按

SQLite 如何實現從個數的某個的記錄複製到另個數

最近遇到了跨資料庫複製表中記錄問題,折騰了兩天,終於得到了解決!總結如下: 一、跨資料庫複製表中記錄 SQL語句: --1.附加資料庫ATTACH DATABASE T1 As A1;--2.將A1中的記錄插入到目標資料庫的表中 Insert Into sn_info(au

mysql 怎樣清空個數所有

Mysql清空表是很重要的操作,也是最常見的操作之一,下面就為您詳細介紹Mysql清空表的實現方法,希望能夠對您有所幫助。 方法1:重建庫和表 一。只匯出表結構 匯出整個資料庫結構(不包含資料) mysqldump -h localhost -uroot -p12345