在相容性層級 90 (SQL Server 2005) 的**系統資料庫** (master、model、msdb) 中,建立引用使用者定義函數 (UDF) 的計算欄位會失敗:
CREATE FUNCTION dbo.f_test(@value XML) RETURNS INT
AS BEGIN RETURN @value.value('(//*)[1]', 'int'); END;
CREATE TABLE #t (col1 XML, col2 AS dbo.f_test(col1)); -- 系統資料庫執行
-- Msg 4121, Level 16, State 1: Cannot find either column "dbo" or the user-defined function...
但**使用者資料庫** 與 **tempdb** 正常運作。直接在查詢中呼叫函數 (SELECT dbo.f_test(@x)) 無問題。
USE MyAppDB; -- 而非 master/msdb
CREATE FUNCTION dbo.f_test(@value XML) RETURNS INT ...;
CREATE TABLE MyTable (col1 XML, col2 AS dbo.f_test(col1));
✅ 完全支援、可建立索引 (CREATE INDEX idx_col2 ON MyTable(col2) 將計算欄位具體化)。
CREATE TABLE #t (col1 XML, col2 INT); -- 實體欄位
CREATE TRIGGER trg_t_insupd ON #t
AFTER INSERT, UPDATE AS
BEGIN
UPDATE t SET col2 = dbo.f_test(i.col1)
FROM #t t JOIN inserted i ON t.pk = i.pk;
END;
⚠️ 需手動管理同步、效能較差、增加寫入開銷。
CREATE VIEW dbo.v_test WITH SCHEMABINDING AS
SELECT pk, col1, dbo.f_test(col1) AS col2 FROM dbo.MyTable;
CREATE UNIQUE CLUSTERED INDEX idx_v_test ON dbo.v_test(pk); -- 具體化檢視表
✅ 查詢效能等同索引計算欄位、不佔用基表寫入路徑。
col2,存入實體欄位col2 AS (dbo.f_test(col1)) PERSISTEDMyDB.dbo.f_test** 或同義詞CREATE PRIMARY XML INDEX、SECONDARY XML INDEX) 而非標量 UDF| 版本 | 計算欄位 UDF | PERSISTED | XML 索引 | Generated Columns |
|---|---|---|---|---|
| SQL 2005 | 使用者庫支援 | 支援 | 支援 | 不支援 |
| SQL 2008 | 支援 | 支援 | 增強 | 不支援 |
| SQL 2012+ | 支援 | 支援 | 選擇性 XML 索引 | 不支援 |
| SQL 2022 | 支援 | 支援 | 支援 | 支援 (GENERATED ALWAYS AS) |
結論:請將業務物件置於**使用者資料庫**,善用 PERSISTED 計算欄位與 XML 索引,避開系統資料庫限制區。