簡體   English   中英

Select 從存儲過程到表的結果

[英]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

選項 1:使用 DDL 觸發器

您可以自動化整個過程並在每次更改存儲過程 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

選項 2:使用 sys.dm_exec_describe_first_result_set 從存儲過程到 select 的技巧

這是獲得所需內容的簡單直接的方法。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM