萬能模糊查詢SQL


******************************************************************

* 功能:萬能模糊查詢SQL
* 時間:2015/1/30 16:00:22
* 開發者:流浪的菜鳥
* 需求來源:要查詢系統數據庫中,有某些特殊字段是否存在。
* 實現思路
  1.為了防止后期,需求變更,自己打算寫一個萬能通用的SQL,只需要給出 關鍵字,就能查詢到當前數據庫中所有關鍵字存在的地方
  2.第一步,要循環當前數據中所有的表,當然想到了用系統表和游標。同時在循環表的時候,嵌套循環當前表的結構,
          所以必須會用到兩個嵌套的游標來完成實現
  3.第二步,查詢相應的數據庫文檔,找到相應能快速查詢到所有表,所有列的系統表
  4.第三步,根據實現的思路,一步步的去實現完成
* 最終導出生成對應的報表,報表能看到,當前數據庫中有哪些表,哪個字段的值包含了當前特殊字段
* 課外資料(必須要知道的那些潛規則)
    1. sql 常見的系統表,以及系統表對應的功能查詢
            select * from sys.all_objects where type='u'  ---查詢當前數據庫中所有的表,其中是屬於用戶創建的表,不是系統表
            select * from  information_schema.columns     ---查詢當前表中所有列,以及列的屬性(比如列的名稱,列的數據類型,后面有用到)
    2. 游標的工作執行原理,以及相關的特性
    3.存儲過程,以及sql字符串的拼接操作
    4.調試使用好 print 關鍵字,打印出來相應的sql語句來驗證自己的思路和結果是否正確  
*注意事項
  1.自己所寫的程序必須要嚴格優化你的SQL,我一開始沒有優化,導致執行我的這個sql的時候數據庫出現相應的異常,讓我好蛋疼,於是我猜想
   異常:由於這個系統有1589張表,循環表就循環1589次,然后再1589次當中還得循環每個表的字段(平均每個表有35個字段),
   那算起來大概要循環五萬次,然后這五萬次循環的時候 還得去模糊拼接查詢一次數據庫,估計游標受不了,或者內存不足,具體原因待查
  2.細節注意的地方: exec sp_executesql 其中這個地方要注意,執行這個的時候 它拼接生成的sql的標量聲明必須是 nvarchar,不能是varchar,
   這一點比較惡心,我這里就是少寫了個n,導致一直報錯。
  3.循環所有的表,所有的字段,邏輯是這樣的,但是實際業務沒必要去這樣做,這里就做好優化的相關代碼
    比如我這里優化了兩個:
     第一. 排除了數據庫中表的數據是0的,也就是說當前表中沒有任何數據,沒有數據的我就沒有必要去循環當前表的結構和模糊查詢了
     第二. 模糊查詢肯定是針對表中字段是 字符串類型的,如果不是字符串類型的(text,varchar,nvarchar等),當然沒必要去循環模糊查詢了
     第三. 后期還需要優化的代碼 
 
******************************************************************/
declare @QueryKeyword nvarchar(2000)
set @QueryKeyword='關鍵字'
declare @tblname nvarchar(200) --表名稱 
declare @tablenum int ---獲取執行查詢表中是否有數據 返回的結果 只要大於1 代表 這個表有數據,就進行列的循環讀取和模糊匹配
declare @tablestr nvarchar(4000)
declare tbl_cursor cursor for select name from sys.all_objects where type='u'
---定義表的游標,並且指定游標的循環范圍 當前數據庫的所有表(所有用戶表)
---獲取當前數據庫中的表  
open tbl_cursor --打開游標 
fetch next from tbl_cursor  INTO @tblname --游標開始循環讀取,一條條讀取,讀取每一條的時候 將讀到的表名稱 賦值給標量@tblname
--將當前游標讀取到的表名稱 保存到標量中,給下面的循環使用 每一次循環得到表名
while @@FETCH_STATUS = 0 ---只要讀到數據,就循環執行下面的操作 
begin
    ----開始 排除沒有數據的表 (優化)
     set @tablestr='select @b=count(*) from '+@tblname 
     exec sp_executesql @tablestr,N'@b int output',@tablenum output ---執行當前的數據結果集,有數據的表,才能進行表結構中每個字段的循環
     if(@tablenum>0) --得到有數據的表 
     begin  
declare @str nvarchar(4000)
declare @colvaluesql nvarchar(4000)
set @str='' --開始拼接 表中的字段 
declare @data_typevalue nvarchar(200)
declare @num int 
declare @colname nvarchar(200) ---表中列的標量
declare col_cursor cursor for  select column_name,data_type from information_schema.columns where table_name= @tblname order by column_name
--定義列的游標,循環的范圍是當前表中的所有列,以及列相應的數據類型  
--如果不是字符串類型的 都忽略掉 
open col_cursor  --打開游標 
fetch next from col_cursor into @colname,@data_typevalue --將列游標讀到的列 放到變量中
while @@FETCH_STATUS = 0
begin
 ---初步判斷 數據類型符合的有 nvarchar ntext 兩種數據類型的 符合 
 --當只有數據類型符合規則的時候 才生成對應模糊查詢的sql
  if(@data_typevalue='nvarchar' or @data_typevalue='ntext')
   begin
 set @str='select @a=count(*) from '+@tblname+' where '+@colname+' like ''%'+@QueryKeyword+'%'''
 set @colvaluesql='select '+@colname+',* from '+@tblname+' where '+@colname+' like ''%'+@QueryKeyword+'%'''
 exec sp_executesql @str,N'@a int output',@num output ---執行模糊查詢 返回模糊查詢的結果
 if(@num>0) ---如果模糊查詢的結果 有值 那么就說明該表這的這個字段中包括這個 關鍵字
begin 
  -------這里 可以進行相應的擴展,比如生成批量的查詢 修改,刪除語句,並且執行
  -------擴展區
  -------擴展區
print @colvaluesql  ---打印出 符合模糊查詢的表 生成相應的sql
exec(@colvaluesql)  ----執行 sql
end  
   end 
  fetch next from col_cursor into @colname,@data_typevalue
 END   
close col_cursor    ---關閉列的游標
deallocate col_cursor  --釋放列的游標
                
end
------結束 排除沒有數據的表 (優化)
    fetch next from tbl_cursor into @tblname  --讓表的游標繼續讀下一條數據
End
close tbl_cursor  --關閉游標
deallocate tbl_cursor   --釋放游標資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM