我們有以下案例:
我們有一個帶有表的 SQL Server 資料庫
CL_Example和另一個帶有同名視圖的資料庫CL_Example。此視圖是通過使用多個具有內部聯接的表來創建的。CL_Example視圖和CL_Example表的結構是相同的。我們有一個將在這兩個資料庫上執行的 SQL 腳本。如果它發現
CL_Example為表,則應插入資料,如果發現CL_Example為視圖,則不應插入資料。
但是當我們在資料庫 where CL_Exampleis a view上執行腳本時,我們得到以下錯誤:
視圖或函式“dbo.CL_Example”的更新或插入失敗,因為它包含派生或常量欄位。
即使CL_Example視圖所在的資料庫無法訪問插入陳述句,也會生成此錯誤。我們可以禁止這個錯誤并繼續在兩個資料庫中執行腳本嗎?
uj5u.com熱心網友回復:
SQL Server 在執行前會批量編譯所有陳述句。
這將是一個編譯時錯誤并停止批量編譯(參考不存在的物件可能會導致陳述句延遲編譯,它在陳述句執行時再次嘗試,但這不適用于此處)。
如果批處理可能需要運行此類問題陳述句,您需要將它們移動到不同的范圍,以便僅在它們滿足您的控制流條件時才編譯它們。
通常最簡單的方法是將整個問題陳述包裝在 EXEC('')
IF OBJECT_ID('dbo.CL_Example', 'U') IS NOT NULL /*It is a table*/
EXEC('UPDATE dbo.CL_Example ....')
或者sys.sp_executesql如果它不僅僅是一個靜態字串并且您需要將引數傳遞給它,則使用它。
uj5u.com熱心網友回復:
我可以建議另一種方法來解決您的問題。CL_Example您可以在視圖INSTEAD OF INSERT上創建不執行任何操作的觸發器,而不必擔心插入查詢,而不是修復查詢以不插入如果是視圖。
例子:
create view vw_test
as
select 1 as a, 2 as b;
go
select * from vw_test;
go
if (1=2)
begin
insert into vw_test (a,b) values (3,4); -- unreachable but fails
end
go
create trigger tg_fake_insert on vw_test
instead of insert
as
begin
set nocount on;
end;
go
if (1=2)
begin
insert into vw_test (a,b) values (3,4); --unreachable, does not fail
end
else
begin
insert into vw_test (a,b) values (3,4); --actually works
end
go
您甚至可能想在該觸發器中放置一些實際邏輯并將資料轉移到其他地方?
編輯:要額外考慮-如果您使用視圖替換表以使遺留代碼正常作業-您應該處理可能發生的插入/更新/洗掉情況,而這樣做的好方法是使用instead of觸發器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/408474.html
標籤:
