日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

如何踢掉 sql 语句中的尾巴,我用 C# 苦思了五种办法

發布時間:2023/12/4 C# 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何踢掉 sql 语句中的尾巴,我用 C# 苦思了五种办法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:背景

1. 講故事

這幾天都在修復bug真的太忙了,期間也遇到了一個挺有趣bug,和大家分享一下,這是一塊sql挺復雜的報表相關業務,不知道哪一位大佬在錯綜復雜的 嵌套 + 平行 if判斷中sql拼接在某些UI組合下出問題了,最終的 sql 架構類似這樣的。

var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";

這種sql到數據庫去肯定是報錯的,有些朋友可能想說這還不簡單,在相關的 if 判斷中不要追加這個 union all 就好了,這確實是一個根治的辦法,但現實情況這一塊的業務太復雜了,也不太敢改里面的代碼,改的沒問題還好,改出問題你得兜著走,所以最保險的辦法就是怎么去掉 union all 這個大尾巴,所以我干脆思考了一會,想出了如下五種辦法。

二:剔除 union all 的五大方式

1. 最原始的 for 循環

最簡單的辦法就是通過 for 循環搞定,我可以倒序判斷最后幾個字符是不是關鍵詞 union all 就可以了,如下代碼所示:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";var?isall?=?true;int?i?=?0;for?(i?=?1;?i?<=?keyword.Length;?i++){if?(keyword[keyword.Length?-?i]?!=?sql[sql.Length?-?i]){isall?=?false;break;}}if?(isall){var?query?=?sql.Substring(0,?sql.Length?-?i?+?1);Console.WriteLine(query);}}

從代碼中可以看出,只要在倒序的過程中,有一個字符和 keyword 中的不符,那就直接跳出,否則就是全匹配,拿到最后的 i 進行 Substring 截取即可。

2. 使用 Substring 搞定

第一種方式確實可以實現,但實現的并不輕松,畢竟大家都是用 C# 寫代碼而不是 C,為了這點小功能寫了這么多代碼,顯得太 low 了,所以盡量能用類庫的方法就用類庫的方法吧,改進措施很簡單,可以從 sql 尾部切出 keyword.length 個字符,也就是:start:sql.length - keyword.length,然后判斷一下是否和 keyword 相等即可,代碼修改如下:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";var?isSucc?=?sql.Substring(sql.Length?-?keyword.Length)?==?keyword;if?(isSucc){var?query?=?sql.Substring(0,?sql.Length?-?keyword.Length);Console.WriteLine(query);}}

3. 使用 LastIndexOf

第二種方式寫出來的代碼確實比較簡潔,但大家有沒有發現一個問題,我為了獲取最后的 string 做了兩次 substring 操作,也就是說在托管堆中生成了兩個 string 對象,那能不能免掉一個 substring 呢?給 gc 減輕一些負擔,這就可以用到 LastIndexOf 方法了,代碼如下:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";var?index?=?sql.LastIndexOf(keyword);if?(sql.Length?-?index?==?keyword.Length){var?query?=?sql.Substring(0,?index);Console.WriteLine(query);}}

思想很簡單,就是判斷最后出現的 union all的位置到尾部的距離 是否恰好和 keyword.length 一致,如果是的話那 keyword 就是 sql 的大尾巴,這里的 if 寫的有點難懂,其實還可以使用 ?EndsWith 再優化一下代碼:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";if?(sql.EndsWith(keyword)){var?query?=?sql.Substring(0,?sql.Length?-?keyword.Length);Console.WriteLine(query);}}

4. 使用 Split 切割

前面幾種方式都是在 string 上做文章,要么 substring,要么 LastIndexOf,要么 EndsWith,其實也可以跳出這個定勢思維,轉換成數組進行處理,用 union all 作為分隔符切割字符串,如果數組的最后一個元素為 string.Empty,那就表明 sql 尾巴就是 keyword, 對吧,代碼修改如下:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";var?arr?=?sql.Split("union?all");if?(string.IsNullOrEmpty(arr[arr.Length?-?1])){var?query?=?string.Join(keyword,?arr.Take(arr.Length?-?1));Console.WriteLine(query);}}

5. 使用 TrimEnd

相信很多朋友用這個方法的場景大多在于剔除尾部的空格,哈哈,其實它還有一個隱藏功能,不僅可以剔除空格,還可以剔除任意多個指定的字符,這就????????了,不信的話可以看看 TrimEnd 方法簽名即可:

public?sealed?class?String{public?string?TrimEnd(params?char[]?trimChars){if?(trimChars?==?null?||?trimChars.Length?==?0){return?TrimHelper(1);}return?TrimHelper(trimChars,?1);}}

可以看到 trimChars 是一個字符數組,你可以灌入你想剔除的任意多·個字符,有了這個思想,我可以將 keyword 轉成 char[] 再灌入到 TrimEnd 即可,代碼如下:

static?void?Main(string[]?args){var?sql?=?"select?1?union?all?select?2??union?all?select?3?union?all";var?keyword?=?"union?all";var?query?=?sql.TrimEnd(keyword.ToArray());Console.WriteLine(query);}

可以看出已成功剔除,此時我很好奇底層到底是怎么實現的,源碼如下:

private?string?TrimHelper(char[]?trimChars,?int?trimType){int?num?=?Length?-?1;int?i?=?0;if?(trimType?!=?1){for?(i?=?0;?i?<?Length;?i++){int?num2?=?0;char?c?=?this[i];for?(num2?=?0;?num2?<?trimChars.Length?&&?trimChars[num2]?!=?c;?num2++){}if?(num2?==?trimChars.Length){break;}}}if?(trimType?!=?0){for?(num?=?Length?-?1;?num?>=?i;?num--){int?num3?=?0;char?c2?=?this[num];for?(num3?=?0;?num3?<?trimChars.Length?&&?trimChars[num3]?!=?c2;?num3++){}if?(num3?==?trimChars.Length){break;}}}return?CreateTrimmedString(i,?num);}private?string?CreateTrimmedString(int?start,?int?end){int?num?=?end?-?start?+?1;if?(num?==?Length){return?this;}if?(num?==?0){return?Empty;}return?InternalSubString(start,?num);}

這么多代碼,看樣子 TrimEnd 底層也不是那么容易的,雖然用起來很爽。

四:總結

五種方式各有利弊,不管是簡單粗暴的,基于性能的,靈活巧妙的,都能達到最終的目的,暫時就想到這5種,腦仁已經疼了????????????, 更多好玩的寫法,歡迎大家留言討論哈!

總結

以上是生活随笔為你收集整理的如何踢掉 sql 语句中的尾巴,我用 C# 苦思了五种办法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。