首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

跟我學 MS SQL Server(六):字串資料類型完整指南 — CHAR、VARCHAR、NCHAR、NVARCHAR、MAX 型別

     編輯:關於SqlServer

一、SQL-92 字串類型標準與 SQL Server 實作對照

標準類型語法SQL Server 2005/2008+儲存特性最大長度
CHARACTER / CHAR`CHAR(n)``CHAR(n)`固定長度,空白填充8,000 位元組
CHARACTER VARYING / VARCHAR`VARCHAR(n)``VARCHAR(n)`變動長度,實際長度+2位元組8,000 位元組
NATIONAL CHARACTER / NCHAR`NCHAR(n)``NCHAR(n)`固定長度 Unicode (UTF-16)4,000 字元
NATIONAL CHARACTER VARYING / NVARCHAR`NVARCHAR(n)``NVARCHAR(n)`變動長度 Unicode4,000 字元
- (大型物件)-`VARCHAR(MAX)` / `NVARCHAR(MAX)`LOB 儲存,溢位頁2^31-1 位元組/字元
- (舊型別)-`TEXT` / `NTEXT`**已棄用**,LOB 指標2^31-1

二、核心儲存機制差異

固定長度 (CHAR/NCHAR)

  • 儲存大小 = `n` 位元組 (CHAR) 或 `n*2` 位元組 (NCHAR)
  • 不足長度以空白 (0x20) 填充,**比較時隱式右補空白**
  • 適合:長度極固定、高頻更新的代碼類欄位 (如 `CHAR(2)` 國家代碼)

變動長度 (VARCHAR/NVARCHAR)

  • 儲存大小 = 實際資料長度 + 2 位元組 (長度前綴)
  • 無填充,**比較時不補空白** (語義長度為準)
  • 適合:長度變化大、平均長度遠小於最大值的欄位

大型物件 (MAX 型別)

  • `VARCHAR(MAX)` / `NVARCHAR(MAX)` / `VARBINARY(MAX)` 取代 `TEXT`/`NTEXT`/`IMAGE`
  • 資料 ≤ 8000 位元組:行內儲存 (In-row)
  • 資料 > 8000 位元組:溢位頁 (LOB_data),行內留 24 位元組根指標
  • 支援所有字串函數、`UPDATE .WRITE()` 部分更新、全文檢索

三、Unicode 與排序規則

  • `NCHAR`/`NVARCHAR` 使用 UTF-16 (每字元 2 位元組,輔助平面 4 位元組)
  • 排序規則決定比較/排序/索引行為:`Latin1_General_CI_AS`、`Chinese_PRC_CI_AS`、`SQL_Latin1_General_CP1_CI_AS`
  • 隱式轉換陷阱:`VARCHAR` 欄位比較 `N'字串'` → 索引失效 (掃描);**永遠用 N 前綴** 對應 Unicode 欄位
  • 資料庫預設排序規則影響 `CHAR`/`VARCHAR`;欄位可覆蓋 `COLLATE`

四、長度參數陷阱:字元 vs 位元組

型別參數 n 代表最大 n實際儲存上限
`CHAR(n)` / `VARCHAR(n)`位元組數8,0008,000 位元組
`NCHAR(n)` / `NVARCHAR(n)`**字元數** (非位元組)4,0008,000 位元組 (4,000 字元 × 2)

常見錯誤:`NVARCHAR(100)` 以為可存 100 位元組,實際可存 100 字元 (中文 100 字,英文 100 字母)。

五、字串函數與運算最佳實踐

操作推薦函數避免/注意
連接`CONCAT()` (2012+) 自動處理 NULL / `+` (舊版)`+` 遇 NULL 結果為 NULL
長度`LEN()` (不含尾空白) / `DATALENGTH()` (位元組數)`LEN` 忽略尾空白,`CHAR` 欄位需 `DATALENGTH`
截取`SUBSTRING` / `LEFT` / `RIGHT`索引 1 起算
修剪`LTRIM`/`RTRIM` / `TRIM` (2017+)`CHAR` 欄位尾空白語義模糊
大小寫`UPPER`/`LOWER`受排序規則影響
替換`REPLACE` / `TRANSLATE` (2017+)`REPLACE` 全掃描,大量資料慎用
模式比對`LIKE` / `PATINDEX`前導萬用字元 `%abc` 導致索引掃描

六、遷移策略:Oracle / MySQL / PostgreSQL → SQL Server

來源型別SQL Server 目標注意事項
Oracle `CHAR(n)` / `VARCHAR2(n)``CHAR(n)` / `VARCHAR(n)`Oracle `VARCHAR2` 語義同 `VARCHAR`;長度單位同為位元組
Oracle `NCHAR` / `NVARCHAR2``NCHAR` / `NVARCHAR`Oracle 字元語義預設,SQL Server 需確認 n 為字元數
Oracle `CLOB` / `NCLOB``VARCHAR(MAX)` / `NVARCHAR(MAX)`LOB 存取 API 差異大,應用層需改寫
MySQL `CHAR` / `VARCHAR` (utf8mb4)`NCHAR` / `NVARCHAR`MySQL `VARCHAR(n)` n 為字元數,映射至 `NVARCHAR(n)`
PostgreSQL `VARCHAR(n)` / `TEXT``NVARCHAR(n)` / `NVARCHAR(MAX)`PostgreSQL 無固定長度型別,`CHAR(n)` 會空白填充

七、效能調優關鍵點

  1. 選擇合適長度:`VARCHAR(100)` vs `VARCHAR(MAX)` — 前者可建立索引、統計資訊更精確、行內儲存
  2. 避免 `CHAR` 存變長資料:空白填充浪費空間,`TRIM` 成本高
  3. Unicode 一致性:全系統統一 `NVARCHAR`,消除隱式轉換導致的索引掃描
  4. 大型字串索引:`VARCHAR(MAX)` **不可**建立標準索引;需全文檢索或計算校驗碼欄位索引
  5. 參數化查詢:`WHERE Name = @Name` 確保 `@Name` 型別與欄位一致 (NVarChar vs VarChar)

八、常見錯誤修正表

錯誤現象根因修正
中文存入 `VARCHAR` 變亂碼編碼頁不支援 Unicode改用 `NVARCHAR`,連線字串無需特殊設定
`WHERE VarcharCol = N'值'` 索引掃描隱式轉換 `VarcharCol` → Unicode參數化傳入 `SqlDbType.VarChar`,或欄位改 `NVARCHAR`
`LEN(CHAR(10))` 回傳 10 即使只存 'A'`CHAR` 尾空白不計入 `LEN`,但 `DATALENGTH` 回傳 10理解語義差異,比較用 `RTRIM` 或改 `VARCHAR`
`VARCHAR(MAX)` 無法建立索引LOB 型別限制改 `VARCHAR(8000)` 或用計算欄位 `CHECKSUM`/`HASHBYTES` 索引

下一篇將講解建立與修改資料表:`CREATE TABLE`、`ALTER TABLE`、`DROP TABLE`、約束條件、索引、身分識別欄位、分區表等 DDL 完整實戰指南。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved