2013-02-01 33 views
9

如果SP的參數具有默認值,是否有任何方法可以從SQL Server內部(我在2012年的FYI中)確定?有otherthreads對此,但是這些建議似乎並沒有準確地給我這些信息。確定SP參數在T-SQL中是否有缺省值

這是我試過的一些事情;

select * 
from sys.objects so join sys.parameters sp on so.object_id = sp.object_id 
where so.type='P' 
and so.name = 'someSp' 

上面的查詢返回一個數字,聽起來像我吠叫右樹(has_default_value,DEFAULT_VALUE其中)列這些似乎並沒有改變我是否有一個默認值我的SP還是不是。 (has_default的值始終爲0,default_value的值始終爲空)

exec sp_sproc_columns 'someSp' 

相同的交易;上面的SP返回一些列,包括NULLABLE和IS_NULLABLE;無論我的SP內容如何,​​NULLABLE總是等於1,IS_NULLABLE = YES。

注意; SQL Server管理工作室清楚地顯示與每個SP參數關聯的元數據。

Management Studio SP Parameter MetaData

我使用SQL Profiler來檢查的時候我在Management Studio的對象資源管理器查看SP的參數會發生什麼。展開參數文件夾時,有兩個查詢運行。第一個查詢在這裏粘貼有點長(儘管如果有幫助,我會這樣做)。它包含一個名爲DEFAULT VALUE的列;但據我所知,它總是NULL。第二個查詢只是返回SP的主體;據推測輸出到文本編輯器窗口(雖然恐怕可能有一些解析發生在mgmt工作室!)

僅供參考/只是爲了確保我不失去我的彈珠我創造了兩個毫無意義的Sps只是爲了測試。它們看起來像:

CREATE PROCEDURE TestDefaultSpValue_Default 
@I   INT = 2 
AS 
BEGIN 
SET NOCOUNT ON; 
SELECT @I 
END 

CREATE PROCEDURE TestDefaultSpValue_NoDefault 
@I   INT 
AS 
BEGIN 
SET NOCOUNT ON; 
SELECT @I 
END 
+0

嘗試sp_procedure_params_rowset 如在此鏈接建議 - http://social.msdn.microsoft。com/forums/zh-CN/transactsql/thread/900756fd-3980-48e3-ae59-a15d7fc15b4c/ –

+0

感謝您的快速響應。沒有骰子我害怕,sp_procedure_params_rowset'TestDefaultSpValue_Default' sp_procedure_params_rowset'TestDefaultSpValue_NoDefault'返回相同的列和值。 –

+0

正如此鏈接中所述,http://msdn.microsoft.com/zh-cn/library/ms176074.aspx,SQL Server僅在此目錄視圖中爲CLR對象維護默認值;因此,對於Transact-SQL對象,此列的值爲0。要查看Transact-SQL對象中參數的默認值,請查詢sys.sql_modules目錄視圖的定義列,或使用OBJECT_DEFINITION系統函數。 –

回答

1

MS SQL僅存儲默認設置爲CLR存儲過程和函數,所以在這種情況下唯一的方法是解析對象定義。 要運行該示例,您可以創建一個空白存儲過程或採取其他任何方式。

ALTER PROCEDURE dbo.usp_test1 
(
    @a UNIQUEIDENTIFIER = NULL, 
    @b DATETIME = '20100101', 
    @c DATETIME = DEFAULT, 
    @d BIT = 1, 
    @e BIT, 
    @k INT = 1, 
    @f BIT = 0, @g NVARCHAR(MAX) = '23235', 
    @h INT = 3, 
    @j DECIMAL(10,2) = DEFAULT 
) 
WITH RECOMPILE 
AS 
BEGIN 

    PRINT 1; 

END 

默認值的存儲過程,該查詢返回列表:

