﻿# T-SQL 技巧：產生「固定長度前面補零的數字字串」

今天看到一則 T-SQL 語法，是用來產生**固定長度前面補零的數字字串**，例如你拿到一個數值為 123 而你要將其數字轉成 00000123 的字串格式，我剛看到這個語法突然楞了一下，因為看到一個我沒用過的 [POWER](http://msdn.microsoft.com/zh-TW/library/ms174276.aspx) 函式，我看到這串 T-SQL 後突然聞到一點點怪怪的味道，因此寫出了幾個不同的版本，各位可以參考參考。

以下是我今天看到的寫法：

-   先將算出 10 的 8 次方 ( 10^8 )
-   然後加上原本的數字 @Number
-   將**運算的結果(float)**轉型成 varchar(9) 字串
-   最後從右邊算起取 8 個字元

針對效能的判斷：

-   因為 [POWER](http://msdn.microsoft.com/zh-TW/library/ms174276.aspx) 函式把原本 int 數字型別轉型為 float 型別，較佔記憶體空間
-   數字轉型 2 次 ( int –> float , float –> varchar )
-   字串函式處理 1 次

```sql
DECLARE @Number INT = 123

DECLARE @Digits INT = 8

DECLARE @Result CHAR(8)

-- 第一種

SELECT @Result =
    RIGHT(
        CAST(
            POWER(10, @Digits) + @Number
            AS VARCHAR(9))
        , @Digits)

SELECT @Result
```

\---

好奇的我我自己重寫如下：

-   將原本的數字 @Number 轉型成 varchar(8) 後算出資料的長度 ( 注意：不能用 nvarchar 喔!! )
-   再用 [REPLICATE](http://msdn.microsoft.com/zh-tw/library/ms174383.aspx) 函式產生特定數量的 '0'
-   最後再加上原本的數字 @Number 轉型成 varchar(8) 後的字串

針對效能的判斷：

-   數字轉型 2 次 ( int –> varchar )  → 若多新增一組變數可省去 1 次數值轉型的負擔
-   數值函式處理 1 次 ( DATALENGTH )
-   字串函式處理 1 次 ( REPLICATE )
-   字串相加 1 次

```sql
DECLARE @Number INT = 123

DECLARE @Digits INT = 8

DECLARE @Result CHAR(8)

-- 第二種

SELECT @Result =
	REPLICATE('0', 
		@Digits - DATALENGTH(CAST(@Number AS VARCHAR(8)))) +
	CAST(@Number as VARCHAR(8))
	
SELECT @Result
```

\---

最後我到[噗浪](http://www.plurk.com/p/5a1zjl "連結")上詢問網友的看法，果然由 [Sean](http://www.plurk.com/Seanamph "Sean") 提供了一個更直覺的寫法：

-   用 [REPLICATE](http://msdn.microsoft.com/zh-tw/library/ms174383.aspx) 函式產生固定位數 (@Digits) 的 '0'
-   將 @Number 轉型成 varchar 字串 (不指定長度)
-   最後從右邊算起取 8 個字元

針對效能的判斷：

-   數字轉型 1 次 ( int –> varchar )
-   字串函式處理 2 次 ( REPLICATE + RIGHT )
-   字串相加 1 次

```sql
DECLARE @Number INT = 123

DECLARE @Digits INT = 8

DECLARE @Result CHAR(8)

-- 第三種

SELECT @Result =
	RIGHT(
		REPLICATE('0', @Digits) + CAST(@Number as VARCHAR)
		, @Digits)

SELECT @Result
```

\---

我不敢說以上三種寫法哪個是好、哪個是壞，在效能上應該不會差多少，畢竟這並非頻繁執行的 T-SQL 語法，但如果以「可讀性」來看，我應該會選擇第三種寫法。

除此之外，[網路上也有人(Daniel Read)提供一個寫好的 Function 可供使用](https://web.archive.org/web/20070307135307/http://www.developerdotstar.com:80/community/node/319)，感覺也不錯，當 Function 建立好之後，只要輸入以下 T-SQL 就可以完成使命，可讀性超高！ ^\_^

```
SELECT dbo.fnPadLeft('0', 8, 123)
```

**相關連結**

-   [SQL Server T-SQL LPAD & RPAD Functions (String Padding Equivalent to PadLeft & PadRight)](https://web.archive.org/web/20070307135307/http://www.developerdotstar.com:80/community/node/319)
-   [REPLICATE (Transact-SQL)](http://msdn.microsoft.com/zh-tw/library/ms174383.aspx)
-   [CAST 和 CONVERT (Transact-SQL)](http://msdn.microsoft.com/zh-tw/library/ms187928.aspx)
