T-SQL: как создать «частную» функцию внутри хранимой процедуры - PullRequest
19 голосов
/ 08 июня 2010

Хорошо, я пишу хранимую процедуру 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, но тогда мне нужно будет создать / удалить его и т. Д., Поскольку эта логика требуется только на время выполнения этой хранимой процедуры.

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

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

EDIT

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

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

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

Ответы [ 2 ]

19 голосов
/ 08 июня 2010

Сначала я попытался создать еще один временный 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
0 голосов
/ 08 июня 2010

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

...