使用者定義資料類型 (UDT) 一經被資料表參考即無法直接修改或刪除。本文提供標準化的三步驟變更流程:重命名舊型別 → 建立新型別 → 批次 ALTER TABLE 切換欄位型別,並附完整動態 SQL 腳本。
sp_droptype 失敗:訊息 15170,型別已被參考。ALTER TYPE 不支援修改精度/長度 (SQL Server 至 2022 仍不支援)。EXEC sp_rename 'aa', 'aa_bak', 'USERDATATYPE';EXEC sp_addtype 'aa', 'numeric(20,2)', 'not null'; (新精度/長度/NULLability)ALTER TABLE ... ALTER COLUMN ... 陳述式逐表執行。
-- 參數區:請修改以下三個變數
DECLARE @OldTypeName SYSNAME = 'aa'; -- 舊 UDT 名稱
DECLARE @NewTypeDef NVARCHAR(256) = 'numeric(20,2)'; -- 新型別定義
DECLARE @Nullability NVARCHAR(10) = 'NOT NULL'; -- NULL/NOT NULL
-- 1. 重命名舊型別
EXEC sp_rename @OldTypeName, @OldTypeName + '_bak', 'USERDATATYPE';
-- 2. 建立新型別
DECLARE @CreateTypeSQL NVARCHAR(MAX) =
N'EXEC sp_addtype @typename = ' + QUOTENAME(@OldTypeName, '''') +
N', @phystype = ' + QUOTENAME(@NewTypeDef, '''') +
N', @nulltype = ' + QUOTENAME(@Nullability, '''') + N';';
EXEC sp_executesql @CreateTypeSQL;
-- 3. 批次 ALTER TABLE 切換欄位型別
DECLARE @SQL NVARCHAR(MAX) = N'';
SELECT @SQL += N'
ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) + N'
ALTER COLUMN ' + QUOTENAME(c.name) + N' ' + @NewTypeDef + N' ' + @Nullability + N';'
FROM sys.columns c
JOIN sys.objects o ON c.object_id = o.object_id
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE t.name = @OldTypeName + '_bak' -- 找出仍使用舊型別的欄位
AND o.type = 'U'; -- 僅使用者資料表
-- 列印並執行 (大量資料表建議分批執行並監控記錄檔)
PRINT @SQL;
-- EXEC sp_executesql @SQL; -- 確認無誤後取消註解執行
| 情境 | 處理方式 |
|---|---|
| 欄位有預設值/條件約束 | ALTER COLUMN 會自動保留 DEFAULT/CHECK,但建議先腳本備份再執行 |
| 欄位為索引鍵/外鍵 | 若精度變更不影響資料完整性可直接執行;否則需先卸除索引/FK 再重建 |
| 大量資料表 (億級資料列) | ALTER COLUMN 為大小 metadata-only 作業 (SQL 2016+),極快;舊版需重建資料表,請排在維護窗口並啟用線上索引重建 |
| 複寫/CDC/變更追蹤啟用 | 需先停用相關功能,變更後重新啟用並重新初始化訂閱 |
| 跨資料庫參考 | 各資料庫需分別執行相同流程 |