SELECT 
     data3.name 
    , [default_value] = REVERSE(RTRIM(SUBSTRING(
      data3.rtoken 
     , CASE 
      WHEN CHARINDEX(N',', data3.rtoken) > 0 
       THEN CHARINDEX(N',', data3.rtoken) + 1 
      WHEN CHARINDEX(N')', data3.rtoken) > 0 
       THEN CHARINDEX(N')', data3.rtoken) + 1 
      ELSE 1 
      END 
     , LEN(data3.rtoken) 
    ))) 
FROM (
    SELECT 
      data2.name 
     , rtoken = REVERSE(
      SUBSTRING(ptoken 
        , CHARINDEX('=', ptoken, 1) + 1 
        , LEN(data2.ptoken)) 
       ) 
    FROM (
     SELECT 
       data.name 
      , ptoken = SUBSTRING(
        data.tokens 
       , token_pos + name_length + 1 
       , ISNULL(ABS(next_token_pos - token_pos - name_length - 1), LEN(data.tokens)) 
      ) 
     FROM (
      SELECT 
        sm3.tokens 
       , p.name 
       , name_length = LEN(p.name) 
       , token_pos = CHARINDEX(p.name, sm3.tokens) 
       , next_token_pos = CHARINDEX(p2.name, sm3.tokens) 
      FROM (
       SELECT 
         sm2.[object_id] 
        , sm2.[type] 
        , tokens = REVERSE(SUBSTRING(sm2.tokens, ISNULL(CHARINDEX('SA', sm2.tokens) + 2, 0), LEN(sm2.tokens))) 
       FROM (
        SELECT 
          sm.[object_id] 
         , o.[type] 
         , tokens = REVERSE(SUBSTRING(
             sm.[definition] 
            , CHARINDEX(o.name, sm.[definition]) + LEN(o.name) + 1 
            , ABS(CHARINDEX(N'AS', sm.[definition])) 
           ) 
         ) 
        FROM sys.sql_modules sm WITH (NOLOCK) 
        JOIN sys.objects o WITH (NOLOCK) ON sm.[object_id] = o.[object_id] 
        JOIN sys.schemas s WITH (NOLOCK) ON o.[schema_id] = s.[schema_id] 
        WHERE o.[type] = 'P ' 
         AND s.name + '.' + o.name = 'dbo.usp_test1' 
       ) sm2 
       WHERE sm2.tokens LIKE '%=%' 
      ) sm3 
      JOIN sys.parameters p WITH (NOLOCK) ON sm3.[object_id] = p.[object_id] 
      OUTER APPLY (
       SELECT p2.name 
       FROM sys.parameters p2 WITH (NOLOCK) 
       WHERE p2.is_output = 0 
        AND sm3.[object_id] = p2.[object_id] 
        AND p.parameter_id + 1 = p2.parameter_id 
      ) p2 
      WHERE p.is_output = 0 
     ) data 
    ) data2 
    WHERE data2.ptoken LIKE '%=%' 
) data3 

而且此查詢,就可以知道,如果存儲過程包含任何默認值:

DECLARE @name SYSNAME = 'dbo.usp_test1' 

IF EXISTS(
    SELECT 1 
    FROM (
     SELECT 
       sm2.[object_id] 
      , tokens = SUBSTRING(sm2.tokens, ISNULL(CHARINDEX('SA', sm2.tokens) + 2, 0), LEN(sm2.tokens)) 
     FROM (
      SELECT 
        sm.[object_id] 
       , tokens = REVERSE(SUBSTRING(
           sm.[definition] 
          , CHARINDEX(o.name, sm.[definition]) + LEN(o.name) + 1 
          , ABS(CHARINDEX(N'AS', sm.[definition])) 
         ) 
       ) 
      FROM sys.sql_modules sm WITH (NOLOCK) 
      JOIN sys.objects o WITH (NOLOCK) ON sm.[object_id] = o.[object_id] 
      JOIN sys.schemas s WITH (NOLOCK) ON o.[schema_id] = s.[schema_id] 
      WHERE o.[type] = 'P ' 
       AND s.name + '.' + o.name = @name 
     ) sm2 
    ) sm3 
    WHERE sm3.tokens LIKE '%=%' 
) PRINT @name + ' have default values' 
+0

