T-SQL: как создать приватную функцию внутри хранимой процедуры

Итак, я пишу хранимую процедуру SQL Server 2008 (сценарий обслуживания).

При этом, будучи хорошим мальчиком, я много обрабатывал ошибки, проверял количество строк, печатал выходные сообщения и т. д.

Но при этом я ловил себя на том, что снова и снова пишу что-то вроде этого:

SELECT @RowsAffected = @@ROWCOUNT
IF @RowsAffected > 0
BEGIN
   PRINT CAST(@RowsAffected, NVARCHAR(2)) + 'rows updated.'
END

Или отладочные сообщения, подобные этому:

PRINT 'User ' + CAST(@UserId AS NVARCHAR(5)) + ' modified successfully'

Есть ли способ создать своего рода «подпрограмму» внутри хранимой процедуры (например, частный метод), которая может принимать что-то в качестве параметра (хотя это и не обязательно) и выполнять некоторую логику?

Я хочу иметь возможность сделать что-то вроде этого:

CheckRowCounts

Или это:

PrintUserUpatedMessage(@UserId)

Что затем будет выполнять указанную выше логику (проверить количество строк, распечатать сообщение и т.д.)

И да, очевидно, я могу создать UDF, но тогда мне нужно будет создать/удалить его и т. д., поскольку эта логика требуется только на время выполнения этой хранимой процедуры.

Меня тошнит от написания одного и того же кода снова и снова и изменения всех различных областей, которые я использовал, когда получаю сообщение об ошибке =)

Кто-нибудь может помочь?

ИЗМЕНИТЬ

Хорошо, поэтому я создал скалярную функцию UDF (кажется, единственный способ).

Тем не менее, я наградил Фредрика правильным ответом, так как, хотя я не планирую это реализовывать, это одновременно и правильный ответ, и творческий.

Спасибо за все советы/помощь.


person RPM1984    schedule 08.06.2010    source источник


Ответы (2)


Сначала я попытался создать еще один временный SP из существующего SP, что не сработало, но, немного поэкспериментировав, я думаю, что вы могли бы использовать что-то вроде этого (если вы не возражаете против динамического SQL):

CREATE PROCEDURE sp_myTest_v1_0(@firstName NVARCHAR(255)) AS
BEGIN
    -- declare private method
    DECLARE @privateMethod NVARCHAR(255), @privateMethodSig NVARCHAR(255)
    SELECT @privateMethod = 
        'DECLARE @x INT' + CHAR(10) +
        'WHILE ISNULL(@x,0) < 10 BEGIN' + CHAR(10) +
            'PRINT @param1 + CAST(@x AS VARCHAR)' + CHAR(10) +
            'SET @x = ISNULL(@x,0)+1' + CHAR(10) +
        'END', @privateMethodSig = '@param1 NVARCHAR(255)'

    -- call privateMethod
    EXEC sp_executesql @privateMethod, @privateMethodSig, @param1 = @firstName
END
GO
person Fredrik Johansson    schedule 08.06.2010
comment
на самом деле это не ужасно. +1 - person nathan gonzalez; 08.06.2010

на самом деле ничего подобного в tsql. самая близкая вещь, как вы сказали, - это скалярный udf, и вы, похоже, не являетесь поклонником этой идеи. я не вижу проблемы с созданием таких вспомогательных функций и оставлением их в базе данных. наверняка у вас есть другие процедуры, которые могли бы извлечь выгоду из хороших сообщений.

person nathan gonzalez    schedule 08.06.2010
comment
я согласен, что вспомогательные функции не повредят (у меня их много, таких как splitstring, propcase и т. д.). Но что-то вроде этого (распечатка информации в транзакции, количество строк и т. д.) кажется немного излишним. тем не менее, как я уже сказал, это последнее средство, но я подумал, что посмотрю, есть ли у кого-нибудь на SO какие-либо другие идеи. - person RPM1984; 08.06.2010