資料庫繼承早期設計,大量欄位預設值為 NULL,導致應用層頻繁判斷 IS NULL。本文提供動態 T-SQL 腳本,掃描所有使用者資料表的 INT、VARCHAR 欄位,自動為無預設值、非身分識別欄位加上預設值(INT→0、VARCHAR→''),並附帶完整註解與邏輯說明。
-- 1. 收集目標欄位資訊到暫存表變數
DECLARE @t TABLE (
id INT IDENTITY(1,1),
tbname VARCHAR(256),
colname VARCHAR(256),
xtype VARCHAR(20)
);
INSERT INTO @t
SELECT a.name, b.name, c.name
FROM sysobjects a
INNER JOIN syscolumns b ON a.id = b.id
INNER JOIN systypes c ON b.xusertype = c.xusertype
WHERE a.xtype = 'u' -- 使用者資料表
AND c.name IN ('varchar', 'int') -- 僅處理這兩類型
AND b.status <> 0x80 -- 排除身分識別欄位 (IDENTITY)
AND NOT EXISTS ( -- 排除已有預設值的欄位
SELECT 1
FROM (
SELECT (SELECT name FROM sysobjects WHERE id = c.id) AS 表名,
(SELECT name FROM syscolumns WHERE cdefault = a.id) AS 欄位名
FROM sysobjects b, syscolumns c, syscomments a
WHERE b.xtype = 'D' -- DEFAULT 約束
AND a.id = b.id
AND b.parent_obj = c.id
AND a.colid = c.colid
) t
WHERE a.name = t.表名 AND b.name = t.欄位名
);
-- 2. 迴圈逐一建立 DEFAULT 約束
DECLARE @i INT = 1, @max_id INT = (SELECT MAX(id) FROM @t);
DECLARE @tbname VARCHAR(256), @colname VARCHAR(256), @xtype VARCHAR(20), @sql NVARCHAR(4000);
WHILE @i <= @max_id
BEGIN
SELECT @tbname = tbname, @colname = colname, @xtype = xtype FROM @t WHERE id = @i;
SET @sql = 'ALTER TABLE [' + @tbname + '] ADD CONSTRAINT ' +
'df_' + REPLACE(@tbname, '-', '') + '_' + REPLACE(@colname, '-', '') + ' DEFAULT ';
IF @xtype = 'int'
SET @sql = @sql + '0';
ELSE IF @xtype = 'varchar'
SET @sql = @sql + ''''''; -- 空字串
SET @sql = @sql + ' FOR [' + @colname + ']';
PRINT @sql; -- 可先列印檢查,確認無誤再執行 EXEC(@sql)
-- EXEC(@sql);
SET @i = @i + 1;
END
| 步驟 | 目的 | 關鍵系統表/條件 |
|---|---|---|
| 掃描欄位 | 找出所有使用者表的 INT/VARCHAR 欄位 | sysobjects(xtype='U') + syscolumns + systypes |
| 排除 IDENTITY | 避免修改自增欄位導致錯誤 | syscolumns.status <> 0x80 |
| 排除既有 DEFAULT | 避免重複建立約束報錯 | 聯結 sysobjects(xtype='D') + syscomments + syscolumns |
| 動態建構 DDL | 約束命名規則:df_表名_欄位名,移除連字號避免語法錯誤 | REPLACE + QUOTENAME 概念 |
| 型別對應預設值 | INT→0, VARCHAR→'' | 依 xtype 判斷 |
PRINT @sql 檢視產生的 DDL。DATETIME → GETDATE()、BIT → 0、DECIMAL → 0.00。SCHEMA 支援(sysobjects.uid 關聯 sysusers)。善用動態 SQL 批次處理結構變更,能將數天人工作業壓縮為幾分鐘自動化執行,並大幅降低人為疏漏風險。