在 SQL Server 2000 中,視圖定義使用 SELECT * 參考另一視圖/資料表,當基礎視圖/資料表欄位順序變更(ALTER VIEW 或 ALTER TABLE)時,上層視圖**不會自動重新綁定欄位對應**,導致資料錯位、型別衝突甚至靜默回傳錯誤結果。
USE Northwind;
GO
-- 基礎視圖:明確列出欄位
CREATE VIEW vCustomersA AS
SELECT CustomerID, CompanyName, ContactName, ContactTitle,
Address, City, Region, PostalCode, Country, Phone, Fax
FROM dbo.Customers;
GO
-- 衍生視圖:使用 SELECT *
CREATE VIEW vCustomersB AS
SELECT * FROM vCustomersA;
GO
-- 測試查詢:正常
SELECT * FROM vCustomersA WHERE CustomerID = 'ALFKI';
SELECT * FROM vCustomersB WHERE CustomerID = 'ALFKI';
-- 兩者結果一致
-- 變更基礎視圖欄位順序:CompanyName 與 ContactName 互換
ALTER VIEW vCustomersA AS
SELECT CustomerID, ContactName, CompanyName, ContactTitle,
Address, City, Region, PostalCode, Country, Phone, Fax
FROM dbo.Customers;
GO
-- 再次查詢:vCustomersB 欄位錯位!
SELECT * FROM vCustomersA WHERE CustomerID = 'ALFKI'; -- 正確
SELECT * FROM vCustomersB WHERE CustomerID = 'ALFKI'; -- CompanyName 欄顯示 ContactName 值
* 展開為當時的欄位清單,並將**欄位序數 (Ordinal Position)** 寫入系統目錄 (syscolumns)。ALTER VIEW 重新編譯基礎視圖,產生新的欄位序數,但**不會級聯更新** 參考它的上層視圖元資料。| 場景 | 是否受影響 | 說明 |
|---|---|---|
| 視圖巢狀參考 (VIEW → VIEW) | ✅ 是 | 最常見,如範例 |
| 視圖參考資料表 (VIEW → TABLE) | ✅ 是 | ALTER TABLE ... ALTER COLUMN 改變順序同樣觸發 |
| 內嵌表值函數 (Inline TVF) | ✅ 是 | 本質上同視圖 |
| SQL Server 2005+ | ❌ 否 | 引入延遲綁定/重新綁定機制,執行時自動解析最新結構描述 |
CREATE VIEW v AS SELECT Col1, Col2, Col3 FROM Table。sp_refreshview / sp_refreshsqlmodule:若必須維護舊系統且無法立即改寫,在 ALTER VIEW 基礎物件後,立即對所有相依視圖執行 EXEC sp_refreshview 'vCustomersB' 強制重新綁定。sp_depends / sys.sql_expression_dependencies) → 批次 sp_refreshview → 迴歸測試。sp_refreshview 實戰-- 取得所有直接/間接參考 vCustomersA 的視圖
SELECT DISTINCT OBJECT_SCHEMA_NAME(referencing_id) + '.' + OBJECT_NAME(referencing_id) AS DependentView
FROM sys.sql_expression_dependencies
WHERE referenced_id = OBJECT_ID('vCustomersA');
-- 動態批次刷新
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += 'EXEC sp_refreshview ''' + OBJECT_SCHEMA_NAME(referencing_id) + '.' + OBJECT_NAME(referencing_id) + ''';'
FROM sys.sql_expression_dependencies
WHERE referenced_id = OBJECT_ID('vCustomersA');
EXEC sp_executesql @sql;
SQL Server 2000 視圖 SELECT * 是定時炸彈:ALTER VIEW/TABLE 靜默破壞上層視圖語義,且無編譯錯誤預警。鐵律:**視圖定義永遠明確列出欄位**,配合 sp_refreshview 自動化腳本,才能在舊版本環境安全演進結構描述。