2016-05-05 101 views
4

我有一個服務於Web服務調用的過程。這是一個SQL 2012環境。 proc採用存儲過程名稱和任意一組過程參數(用字符串分隔符分隔)。在proc內部我建立如下陳述: -存儲過程默認參數標識

INSERT INTO @Params 
    SELECT p.parameter_id, p.name AS ParameterName, t.name AS ParameterType, p.max_length AS ParameterLength, '' 
    FROM sys.parameters AS p 
    JOIN sys.types AS t ON t.user_type_id = p.user_type_id 
    WHERE object_id = OBJECT_ID(RTRIM(LTRIM(@ProcName))) 

    UPDATE P 
    SET pValue = s.data 
    FROM dbo.split(@ParamList,'ç') as S 
    INNER JOIN @Params as P ON P.id = S.ID 


    SELECT @ParamSplit = ISNULL(Stuff((SELECT ',' + 
     pName + '=' + 
     CASE 
      WHEN pValue = 'ÆNULL' THEN 'NULL' 
      WHEN pType = 'varchar' THEN char(39) + replace(pValue,char(39),char(39) + char(39)) + char(39) 
      WHEN pType = 'date' THEN char(39) + replace(pValue,char(39),char(39) + char(39)) + char(39) 
      WHEN pType = 'datetime' or pType='TIME' THEN char(39) + replace(pValue,char(39),char(39) + char(39)) + char(39) 
      else pValue 
      END 
    FROM @Params 
    FOR XML PATH ('')),1,1,''),'') 

這工作正常。我明白並非所有的數據類型都被檢查過,但爲了我的目的(這是一個封閉的系統),它涵蓋了所有必需的基礎。但我有一個問題,因爲調用服務必須傳遞所有參數,甚至可能在proc中默認的參數。

有一個在sys.parameters表是

has_default_value

和另一場

DEFAULT_VALUE

一個領域,但檢查微軟記錄他們 說: -

默認值記錄在sys.parameters.default列只 CLR過程。對於Transact-SQL 過程參數,該列將爲NULL。

我想要做的是確定如果我調用的proc具有任何默認參數,如果他們這樣做(並且調用服務沒有通過它們)我可以使用默認值,否則這些可以被替換爲無論呼叫服務已通過。

所以...問題 - 有誰知道如何識別proc是否有任何默認參數分配?

+1

到的答案[此問題](http://stackoverflow.com/q/5873731/1048425)包含解析過程定義以檢索默認值的方法。我不確定是否有更乾淨的做法。 – GarethD

+1

你可以:1)創建將攔截CREATE/ALTER過程的DDL觸發器2)解析定義以檢索默認值3)放入擴展屬性4)在你的代碼列表中從sys.parameters中獲取所有參數並獲取默認值來自擴展事件。像** [demo](http://rextester.com/GGXWTY28224)**。完全可以以自動化的方式實現它。如果您在'JSON/XML格式'中有某種文檔作爲註釋,則解析可能更簡單。 – lad2025

+0

這是一個現有的生產數據庫,因此不太實際的打開引擎蓋。我可以查詢有什麼 - 不能真正修改任何特效。我認爲在運行時解析會效率低下(這些過程稱爲很多,每秒可能多次)。我以爲我能做的就是假設如果Web服務沒有通過所有的參數,那麼任何錯過的必須由defaut - 所以proc可以被調用沒有這些參數。我認爲這將起作用... –

回答

0

你可以試試這個,但可能需要檢查您的存儲過程defintions的格式,你可以從你的應用程序和緩存在客戶端調用這個防止性能開銷:

Declare @ProcedureName VARCHAR(50) = 'MySP' 
DECLARE @text VARCHAR(MAX) 
DECLARE @startPos int = 0 
DECLARE @endPos int = 0 

SELECT @text=text FROM syscomments 
WHERE id = object_id(@ProcedureName) and colid=1 AND text LIKE '%(%' 

IF @text IS NULL 
BEGIN 
    -- No Parameters in stored procedure 
    PRINT 'No Parameters' 
END 
ELSE 
BEGIN 

    -- Find Start of parameter declaration 
    SELECT @startPos = PATINDEX('%(%' ,@text) 
    -- Find end of parameter declaration 
    SELECT @endPos = PATINDEX('%AS' + CHAR(13) + '%' ,@text) 

    -- Set Text to our parameters string 
    SELECT @text = SUBSTRING(@text, @startPos + 1, @endpos - @startpos -4) 

    -- Split parameters and insert into table 
    -- Alternatively use other string splitting techniques such as numbers table 
    DECLARE @t1 TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX)) 
    DECLARE @xml XML 
    SET @xml = N'<t>' + REPLACE(@text,',','</t><t>') + '</t>' 
    INSERT INTO @t1(val) 
    SELECT r.value('.','varchar(MAX)') as item 
    FROM @xml.nodes('/t') as records(r) 


    SELECT SUBSTRING(val, PATINDEX('%@%', val), PATINDEX('% %', val) - PATINDEX('%@%', val)) as Parm, 
      SUBSTRING(val, PATINDEX('%=%',val) + 1, DATALENGTH(val) - PATINDEX('%=%',val)) As DefaultValue 
    FROM @t1 
    WHERE val like '%=%' -- Only get parameters with default value 

END