需求:將 `125 / 60.00 = 2.083333...` 小時在 DataGrid 中僅顯示 `2.08` (保留兩位小數)。本文彙整三大主流解法:**SQL 查詢端格式化**、**DataGrid 繫結屬性格式化**、**ItemDataBound 事件程式化控制**,並比較優劣適用場景。
| 語法 | 範例 | 結果 | 適用資料庫 |
|---|---|---|---|
| `ROUND(value, 2)` | `SELECT ROUND(125/60.00, 2)` | `2.08` | SQL Server, Oracle, MySQL, PostgreSQL |
| `CAST(value AS DECIMAL(18,2))` | `SELECT CAST(125/60.00 AS DECIMAL(18,2))` | `2.08` | 標準 SQL (所有主流 DB) |
| `CONVERT(DECIMAL(18,2), value)` | `SELECT CONVERT(DECIMAL(18,2), 125/60.00)` | `2.08` | SQL Server, Sybase |
| `FORMAT(value, 'N2')` | `SELECT FORMAT(125/60.00, 'N2')` | `2.08` (字串) | SQL Server 2012+ |
| `TRUNCATE(value, 2)` | `SELECT TRUNCATE(125/60.00, 2)` | `2.08` (直接截斷) | MySQL, PostgreSQL |
**優點**:資料傳輸量小、前端無需額外處理、報表匯出一致。
**缺點**:精度在資料庫端截失、不同 DB 語法不一、排序/篩選可能受影響。
<asp:DataGrid ID="DataGrid1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn
DataField="Hours"
HeaderText="工時"
DataFormatString="{0:F2}"
HtmlEncode="False" />
<!-- F2 = 固定兩位小數;N2 = 含千分位分隔符 -->
</Columns>
</asp:DataGrid>
**常用格式字串**:
| 格式 | 說明 | 範例 (1234.567) |
|---|---|---|
| `{0:F2}` | 固定 2 位小數 | `1234.57` |
| `{0:N2}` | 含千分位、2 位小數 | `1,234.57` |
| `{0:C2}` | 貨幣格式 (依文化特性) | `$1,234.57` / `NT$1,234.57` |
| `{0:P2}` | 百分比、2 位小數 | `123,456.70 %` |
| `{0:#.##}` | 最多 2 位小數 (尾端 0 不顯示) | `1234.57` / `1234.5` / `1235` |
protected void DataGrid1_ItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// 假設 Hours 在第 2 欄 (索引 1)
decimal hours = Convert.ToDecimal(DataBinder.Eval(e.Item.DataItem, "Hours"));
e.Item.Cells[1].Text = hours.ToString("F2"); // 或 N2, C2...
// 進階:依條件動態格式
if (hours > 100)
e.Item.Cells[1].CssClass = "overtime-highlight";
}
}
**優點**:可依資料值動態決定格式、加 CSS Class、加圖示、甚至改寫整個 Cell 內容。
**缺點**:需寫代碼、效能略低於宣告式、維護成本較高。
| 維度 | SQL 端 | DataFormatString | ItemDataBound |
|---|---|---|---|
| 實作難度 | 低 (改 SQL) | 極低 (屬性設定) | 中 (寫事件代碼) |
| 維護性 | 分散在 SQL/SP | 集中在 ASPX | 集中在 CodeBehind |
| 資料精度保留 | **截失** (DB 端已四捨五入) | **保留** (原始值在 DataItem) | **保留** |
| 匯出 Excel/CSV 一致性 | 自動一致 | 需額外處理 (匯出時重新格式化) | 需額外處理 |
| 跨資料庫可移植 | 語法不同 | **完全相容** | **完全相容** |
| 動態條件格式化 | 困難 (CASE WHEN) | 不支援 | **完美支援** |
| 效能 | 最好 (DB 端完成) | 極佳 (框架內建) | 略低 (反射/轉型) |
需要在匯出/報表/下游系統保持原始精度?
├─ 是 → 勿在 SQL 端截斷,改用 DataFormatString 或 ItemDataBound
└─ 否 →
需要動態條件格式 (如負數紅字、超標高亮)?
├─ 是 → ItemDataBound
└─ 否 → DataFormatString (最簡潔、零代碼、效能佳)
@* Razor Pages / MVC *@
<td>@Model.Hours.ToString("F2")</td>
<td>@String.Format("{0:F2}", Model.Hours)</td>
@* Blazor *@
<td>@hours.ToString("F2")</td>
@* JavaScript (客戶端) *@
cell.textContent = hours.toFixed(2); // 或 toLocaleString(undefined, {minimumFractionDigits: 2})
小數位數控制看似微不足道,卻關係到**資料精度保真、跨層一致性、國際化支援、維護成本**。掌握三大方案優劣,依據「精度保留需求、動態格式化需求、團隊技術棧」三角決策,才能在專案中建立統一、可擴充的格式化規範。