失敗,因爲您可以在數據類型定義之前擁有一個AS。 –

+0

這個查詢以各種方式失敗,它也報告誤報... –

1

如果參數名稱有「AS」符號 - 不起作用 請嘗試我的

create procedure ViewParameters 
    @procedure varchar(50) 
as 
    declare 
     @w varchar(max), 
     @p int, @p2 int, 
     @t varchar(max) 


    /* Andrey Rubanko 18 jul 2013 */ 

    /* fill temporary table with procedure body */ 

    select @w = definition 
    from sys.sql_modules 
    where object_id = object_id(@procedure) 

    declare @lines table (line varchar(500), id int identity(1, 1)) 

    while len(@w) > 0 begin 
     set @p = charindex(char(10), @w) 
     if @p > 0 begin 
      insert @lines(line) values(replace(replace(SUBSTRING(@w, 1, @p - 1), char(13), ''), char(9), ' ')) 
      set @w = SUBSTRING(@w, @p + 1, 10000) 
     end else begin 
      insert @lines(line) values(replace(@w, char(13), '')) 
      set @w = '' 
     end 
    end 



    /* remove comments */ 

    declare 
     @i int, 
     @inCommentNow bit, 
     @again bit 

    set @i = 1 
    set @inCommentNow = 0 

    while @i <= (select max(id) from @lines) begin 
     select @w = line from @lines where id = @i 
     set @again = 0 

     if @inCommentNow = 0 begin 
      set @p = patindex('%--%', @w) 
      if @p > 0 begin 
       set @w = SUBSTRING(@w, 1, @p - 1) 

       update @lines 
       set line = @w 
       where id = @i 

      end 

      set @p = patIndex('%/*%', @w) 
      if @p > 0 begin 
       set @p2 = PATINDEX('%*/%', @w) 
       if @p2 > 0 begin 
        update @lines 
        set line = substring(@w, 1, @p - 1) + SUBSTRING(@w, @p2 + 2, 10000) 
        where id = @i 

        set @again = 1 
       end else begin 
        set @inCommentNow = 1 

        update @lines 
        set line = SUBSTRING(@w, 1, @p - 1) 
        where id = @i 
       end 
      end 
     end 

     if @inCommentNow = 1 begin 
      set @p = PATINDEX('%*/%', @w) 
      if @p > 0 begin 
       update @lines 
       set line = SUBSTRING(@w, @p + 2, 10000) 
       where id = @i 

       set @inCommentNow = 0 
       set @again = 1 
      end else 
       update @lines 
       set line = '' 
       where id = @i 
     end 

     if @again = 0 
      set @i = @i + 1 
    end 


    /* remove all except parameters */ 
    declare 
     @first int, 
     @last int 

    set @i = 1 

    while @last is null begin 
     select @w = line from @lines where id = @i 

     if SUBSTRING(@w, 1, 2) = 'as' 
      set @last = @i - 1 

     set @p = PATINDEX('% as%', @w) 
     if @last is null and @p > 0 begin 
      set @w = SUBSTRING(@w, 1, @p - 1) 

      update @lines 
      set line = @w 
      where id = @i 

      if charindex('@', @w) > 0 
       set @last = @i 
      else 
       set @last = @i - 1 
     end 


     set @p = CHARINDEX('@', @w) 
     if @first is null and @p > 0 begin 
      set @first = @i 
      set @w = SUBSTRING(@w, @p, 10000) 
     end 

     set @i = @i + 1 
    end 

    delete @lines 
    where @first is null 
     or id < @first 
     or id > @last 



    /* decode lines to paramters */ 

    declare @par table (ParameterName varchar(50), ParameterType varchar(50), DefaultValue varchar(50)) 

    declare 
     @name varchar(50), 
     @type varchar(50), 
     @default varchar(50) 

    declare c cursor for 
     select line 
     from @lines 
    open c 
    fetch next from c into @w 
    while @@FETCH_STATUS = 0 begin 
     while len(@w) > 0 begin 
      set @default = null 

      set @w = SUBSTRING(@w, charindex('@', @w) + 1, 10000) 
      set @p = CHARINDEX(',', @w) 
      print 'start:' + @w 
      if @p > 0 begin 
       set @t = SUBSTRING(@w, 1, @p - 1) 
       set @w = LTrim(RTrim(SUBSTRING(@w, @p + 1, 10000))) 
      end else begin 
       set @p = patindex('% as%', @w) 
       if @p > 0 
        set @t = SUBSTRING(@w, 1, @p - 1) 
       else 
        set @t = @w 
       set @w = '' 
      end 

      print 'T=' + @t 
      set @p = charindex(' ', @t) 
      if @p = 0 
       print 'NameError:' + @t + ' ->' + cast(@p as varchar) 
      set @name = SUBSTRING(@t, 1, @p - 1) 
      set @t = SUBSTRING(@t, @p + 1, 10000) 

      set @p = CHARINDEX('=', @t) 
      if @p > 0 begin 
       set @default = Replace(LTrim(RTrim(SUBSTRING(@t, @p + 1, 10000))), '''', '') 
       set @t = SUBSTRING(@t, 1, @p - 1) 
      end 

      set @p = CHARINDEX('(', @t) 
      if @p > 0 
       set @type = LTrim(RTrim(SUBSTRING(@t, 1, @p - 1))) 
      else 
       set @type = LTrim(RTrim(@t)) 

      insert @par (ParameterName, ParameterType, DefaultValue) 
      values(@name, @type, @default) 
     end--while len(@w) > 0 

     fetch next from c into @w 
    end 
    close c 
    deallocate c 

    select * 
    from @par 
-1

有很多簡單和正確的方法來獲取SP和函數的所有輸入和輸出參數,請嘗試下面的語句。 (源是http://www.mssqltips.com/sqlservertip/1669/generate-a-parameter-list-for-all-sql-server-stored-procedures-and-functions/

SELECT SCHEMA_NAME(SCHEMA_ID) AS [Schema], 
SO.Name AS [ObjectName], 
SO.Type_Desc AS [ObjectType (UDF/SP)], 
PM.Parameter_ID AS [ParameterID], 
case 
when pm.system_type_id = pm.user_type_id then 'system_type' 
else 'user_type' 
end as [TypeDescr], 
CASE 
WHEN PM.Parameter_ID = 0 THEN 'Returns' 
ELSE PM.Name 
END AS [ParameterName], 
'['+TYPE_NAME(PM.User_Type_ID)+']' AS [ParameterDataType], 
CASE 
WHEN TYPE_NAME(PM.User_Type_ID) IN ('float', 'uniqueidentifier', 'datetime', 'bit', 'bigint', 'int', 'image', 'money', 'xml', 'varbinary', 'tinyint', 'text', 'ntext', 'smallint', 'smallmoney') THEN '' 
WHEN TYPE_NAME(PM.User_Type_ID) IN ('decimal', 'numeric') THEN '(' + CAST(Precision AS VARCHAR(4)) + ', ' + CAST(Scale AS VARCHAR(4)) + ')' 
ELSE 
case 
when PM.Max_Length <> -1 then '('+CAST(PM.Max_Length AS VARCHAR(4))+')' 
when (TYPE_NAME(PM.User_Type_ID) = 'xml') or (pm.system_type_id <> pm.user_type_id) then '' 
else '(max)' 
end 
END AS [Size], 
CASE 
WHEN PM.Is_Output = 1 THEN 'Output' 
ELSE 'Input' 
END AS [Direction] 
FROM sys.objects AS SO 
INNER JOIN sys.parameters AS PM ON SO.OBJECT_ID = PM.OBJECT_ID 
WHERE TYPE IN ('P','FN') 
ORDER BY [Schema], SO.Name, PM.parameter_id 
+1

您應該嘗試:select * from information_schema.INFORMATION_SCHEMA.PARAMETERS WHERE specific_name ='my_sp_name' –