1. 程式人生 > 資料庫 >利用python解決mysql檢視匯入匯出依賴的問題

利用python解決mysql檢視匯入匯出依賴的問題

檢視

檢視是一個虛擬表(非真實存在),其本質是根據SQL語句獲取動態的資料集,併為其命名,使用者使用時只需使用名稱即可獲取結果集,並可以將其當作表來使用。

建立檢視

建立一個名稱為v1的檢視,其功能就是查詢color表中的所有資料

CREATE VIEW v1 AS SELECT * FROM color;

檢視檢視

使用檢視時,將其當作表進行操作即可,由於檢視是虛擬表,所以無法使用其對真實表進行建立、更新和刪除操作,僅能做查詢用。

select * from v1; -- 等於執行SELECT * FROM color

輸出結果

+-----+--------+
| nid | title |
+-----+--------+
| 1 | red |
| 2 | yellow |
+-----+--------+
2 rows in set (0.00 sec)

修改檢視

ALTER VIEW v1 AS SELECT * FROM color WHERE nid = 1;

刪除檢視

DROP VIEW v1;

引用

navicat是mysql視覺化工具中最棒的,但是,在處理檢視的匯入匯出方面,它是按照檢視名稱的字母順序來處理的,若檢視存在依賴,在匯入過程中就會報錯。這個問題一直困繞我,一度因為我使用docker來部署mysql而繞過了這個問題。最近不得不直面這個問題,因此,寫了一個小工具來解決它。

整體思路

在mysql很容易查出所有檢視和其定義,因此可以寫一個檢視匯出工具,儲存時對各檢視的儲存位置進行調整,處理好它們之間的依賴關係,被依賴的放前面,這樣就解決了匯入時的依賴問題。

獲取檢視資訊

執行以下查詢語句,就能獲得該資料庫中所有檢視的資訊。

select * from information_schema.VIEWS where TABLE_SCHEMA = DatabaseName

查詢結果欄位說明:

  • TABLE_NAME : 數所庫中檢視名稱
  • VIEW_DEFINITION : 檢視的定義程式碼,只有查詢語句部分
  • DEFINER : 檢視定義(建立)者名稱
  • SECURITY : 安全級別

總之,所有檢視的資訊都在這個表中儲存,我要完成任務,只需要TABLE_NAME和VIEW_DEFINITION就可以了。

演算法描述

  • 將查詢結果放到dict中,檢視名稱為key;檢視定義為value;
  • 編寫處理依賴關係的函式process_rely,輸入引數中的rely_old為儲存所有檢視名稱的陣列;返回引數為按依賴關係調整順序後的檢視名稱陣列。之所以這樣做,是一開始考慮到,依賴關係複雜時,可能一次迭代處理不好,需要遞迴呼叫或多次呼叫。

process_rely函式演算法描述:

第一層迴圈,從rely_old中取一個檢視名稱

第二層迴圈,從dict中取出一個鍵值

若鍵值被第一層元素的定義所依賴

若鍵值還不在結果陣列中

若第一層元素不在結果陣列中

追加鍵值到結果陣列中

第一層元素在結果陣列中

將鍵值插入到第一層元素前

鍵值在結果陣列中

第一層元素在結果陣列中

查詢各自在結果陣列中的位置

若第一層元素在鍵值的後

將鍵值移動到第一層元素前

第二層迴圈結束時,若第一層元素還不在結果集中

將第一層元素追加到結果集中

返回結果集

上面的說明,是按python程式碼模式給出的。很幸運,演算法一次就能將複雜的依賴關係處理好了。我在編寫的過程中,剛開始依賴演算法不完善時,通過多次迭代也能處理好複雜的依賴關係。因此,堅定了必勝的信心,完成了這個任務。

完整程式碼

import pymysql
conn = pymysql.connect(host='172.17.0.1',port=3306,user='root',passwd='123456',db='database',charset='utf8mb4')
def process_rely(parmas={},rely_old=[]):
 _rely = []
 _keys = list(parmas.keys())
 for k in rely_old:
  for bl in _keys:
   if str(parmas[k]).find(bl) > -1:
    if bl not in _rely:
     if k not in _rely:
      _rely.append(bl)
     else:
      i = _rely.index(k)
      _rely.insert(i,bl)
    else:
     if k in _rely:
      i = _rely.index(k)
      j = _rely.index(bl)
      if i < j:
       del _rely[j]
       _rely.insert(i,bl)
  if k not in _rely:
   _rely.append(k)
 return _rely
cur = conn.cursor()
cur.execute('select TABLE_NAME,VIEW_DEFINITION from information_schema.VIEWS where TABLE_SCHEMA = %s ','database')
rs = cur.fetchall()
cur.close()
conn.close()
ps = {}
for al in rs:
 ps['`' + al[0] + '`'] = al[1]
rely = process_rely(ps,list(ps.keys()))
# rely = process_rely(ps,rely1)
file_object = open('view.sql','w')
for al in rely:
 file_object.write('DROP VIEW IF EXISTS ' + al + ';\n')
 file_object.write('CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW ' + al +
      ' AS ' + ps[al] + ';\n\n')
file_object.close()

小結

思路要清晰,程式碼要一步步的向最終目標靠近,積跬步以至千里。在做這個工具時,一開始覺得很麻煩,依賴關係若是深層次的,可能一次處理不好,正因為採用的迭代的思想,最後才完成了一次迭代解決問題的完美結局。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。