不可不知的小工具-LEN() & DATALENGTH()


前言

今天的內容會接續昨天,所以如果還沒看過前一篇的可以先去看一下[Day24]不可不知的小工具-string.Length。昨天有提到我要匯入資料的時候,在程式面端就已經丟出exception了。今天的前提假設是程式碼端已經通過檢核,要進入寫入資料庫端的階段了。
註: 使用的是T-SQL

一樣先來認識下面幾個東西

NVARCHAR(n)

先來看看微軟文件的說明

可變大小字串資料。 n 會定義字串大小 (以位元組配對為單位),可以是 1 到 4,000 的值。 max 表示儲存體大小上限是 2^31-1 個字元 (2 GB)。 儲存大小是 n 位元組的兩倍 + 2 位元組。 針對 UCS-2 編碼,儲存大小是 n 位元組的兩倍 + 2 位元組,而可存放的字元數目也是 n。 針對 UTF-16 編碼,儲存大小仍是 n 個位元組的兩倍 + 2 個位元組,但可儲存的字元數目可能小於 n

謎之音:你最好是看得懂微軟文件在說什麼????
簡單來說,nvarchar(max)可以儲存大約21億多個字元,也就是說nvarchar(max)大約可以存21億多個字母/標點符號...等。如果套用到昨天的情境來說,nvarchar(500)可以儲存的大小就是1002個位元組,但可能會少於500個字元。順帶一提,SQL Server預設的編碼方式為UTF-16

UTF-16編碼

  • 儲存資料時需要2個位元組(btye)

    在 ASCII 的範圍之上,幾乎所有拉丁語系字集,以及希臘文、斯拉夫、科普特文、亞美尼亞文、希伯來文、阿拉伯文、敘利亞文、它拿文和西非書面文字在 UTF-8 和 UTF-16 中的每個字元都需要 2 個位元組。 在這些案例中,可比較的資料類型 (例如使用 char 或 nchar) 沒有明顯的儲存差異。
    若其內容大部分是東亞字集 (例如韓文、中文和日文),則在 UTF-8 中每個字元都需要 3 個位元組,UTF-16 中則為 2 個位元組。 使用 UTF-16 可提供儲存空間上的優勢。

如果關於nvarchar的內容有大致了解,就讓我們繼續看下去!

LEN()

再來看看微軟文件又說了什麼

傳回指定字串運算式的字元數,但尾端空格不算。

可以講人話嗎....???
意思就是說如果使用LEN()這個函式,會回傳這個字串的字母/符號/空白的數量,但是最後面的空格並不會被算進去。

DATALENGTH()

還是要再來看看微軟文件說了什麼

此函式會傳回用來代表任何運算式的位元組數目。

意思是說DATALENGTH()這個函式回傳的內容是位元數目,而不是字元數目。下面舉例讓大家瞭解一下

舉例

說明: 宣告一個變數,欄位大小開nvarchar(40)。變數內容裡面有6個中文字和2個空白(一個在中間一個在尾端)
用SSMS執行語法實際結果會是
LEN() => 7個字元,6個中文字加上中間一個空白
DATALENGTH() => 16個位元組, (6個中文字)2位元組 + (2個空白) 2位元組
https://ithelp.ithome.com.tw/upload/images/20231009/20162714g65iVmPuVB.jpg

講了這麼多,跟昨天的關聯又在哪裡了???讓我們繼續看下去

回歸正題

先附上我要存進資料庫的內容,已知這段越南文有627個字元,DATALENGTH()結果為1254。資料庫存放該內容的欄位大小是nvarchar(500)
https://ithelp.ithome.com.tw/upload/images/20231009/20162714FMXVpvrMHq.jpg

根據上面的內容,可以知道nvarchar(500)可以存的位元組大小為1002。所以真的要存進資料庫的話,這段內容也是會被截斷。不會完整的被存進資料庫內!

結論

沒有這次的踩雷經驗,真的是不會特別去搜尋這些資訊。找資料過程中還有看到UTF-16、UTF-8...編碼的形式也都會影響。希望這個分享可以幫助到大家~

參考

nchar 和 nvarchar (Transact-SQL)
LEN (Transact-SQL)
DATALENGTH (Transact-SQL)

文章同步發布於:[Day25]不可不知的小工具-LEN() & DATALENGTH()

#t-sql #datalength #len()






你可能感興趣的文章

BERT Pretrained Model

BERT Pretrained Model

[ES6 入門] 解構、展開、剩餘參數

[ES6 入門] 解構、展開、剩餘參數

Day 149

Day 149






留言討論