SQL中為什么不要使用1=1

最近看幾個老項目的SQL條件中使用了1=1,想想自己也曾經這樣寫過,略有感觸,特別拿出來說道說道。

編寫SQL語句就像炒菜,每一種調料的使用都可能會影響菜品的最終味道,每一個SQL條件的加入也可能會影響查詢的執行效率。那么 1=1 存在什么樣的問題呢?為什么又會使用呢?

為什么會使用 1=1?

在動態構建SQL查詢時,查詢條件往往都是動態的,最終執行時可能會使用不同的條件。這時候,他們就會使用“1=1”作為一個始終為真的條件,讓接下來的所有條件都可以方便地用“AND”連接起來,就像是搭積木的時候先放一個基座,其他的積木塊就都可以在這個基座上疊加。

就像下邊這樣:

SELECT * FROM table WHERE 1=1
<if test="username != null">AND username = #{username}
</if>
<if test="age > 0">AND age = #{age}
</if>

這樣就不用在增加每個條件之前先判斷是否需要添加“AND”。

1=1 帶來的問題

性能問題?

我們先來了解一下數據庫查詢優化器的工作原理。查詢優化器就像是一個聰明的圖書管理員,它知道如何最快地找到你需要的書籍。當你告訴它所需書籍的特征時,它會根據這些信息選擇最快的檢索路徑。比如你要查詢作者是“譚浩強”的書籍,它就選擇先通過作者索引找到書籍索引,再通過書籍索引找到對應的書籍,而不是費力的把所有的書籍遍歷一遍。

但是,如果我們告訴它一些無關緊要的信息,比如“我要一本書,它是一本書”,這并不會幫助管理員更快地找到書,反而可能會讓他覺得困惑。一個帶有“1=1”的查詢可能會讓數據庫去檢查每一條記錄是否滿足這個始終為真的條件,這就像是圖書管理員不得不檢查每一本書來確認它們都是書一樣,顯然是一種浪費。

你可能會說:數據庫沒有這么傻吧?

確實,這實際上可能不會產生問題,因為現代數據庫的查詢優化器已經非常智能,它們通常能夠識別出像 1=1 這樣的恒真條件,并在執行查詢計劃時優化掉它們。在許多情況下,即使查詢中包含了1=1,數據庫的性能也不會受到太大影響,優化器會在實際執行查詢時將其忽略。

但是優化器并不是萬能的。在某些復雜的查詢場景中,即使是簡單的 1=1 也可能對優化器的決策造成不必要的影響,比如導致全表掃描。

代碼質量

另外從代碼質量的角度,我們也需要避免在查詢中包含 1=1,有以下幾點考慮:

  1. 代碼清晰性:即使數據庫可以優化掉這樣的條件,但對于閱讀SQL代碼的人來說,1=1可能會造成困惑。代碼的可讀性和清晰性非常重要,特別是在團隊協作的環境中。
  2. 習慣養成:即使在當前的數據庫系統中1=1不會帶來性能問題,習慣了寫不必要的代碼可能會在其他情況下引入實際的性能問題。比如,更復雜的無用條件可能不會那么容易被優化掉。
  3. 跨數據庫兼容性:不同的數據庫管理系統(DBMS)可能有不同的優化器能力。一個系統可能輕松優化掉1=1,而另一個系統則可能不那么高效。編寫不依賴于特定優化器行為的SQL語句是一個好習慣。

編寫盡可能高效、清晰和準確的SQL語句,不僅有助于保持代碼的質量,也讓代碼具有更好的可維護性和可擴展性。

替代 1=1 的更佳做法

現在開發者普遍使用ORM框架來操作數據庫了,還在完全手寫拼SQL的同學可能需要反思下了,這里給兩個不同ORM框架下替代1=1的方法。

假設我們有一個用戶信息表 user,并希望根據傳入的參數動態地過濾用戶。

首先是Mybatis

<!-- MyBatis映射文件片段 -->
<select id="selectUsersByConditions" parameterType="map" resultType="com.example.User">SELECT * FROM user<where><!-- 使用if標簽動態添加條件 --><if test="username != null and username != ''">AND username = #{username}</if><if test="age > 0">AND age = #{age}</if><!-- 更多條件... --></where>
</select>

