下面的代碼執行在SQL Server有沒有辦法讓SQL服務器驗證存儲過程中的對象引用?
create proc IamBrokenAndDontKnowIt as
select * from tablewhichdoesnotexist
當然很好,如果我嘗試運行它,它失敗
無效的對象名稱tablewhichdoesnotexist「。
有什麼方法可以編譯或驗證存儲過程是否有效?
下面的代碼執行在SQL Server有沒有辦法讓SQL服務器驗證存儲過程中的對象引用?
create proc IamBrokenAndDontKnowIt as
select * from tablewhichdoesnotexist
當然很好,如果我嘗試運行它,它失敗
無效的對象名稱tablewhichdoesnotexist「。
有什麼方法可以編譯或驗證存儲過程是否有效?
我剛剛發現VS2010與數據庫項目將做語法和名稱引用檢查。看起來像最好的選擇。
您可以運行sp_depends
(請參閱http://msdn.microsoft.com/en-us/library/ms189487.aspx)並使用該信息查詢信息模式(http://msdn.microsoft.com/en-us/library/ms186778.aspx)以查看是否存在所有對象。從我在這裏讀到的(http://msdn.microsoft.com/en-us/library/aa214346(SQL.80).aspx)你只需要檢查參考表,這是可行的。
您可以使用
SET FMTONLY ON
EXEC dbo.My_Proc
SET FMTONLY OFF
你需要捕獲錯誤(S)不知何故,但它不應該花太多放在一起快速的實用程序,利用這個查找存儲無效程序。
我還沒有廣泛使用過,所以我不知道是否有任何副作用需要注意。
沒有。它將返回空結果集和任何更新/插入/等。將不會運行。我也只是在DDL(DROP TABLE)上運行了一個快速測試,並且使用了動態SQL,這兩者都沒有運行。 UPDATE語句剛剛返回了受影響的0行的計數。 – 2010-01-06 19:01:06
當您嘗試創建類似的存儲過程時,您曾經收到警告消息。它會說:
無法將行添加到當前存儲過程的sysdepends,因爲它取決於缺少的對象'dbo.nonexistenttable'。存儲過程仍將被創建。
出於某種原因,我現在還沒有得到它,我不確定它是否已被更改,或者只是有一些設置可以打開或關閉警告。無論如何,這應該讓你知道這裏發生了什麼。
SQL服務器確實跟蹤依賴,但實際存在只依賴這。遺憾的是,沒有任何依賴性技巧像sp_depends
或sp_MSdependencies
可以在此工作,因爲您正在尋找缺少依賴關係。
即使我們可以假設想出一個方法來檢查這些缺少的依賴關係,它仍然是微不足道的編造的東西打敗檢查:
CREATE PROCEDURE usp_Broken
AS
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM NonExistentTable'
EXEC sp_executesql @sql
您也可以嘗試解析像表達式「從xxx」,但它很容易打敗它:
真的是沒有任何可靠的方法來檢查一個存儲過程,檢查缺失的依賴關係,而不實際運行它。
您可以使用SET FMTONLY ON
作爲Tom H的提及,但請注意,這會改變過程「運行」的方式。它不會抓住一些東西。舉例來說,並沒有什麼東西寫這樣的程序阻止你:
CREATE PROCEDURE usp_Broken3
AS
DECLARE @TableName sysname
SELECT @TableName = Name
FROM SomeTable
WHERE ID = 1
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM ' + @TableName
EXEC sp_executesql @sql
讓我們假設你有一個名爲SomeTable
一個真正的表和一個真正的一行ID = 1
,但有Name
不涉及任何表。如果將其包裝在SET FMTONLY ON/OFF
塊中,則不會從此中獲得任何錯誤。
這可能是一個人爲的問題,但FMTONLY ON
做其他奇怪的事情一樣執行的IF
/THEN
/ELSE
塊,這可能會導致其他意外錯誤的每一個分支,所以你必須要非常具體與您的錯誤處理。
唯一的測試過程真正可靠的方法是實際運行它,就像這樣:
BEGIN TRAN
BEGIN TRY
EXEC usp_Broken
END TRY
BEGIN CATCH
PRINT 'Error'
END CATCH
ROLLBACK
這個腳本會在一個事務中運行的程序,採取錯誤的一些操作(在CATCH
)並立即回滾交易。當然,即使這可能會有一些副作用,如更改IDENTITY
種子(如果它插入到表中)(成功)。只是要注意的事情。
說實話,我不會用50英尺的杆子碰這個問題。
afaik只有當一個sp調用另一個(不存在)sp時,纔會收到警告。如果不存在表格或視圖,我從來沒有看到過此警告。 – devio 2010-01-06 19:18:44
否(但看下去,看到最後一行)
Erland Sommarskog提出了一個MS Connect爲SET STRICT_CHECKS ON
連接請求有一個workaround(沒有嘗試過我自己):
使用檢查執行計劃。唯一 弱點是,你可能需要 權限查看執行計劃 第一
你可以檢查INFORMATION_SCHEMA.TABLES檢查表是否存在或不是,然後執行代碼
這裏是快速斜背功能檢查
create function fnTableExist(@TableName varchar(64)) returns int as
begin
return (select count(*) from information_schema.tables where [email protected] and Table_type='Base_Table')
end
go
if dbo.fnTableExist('eObjects') = 0
print 'Table exist'
else
print 'no suchTable'
喜歡聰明人,你可以在
檢查存儲特效的所有腦幹/功能210.INFORMATION_SCHEMA.ROUTINES.Routine_name對日的存儲過程/函數的名稱
在SQL 2005或更高版本,可以使用交易測試存儲過程和try/catch:
BEGIN TRANSACTION
BEGIN TRY
EXEC (@storedproc)
ROLLBACK TRANSACTION
END TRY
BEGIN CATCH
WHILE @@TRANCOUNT > 0
ROLLBACK
END CATCH
的算法測試數據庫中的所有存儲過程有點複雜,因爲如果有許多SP返回許多結果集,則需要解決SSMS限制。看我的blog for complete solution。
我認爲sp_depends只適用於實際存在的對象。在我的服務器上進行的快速測試顯示,當我引用無效的表時,沒有報告相關性。 – 2010-01-06 18:32:09
Tom H.謝謝。我想我應該測試它而不是假設。對不起,紅鯡魚。 – 2010-01-06 19:06:56