Oracle/MySQL/PG/SQL Server關係資料庫中NULL與空字元串的區別

来源:https://www.cnblogs.com/kerrycode/archive/2023/07/17/17560541.html
-Advertisement-
Play Games

Oracle資料庫 在Oracle資料庫中,''(空字元串)與null是什麼關係呢? ''(空字元串)是否會等同(或者說等價於)於null值呢?''跟' '(長度為零的空字元串或包含一個或多個空格的空字元串)是否又等價?下麵我們測試一下 SQL> create table test(id numbe ...


Oracle資料庫

在Oracle資料庫中,''(空字元串)與null是什麼關係呢? ''(空字元串)是否會等同(或者說等價於)於null值呢?''跟' '(長度為零的空字元串或包含一個或多個空格的空字元串)是否又等價?下麵我們測試一下

SQL> create table test(id number not nullname varchar2(16));

Table created.

SQL> insert into test(idnamevalues(1null);

1 row created.

SQL> insert into test(idnamevalues(2'');

1 row created.

SQL> insert into test(idnamevalues(3' '); --符號中' '有一個空格

1 row created.

SQL> insert into test(idnamevalues(4'  '); --符號中'  '有兩個空格


1 row created.

SQL> commit;

Commit complete.

SQLselect * from test where name is null;

        ID NAME
---------- ----------------
         1
         2

2 rows selected.

##三值邏輯,因為''等價與null,null跟任何非null的值比較都等於false
SQL> select * from test where name='';

no rows selected

SQL> select * from test where name=' '--符號中' '有一個空格

        ID NAME
---------- ----------------
         3

1 row selected.

SQL> select * from test where name='  ';--符號中'  '有兩個空格

        ID NAME
---------- ----------------
         4

1 row selected.

SQL> select id ,dump(namefrom test;

        ID DUMP(NAME)
---------- --------------------
         1 NULL
         2 NULL
         3 Typ=1 Len=1: 32
         4 Typ=1 Len=2: 32,32

4 rows selected.

SQL>

如上所示,插入''時,Oracle資料庫確實將其等同與null,但是,像' '這種長度不為零的空字元串,Oracle會存儲其值,從上面實驗就可以看出。另外官方文檔[1]中關於''與Null的解釋如下:

Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls.

翻譯如下:

Oracle 資料庫當前將長度為零的空字元值視為Null。但是,在將來的版本中,這種情況可能不會繼續存在,Oracle 建議您不要將空字元串視為null值。

另外,還有一個有意思的現象,如果在查詢條件中,包含一個空格與包含兩個空格的對比,它們似乎又是等價的。如下所示:

SQL> select * from test where ' ' = '  '

        ID NAME
---------- ----------------
         1
         2
         3
         4

4 rows selected.

SQL>

SQL Server資料庫

這個實驗,我們在SQL Server資料庫測試一下看看,你會看到不一樣的現象。

create table test(id int ,name varchar(16) );

insert into test(idnamevalues(1null);
insert into test(idnamevalues(2'');
insert into test(idnamevalues(3' ');--包含一個空格
insert into test(idnamevalues(4'  ');--包含兩個空格
SELECT * FROM TEST WHERE NAME IS NULL;
SELECT * FROM TEST WHERE NAME ='';
SELECT * FROM TEST WHERE NAME =' ';--包含一個空格
SELECT * FROM TEST WHERE NAME ='  ';--包含兩個空格
SELECT IDDATALENGTH(NAMEAS COLUMN_LEN FROM TEST;
SELECT * FROM TEST WHERE '' = ' ';

如上測試,SQL Server跟Oracle不一樣,在SQL Server中,’’跟null是不一樣的,空字元串是空字元串,null是null,SQL Server資料庫中不會將長度為零的空字元串視為null。但是SQL Server在查詢的時候比較空字元串時,長度為零的空字元串與長度為1的字元串,長度為N的字元串,它們似乎是等價的。跟Oracle的行為完全不一樣。這個的解釋如下,詳情參考官方文檔[2]

SQL Server follows the ANSI/ISO SQL-92 specification (Section 8.2, , General rules #3) on how to compare strings with spaces. The ANSI standard requires padding for the character strings used in comparisons so that their lengths match before comparing them. The padding directly affects the semantics of WHERE and HAVING clause predicates and other Transact-SQL string comparisons. For example, Transact-SQL considers the strings 'abc' and 'abc ' to be equivalent for most comparison operations.

The only exception to this rule is the LIKE predicate. When the right side of a LIKE predicate expression features a value with a trailing space, SQL Server does not pad the two values to the same length before the comparison occurs. Because the purpose of the LIKE predicate, by definition, is to facilitate pattern searches rather than simple string equality tests, this does not violate the section of the ANSI SQL-92 specification mentioned earlier.

SQL Server 遵循 ANSI/ISO SQL-92 規範(第8.2、<比較謂語>、常規規則 #3),說明如何比較帶有空格的字元串。 ANSI 標準要求在比較中使用空字元填充字元串,以便它們的長度與比較它們的長度相匹配。 填充直接影響 WHERE 和 HAVING 子句謂詞以及其他 Transact-SQL 字元串比較的語義。 例如,Transact-SQL 會將字元串 "abc" 和 "abc " 視為對大多數比較操作等效。此規則的唯一例外是類似謂語。 當 LIKE 謂詞表達式的右側具有尾隨空格的值時,SQL Server 不會在比較發生之前將這兩個值填充到同一長度。 根據定義,LIKE 謂語的用途是促進模式搜索,而不是簡單的字元串相等測試,這不違反前面提到的 ANSI SQL-92 規範的部分。

MySQL資料庫

接下來,我們來看看MySQL資料庫的測試情況。

mysql> use test
Database changed
mysql> create table test(id int not nullname varchar(16));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test(id , namevalues(1null);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test(id , namevalues(2'');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test(id , namevalues(3' ');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id , namevalues(4'  ');
Query OK, 1 row affected (0.00 sec)

mysql> select * from test where name is null;
+----+------+
| id | name |
+----+------+
|  1 | NULL |
+----+------+
1 row in set (0.00 sec)

mysql> select * from test where name='';
+----+------+
| id | name |
+----+------+
|  2 |      |
|  3 |      |
|  4 |      |
+----+------+
3 rows in set (0.00 sec)

mysql>
mysql> select * from test where name=' ';
+----+------+
| id | name |
+----+------+
|  2 |      |
|  3 |      |
|  4 |      |
+----+------+
3 rows in set (0.00 sec)

mysql>

MySQL的對於null和空字元串的處理方式跟SQL Server是一致的。但是你會發現還是有不一樣的地方,下麵這個SQL語句, 在SQL Server和MySQL中有不一樣的結果。

mysql> select * from test where '' = ' ';
Empty set (0.00 sec)

PostgreSQL資料庫

postgres=# \c kerry
You are now connected to database "kerry" as user "postgres".
kerry=# create table test(id int not null, name varchar(16));
CREATE TABLE
kerry=# insert into test(id , name) values(1, null);
INSERT 0 1
kerry=# insert into test(id,  name) values(2, '');
INSERT 0 1
kerry=# insert into test(id,  name) values(3, ' ');
INSERT 0 1
kerry=# insert into test(id,  name) values(4, '  ');
INSERT 0 1
kerry=# select * from test where name is null;
 id | name 
----+------
  1 | 
(1 row)

kerry=# select * from test where name='';
 id | name 
----+------
  2 | 
(1 row)

kerry=# select * from test where name=' ';
 id | name 
----+------
  3 |  
(1 row)

kerry=# select * from test where name='  ';
 id | name 
----+------
  4 |   
(1 row)

kerry=#

kerry=# select * from test where '' = ' ';
 id | name 
----+------
(0 rows)

PostgreSQL的對於null和空字元串的處理方式跟MySQL是一致的.

總結:

幾大關係資料庫中,只有Oracle資料庫會將''視為null,其它關係資料庫中,null和''是不同的。另外,包含一個或多個空格的空字元串在細節上有所不同,上面簡單實驗已經展示了這些細微區別。

參考資料

[1]

1: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Nulls.html#:~:text=Oracle%20Database%20currently%20treats%20a%20character%20value%20with,expression%20containing%20a%20null%20always%20evaluates%20to%20null

[2]

2: https://support.microsoft.com/en-us/topic/inf-how-sql-server-compares-strings-with-trailing-spaces-b62b1a2d-27d3-4260-216d-a605719003b0

掃描上面二維碼關註我 如果你真心覺得文章寫得不錯,而且對你有所幫助,那就不妨幫忙“推薦"一下,您的“推薦”和”打賞“將是我最大的寫作動力! 本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接.
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # 網路基礎 ## **網路通信** 1. 概念:兩台設備之間通過網路實現數據傳輸; 2. 網路通信:將數據通過網路從一臺設備傳輸到另一臺設備; 3. java.net包下提供了一系列的類或介面,供程式員使用,完成網路通信; ![](https://img2023.cnblogs.com/blog/ ...
  • ### AQS的定義 ​ 隊列同步器 AbstractQueuedSynchronizer(以下簡稱同步器),是用來構建鎖或者其他同步組件的基礎框架,它使用了一個 int 成員變數表示同步狀態,通過內置的 FIFO 隊列來完成資源獲取線程的排隊工作,併發包的作者(Doug Lea)期望它能夠成為實現 ...
  • 本章將和大家分享 ASP.NET Core SignalR 中的中心篩選器。 本文大部分內容摘自微軟官網:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hub-filters?view=aspnetcore-7.0 廢話不多說,下麵我們直 ...
  • 1.ReferenceEquals(object o1, object o2): 靜態方法:比較兩個對象的引用,引用相同返回true,否則返回false,同為null是返回true;ReferenceEquals進行值類型比較時總是返回false,因為兩個值類型需要分別裝箱到對象中,是不同的引用 ; ...
  • # shell腳本-Nginx訪問日誌分析 ## 1.原理 > 可以通過/usr/local/nginx/logs/access.log 文件-查看nginx的日誌 > > ``` > [root@localhost scripts]# tail -f /usr/local/nginx/logs/a ...
  • ## 跟運維學 Linux - 01 ### 運維的誕生 運維工程師有很多叫法:系統運維、Linux 工程師、系統管理員... `網管`可以說是運維工程師最早的雛形。在個人電腦未普及時,大家去網吧玩游戲。 玩家:“網關,我的電腦上不了網了” 網管負責維修電腦、維修系統、維護網路設備... ### 互 ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202307/3076680-20230717125930891-211733509.png) # 1. 計算同一組或分區的行之間的差 ## 1.1. 最終結果集 ### 1.1.1. sql ```sql D ...
  • 一、DQL介紹 DQL全稱:Data Query Language(數據查詢語言),用來查詢資料庫中表的記錄。 關鍵字:select 二、DQL語法 select 欄位列表 from 表名列表 where 條件列表 group by 分組欄位列表 having 分組後條件列表 order by 排序 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...