Има ли начин да се определи дали даден параметър в съхранена процедура има стойност по подразбиране (и следователно не се изисква) в код - .Net?

Вече изтеглям параметрите от съхранената процедура, изпратена по следния начин:

 foreach (SqlParameter param in cmd.Parameters)
            {
               if ((param.Direction == ParameterDirection.Input) || (param.Direction == ParameterDirection.InputOutput))
                {
                    jsonReturn += "{\"paramName\":\"" + param.ParameterName + "\", \"paramType\":\"" + param.SqlDbType.ToString() + "\"},";
                }
            }

Разгледах обекта SqlParameter и не можах да намеря начин да видя дали може да ми каже дали параметърът има стойност по подразбиране... (въпреки че моят дебъгер се държи странно, така че кой знае).

Това, което правя, е да изграждам нещо като помощник на Stored Proc за потребителите. В момента им казвам всички параметри, които принадлежат към избрания от тях Stored Proc... НАИСТИНА БИХ искал да мога да кажа дали са необходими.


person Todd Vance    schedule 03.05.2011    source източник
comment
Моля, добавете маркера sql-server.   -  person Kenny Evitt    schedule 03.05.2011


Отговори (4)


За да отговоря директно на въпроса ви, не (вероятно) няма начин да се определи дали параметър на съхранена процедура притежава стойност по подразбиране „в кода“ (т.е. използвайки класа SqlParameter).

В SQL Server (поне SQL Server 2005) можете да направите заявка към изгледа на системния каталог sys.parameters (и да го присъедините към изгледа на каталога sys.procedures) и да оцените стойността на колоната has_default_value.

person Kenny Evitt    schedule 03.05.2011

Актуализация на SQL на Devart - благодаря ви много, трябваше да намеря какви са стойностите по подразбиране, а не само дали имаха такава, и вашият код ме накара да започна.

Имаше малък бъг: ако име на параметър съдържаше 'at' (като @d_at_e), останалите параметри не бяха обработени.

Използването на променливите също го ускорява много.

Връща null, ако няма стойност по подразбиране, в противен случай връща всичко между '=' и ',' в декларацията.

declare @ProcName nvarchar(200) = 'your_stored_proc_name'
declare @objectid int
declare @type nchar(2)
declare @oName nvarchar(100)
declare @sName nvarchar(100)
declare @Definition nvarchar(max)


select  @objectid = o.[object_id], 
        @type = o.type, 
        @oName = o.name, 
        @sName = s.name, 
        @Definition = replace(replace(sm.[definition], char(10),' '), char(13),' ')
                    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] IN ('P ', 'FN', 'IF', 'TF')
                        AND s.name + '.' + o.name =  @ProcName 

    SELECT
          data2.[object_name] as StoredProcedure
        , data2.name as ParameterName
        , DefaultValue = 
            CASE WHEN data2.ptoken LIKE '%=%' 
                THEN SUBSTRING(data2.ptoken, CHARINDEX('=', data2.ptoken)+1, CHARINDEX(',',data2.ptoken+',',CHARINDEX('=', data2.ptoken))-CHARINDEX('=', data2.ptoken)-1)
                ELSE null
            END
    FROM (
        SELECT  
              data.name
            , data.[object_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
                , sm3.[object_name]
                , 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]
                    , sm2.[object_name]
                    , tokens = REVERSE(
                        CASE WHEN sm2.[type] IN ('FN', 'TF', 'IF') 
                            THEN SUBSTRING(sm2.tokens, ISNULL(CHARINDEX(N')', sm2.tokens) + 1, 0), LEN(sm2.tokens)) 
                            ELSE SUBSTRING(sm2.tokens, ISNULL(CHARINDEX(' SA ', sm2.tokens) + 2, 0), LEN(sm2.tokens))  
                        END
                    ) 
                FROM (
                    SELECT 
                          @objectid as [object_id]
                        , @type as [type]
                        , @sName + '.' + @oName as [object_name] 
                        , tokens = REVERSE(CASE WHEN @type IN ('FN', 'TF', 'IF') 
                            THEN SUBSTRING(
                                      @Definition
                                    , CHARINDEX(N'(', @Definition) + 1
                                    , ABS(CHARINDEX(N'RETURNS', @Definition) - CHARINDEX(N'(', @Definition) - 1)
                                    ) 
                            ELSE SUBSTRING(
                                      @Definition
                                    , CHARINDEX(@oName, @Definition) + LEN(@oName) + 1
                                    , ABS(CHARINDEX(N' AS ', @Definition) - (CHARINDEX(@oName, @Definition) + LEN(@oname) + 1))
                                    )  
                            END
                            )
                ) 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
person demarchist    schedule 23.08.2013

Опитайте тази заявка. Връща стойности по подразбиране за всяка съхранена процедура/функция -

SELECT
      data2.[object_name]   
    , data2.name
    , has_default_value = 
        CASE WHEN data2.ptoken LIKE '%=%' 
            THEN 1 
            ELSE 0
        END
FROM (
    SELECT  
          data.name
        , data.[object_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
            , sm3.[object_name]
            , 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]
                , sm2.[object_name]
                , tokens = REVERSE(
                    CASE WHEN sm2.[type] IN ('FN', 'TF', 'IF') 
                        THEN SUBSTRING(sm2.tokens, ISNULL(CHARINDEX(N')', sm2.tokens) + 1, 0), LEN(sm2.tokens)) 
                        ELSE SUBSTRING(sm2.tokens, ISNULL(CHARINDEX('SA', sm2.tokens) + 2, 0), LEN(sm2.tokens))  
                    END
                ) 
            FROM (
                SELECT 
                      sm.[object_id]
                    , o.[type]
                    , [object_name] = s.name + '.' + o.name
                    , tokens = REVERSE(CASE WHEN o.[type] IN ('FN', 'TF', 'IF') 
                        THEN SUBSTRING(
                                  sm.[definition]
                                , CHARINDEX(N'(', sm.[definition]) + 1
                                , ABS(CHARINDEX(N'RETURNS', sm.[definition]) - CHARINDEX(N'(', sm.[definition]) - 1)
                                ) 
                        ELSE SUBSTRING(
                                  sm.[definition]
                                , CHARINDEX(o.name, sm.[definition]) + LEN(o.name) + 1
                                , ABS(CHARINDEX(N'AS', sm.[definition]))
                                )  
                        END
                    ) 
                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] IN ('P ', 'FN', 'IF', 'TF')
                    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
person Devart    schedule 05.04.2013

Ако търсите разработване на инструменти за управление на обекти на SQL Server, тогава по-добър вариант може да бъде SMO. Изглежда, че можете да стигнете до стойността по подразбиране на параметър на съхранена процедура, като използвате Клас на StoredProcedureParameter.

http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.parameter.defaultvalue(v=SQL.100).aspx

person Pero P.    schedule 03.05.2011
comment
Ето пример за код, използващ този подход. Проверих, че той действително получава стойностите по подразбиране за обикновени стари процедури, съхранени без CLR. stackoverflow.com/a/1676272 - person Troy Gizzi; 23.06.2017