在 MyBatis 中,避免使用 1=1 的典型方法是利用動態SQL標簽(如 <if>)來構建條件查詢。<where> 標簽會自動處理首條條件前的 AND 或 OR。當沒有滿足條件的 <if> 或其他條件標簽時,<where> 標簽內部的所有內容都會被忽略,從而不會生成多余的 AND 或 WHERE 子句。

再看看 Entity Framework 的方法:

var query = context.User.AsQueryable();
if (!string.IsNullOrEmpty(username))
{query = query.Where(b => b.UserName.Contains(username));
}
if (age>0)
{query = query.Where(b => b.Age = age);
}
var users = query.ToList();

這是一種函數式編程的寫法,最終生成SQL時,框架會決定是否在條件前增加AND,而不需要人為的增加 1=1。

總結

“1=1”在SQL語句中可能看起來無害,但實際上它是一種不良的編程習慣,可能會導致性能下降。就像在做飯時不會無緣無故地多加調料一樣,我們在編寫SQL語句時也應該避免添加無意義的條件。

每一行代碼都應該有它存在的理由,不要讓人和數據庫浪費時間在不必要的事情上。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697506.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697506.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697506.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

昨天Google發布了最新的開源模型Gemma,今天我來體驗一下

前言 看看以前寫的文章&#xff0c;業余搞人工智能還是很早之前的事情了&#xff0c;之前為了高工資&#xff0c;一直想從事人工智能相關的工作都沒有實現。現在終于可以安靜地系統地學習一下了。也是一邊學習一邊寫博客記錄吧。 昨天Google發布了最新的開源模型Gemma&#xf…

電商數據采集的幾個標準

面對體量巨大的電商數據&#xff0c;很多品牌會選擇對自己有用的數據進行分析&#xff0c;比如在控價過程中&#xff0c;需要對商品的價格數據進行監測&#xff0c;或者是需要做數據分析時&#xff0c;則需要采集到商品的價格、銷量、評價量、標題、店鋪名等信息&#xff0c;數…

Unity中.Net與Mono的關系

什么是.NET .NET是一個開發框架&#xff0c;它遵循并采用CIL(Common Intermediate Language)和CLR(Common Language Runtime)兩種約定&#xff0c; CIL標準為一種編譯標準&#xff1a;將不同編程語言&#xff08;C#, JS, VB等&#xff09;使用各自的編譯器&#xff0c;按照統…

JavaScript 原始值和引用值在變量復制時的異同

相比于其他語言&#xff0c;JavaScript 中的變量可謂獨樹一幟。正如 ECMA-262 所規定的&#xff0c;JavaScript 變量是松散類型的&#xff0c;而且變量不過就是特定時間點一個特定值的名稱而已。由于沒有規則定義變量必須包含什么數據類型&#xff0c;變量的值和數據類型在腳本…

mysql.service is not a native service, redirecting to systemd-sysv-install

字面意思&#xff1a;mysql.service不是本機服務&#xff0c;正在重定向到systemd sysv安裝 在CentOS上使用Systemd管理MySQL服務的具體步驟如下&#xff1a; 1、創建MySQL服務單元文件&#xff1a; 首先&#xff0c;你需要創建一個Systemd服務單元文件&#xff0c;以便Syste…

【Python筆記-設計模式】原型模式

一、說明 原型模式是一種創建型設計模式&#xff0c; 用于創建重復的對象&#xff0c;同時又能保證性能。 使一個原型實例指定了要創建的對象的種類&#xff0c;并且通過拷貝這個原型來創建新的對象。 (一) 解決問題 主要解決了對象的創建與復制過程中的性能問題。主要針對…

redhawk:使用ipf文件反標instance power

我正在「拾陸樓」和朋友們討論有趣的話題,你?起來吧? 拾陸樓知識星球入口 往期文章鏈接: Redhawk:Input Data Preparation 使用ptpx和redhawk報告功耗時差別總是很大,如果需要反標top/block的功耗值可以在gsr文件中使用BLOCK_POWER_FOR_SCALING的命令

Verilog刷題筆記35

題目&#xff1a; Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel0 should select in[0], sel1 selects bits in[1], sel2 selects bits in[2], etc. 解法&#xff1a; module top_module( input [255:…

Spring Cloud Alibaba-05-Gateway網關-02-斷言(Predicate)使用

