[英]Select results from stored procedure into a table
我有一個存儲過程, usp_region
,它有一個 select 語句,其中 50 列作為結果集。 此過程由我們應用程序中的多個其他存儲過程調用。
大多數存儲過程將參數傳遞給該過程並顯示它返回的結果集。 我有一個存儲過程usp_calculatedDisplay
,它從此存儲過程中獲取列並將值插入到臨時表中,並對列進行更多計算。
這是usp_calculatedDisplay
中的一部分代碼。
Begin Procedure
/* some sql statements */
Declare #tmptable
(
-- all the 50 columns that are returned from the usp_region procedure
)
Insert Into #tmptable
exec usp_region @regionId = @id
Select t.*, /* a few calculated columns here */
From #tmptable t
End of procedure
每次我向usp_region
過程添加一列時,我還必須確保必須將其添加到此過程中。 否則它會破裂。 維護它變得很困難,因為當將列添加到usp_region
usp_calculatedDisplay
。
為了克服這個問題,我決定這樣做:
Select *
Into #tmptable
From OPENROWSET('SQLNCLI',
'Server=localhost;Trusted_Connection=yes;',
'EXEC [dbo].[usp_region]')
問題是“臨時分布式查詢”組件已關閉。 所以我不能用這種方法來克服這個問題。 我想知道是否有任何其他方法可以克服這個問題。 我真的很感激任何幫助。 謝謝!
每次我向 usp_region 過程添加一列時
SQL 服務器是一個結構化的數據庫,它並不意味着解決您需要每天更改結構的情況。
如果您經常添加/刪除列,那么您可能沒有選擇正確的數據庫類型,您最好重新設計您的系統。
維護它變得很困難,因為當將列添加到 usp_region 時,很可能有人會錯過將列添加到 usp_calculatedDisplay 過程。
有兩個簡單的解決方案(1)使用 DDL 觸發器 - 非常糟糕的想法,但易於實現和工作。 (2) 使用我的技巧select from stored procedure
您可以自動化整個過程並在每次更改存儲過程 usp_region 時更改存儲過程 usp_calculatedDisplay
https://docs.microsoft.com/en-us/sql/relational-databases/triggers/ddl-triggers
基本方法是
CREATE OR ALTER TRIGGER NotGoodSolutionTrig ON DATABASE FOR ALTER_PROCEDURE AS BEGIN
DECLARE @var_xml XML = EVENTDATA();
IF(
@var_xml.value('(EVENT_INSTANCE/DatabaseName)[1]', 'sysname') = 'tempdb'
and
@var_xml.value('(EVENT_INSTANCE/SchemaName)[1]', 'sysname') = 'dbo'
and
@var_xml.value('(EVENT_INSTANCE/ObjectName)[1]', 'sysname') = 'usp_region'
)
BEGIN
-- Here you can parse the text of the stored procedure
-- and execute ALTER on the first SP
-- To make it simpler, you can design the procedure usp_region so the columns names will be in specific row or between to comment which will help us to find it
-- The code of the Stored Procedure which you need to parse is in the value of:
-- @var_xml.value('(EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)'))
-- For example we can print it
DECLARE @SP_Code NVARCHAR(MAX)
SET @SP_Code = CONVERT(NVARCHAR(MAX), @var_xml.value('(EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)'))
PRINT @SP_Code
-- In your case, you need to execute ALTER on the usp_calculatedDisplay procedure using the text from usp_region
END
END
這是獲得所需內容的簡單直接的方法。
CREATE OR ALTER PROCEDURE usp_calculatedDisplay AS
-- Option: using simple table, so it will exists outsie the scope of the dynamic query
DROP TABLE IF EXISTS MyTable;
DECLARE @sqlCommand NVARCHAR(MAX)
select @sqlCommand = 'CREATE TABLE MyTable(' + STRING_AGG ([name] + ' ' + system_type_name, ',') + ');'
from sys.dm_exec_describe_first_result_set (N'EXEC usp_region', null,0)
PRINT @sqlCommand
EXECUTE sp_executesql @sqlCommand
INSERT MyTable EXECUTE usp_region;
SELECT * FROM MyTable;
GO
筆記!!! 不建議在生產中使用這兩種解決方案。 我的建議是通過重新設計系統來避免這種需求。 如果你需要重寫 20 SP 就這樣做,不要偷懶。 您的目標應該是最適合數據庫使用的目標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.