Lison <dreamlison163.com>, v1.0.0, 2023.10.20 Spring Cloud Alibaba-05-Gateway網關-02-斷言(Predicate)使用 文章目錄 Spring Cloud Alibaba-05-Gateway網關-02-斷言(Predicate)使用通過時間匹配通過 Cookie 匹配通過 Header 匹配通過 Host 匹配通過請求方式匹配通…

C# CAD2016 cass10宗地Xdata數據寫入

一、 查看cass10寫入信息 C# Cad2016二次開發獲取XData信息&#xff08;二&#xff09; 一共有81條數據 XData value: QHDM XData value: 121321 XData value: SOUTH XData value: 300000 XData value: 141121JC10720 XData value: 權利人 XData value: 0702 XData value: YB…

2.居中方式總結

居中方式總結 經典真題 怎么讓一個 div 水平垂直居中 盒子居中 首先題目問到了如何進行居中&#xff0c;那么居中肯定分 2 個方向&#xff0c;一個是水平方向&#xff0c;一個是垂直方向。 水平方向居中 水平方向居中很簡單&#xff0c;有 2 種常見的方式&#xff1a; 設…

java面試題之mybatis篇

什么是ORM&#xff1f; ORM&#xff08;Object/Relational Mapping&#xff09;即對象關系映射&#xff0c;是一種數據持久化技術。它在對象模型和關系型數據庫直接建立起對應關系&#xff0c;并且提供一種機制&#xff0c;通過JavaBean對象去操作數據庫表的數據。 MyBatis通過…

MATLAB練習題:randperm函數的練習題

?講解視頻&#xff1a;可以在bilibili搜索《MATLAB教程新手入門篇——數學建模清風主講》。? MATLAB教程新手入門篇&#xff08;數學建模清風主講&#xff0c;適合零基礎同學觀看&#xff09;_嗶哩嗶哩_bilibili MATLAB中有一個非常有用的函數&#xff1a;randperm函數&…

華為算法題 go語言或者ptython

1 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素在答案里不能重復出現。 你可以按任意順序返…

如何進行高性能架構的設計

一、前端優化 減少請求次數頁面靜態化邊緣計算 增加緩存控制&#xff1a;請求頭 減少圖像請求次數&#xff1a;多張圖片變成 一張。 減少腳本的請求次數&#xff1a;css和js壓縮&#xff0c;將多個文件壓縮成一個文件。 二、頁面靜態化 三、邊緣計算 后端優化 從三個方面進…

adb-monkey命令

目錄 adb shell monkey -p/-v 包名 次數 1、指定一個包 2、指定多個包 3、不指定包 Event percentages&#xff08;事件百分比&#xff09; 常見參數 --throttle 延遲時間 單位毫秒 --pct-touch 設定觸屏事件生成的百分比 --pct-motion 設定滑動事件生成…

面試前端性能優化八股文十問十答第二期

面試前端性能優化八股文十問十答第二期 作者&#xff1a;程序員小白條&#xff0c;個人博客 相信看了本文后&#xff0c;對你的面試是有一定幫助的&#xff01;關注專欄后就能收到持續更新&#xff01; ?點贊?收藏?不迷路&#xff01;? 1&#xff09;如何優化動畫&#x…

c語言中的大小寫字母轉換怎么轉?

在C語言中&#xff0c;大小寫字母轉換是基于ASCII碼表的特性實現的。ASCII碼中&#xff0c;小寫字母從’a’到’z’的ASCII碼值是連續的&#xff08;97到122&#xff09;&#xff0c;而大寫字母從’A’到’Z’的ASCII碼值也是連續的&#xff08;65到90&#xff09;。它們之間有…

Redis高性能原理

redis大家都知道擁有很高的性能&#xff0c;每秒可以支持上萬個請求&#xff0c;這里探討下它高性能的原理。單線程架構和io多路復用技術。 一&#xff0c;單線程架構 單線程架構指的是命令執行核心線程是單線程的&#xff0c;數據持久化、同步、異步刪除是其他線程在跑的。re…

獲取視頻第一幀,以及后續上傳

// 獲取視頻基本信息 const getVideoBasicInfo (videoSrc) > {return new Promise((resolve, reject) > {const video document.createElement("video");video.src videoSrc;// 視頻一定要添加預加載video.preload "auto";// 視頻一定要同源或者…