【问题标题】:Is it possible to create SQL SERVER Function using transaction是否可以使用事务创建 SQL SERVER 函数
【发布时间】:2023-03-04 14:08:01
【问题描述】:

我有一个简单的脚本,它基本上做了很多数据库操作。现在我需要升级数据库,我需要在同一个事务中创建函数。

BEGIN TRY --Start the Try Block..

    BEGIN TRANSACTION -- Start the transaction..
        -- HERE I need to add one function like
        IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[FuctionTest]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[FuctionTest]
GO
CREATE FUNCTION FuctionTest 
(   
    @inputVal int
)
RETURNS int
AS
BEGIN
    RETURN (Select Id from [dbo].[test] where Id=@inputVal)
END

        UPDATE MyChecking SET Amount = Amount - @Amount

            WHERE AccountNum = @AccountNum

        UPDATE MySavings SET Amount = Amount + @Amount

            WHERE AccountNum = @AccountNum

    COMMIT TRAN -- Transaction Success!

END TRY

BEGIN CATCH

    IF @@TRANCOUNT > 0

        ROLLBACK TRAN --RollBack in case of Error

我将如何完成这项工作?我不想使用单独的脚本来创建函数。

【问题讨论】:

    标签: sql-server tsql function transactions try-catch


    【解决方案1】:

    是的,使用EXEC('...') 喜欢:

    --list all functions named like '%test_function%', which will not find any
    SELECT [name] FROM sys.objects WHERE [name] like '%test_function%'
    
    --create a function named 'test_function1'
    exec ('create function [dbo].[test_function1] (@x int) returns varchar(50) as BEGIN return convert(varchar(50),@x)+''!'' END')
    
    begin transaction
    
    --create a function 'test_function2', which will be rolled back
    exec ('create function [dbo].[test_function2] (@x int) returns varchar(50) as BEGIN return convert(varchar(50),@x)+''!!!!'' END')
    
    rollback
    
    --show the functions named like '%test_function%'
    --which will only find 'test_function1', since 'test_function2'
    --was rolled back
    SELECT [name] FROM sys.objects WHERE [name] like '%test_function%'
    

    输出:

    name
    -----------------------
    
    (0 row(s) affected)
    
    name
    -------------------------
    test_function1
    
    (1 row(s) affected)
    

    EDIT 显示一个开始尝试块....

    BEGIN TRY
    
        --list all functions named like '%test_function%', which will not find any
        SELECT [name] FROM sys.objects WHERE [name] like '%test_function%'
    
        --create a function named 'test_function1'
        exec ('create function [dbo].[test_function1] (@x int) returns varchar(50) as BEGIN return convert(varchar(50),@x)+''!'' END')
    
        begin transaction
    
        --create a function 'test_function2', which will be rolled back
        exec ('create function [dbo].[test_function2] (@x int) returns varchar(50) as BEGIN return convert(varchar(50),@x)+''!!!!'' END')
    
        RAISERROR('force catch!',16,1) --send control to the BEGIN CATCH block
    
        --should never get here
        COMMIT 
    
    END TRY
    BEGIN CATCH
    
        IF XACT_STATE()!=0
        BEGIN
            ROLLBACK TRANSACTION
        END
        PRINT CASE WHEN ERROR_NUMBER() IS NOT NULL THEN 'Msg '+CONVERT(varchar(30),ERROR_NUMBER()) ELSE '' END+CASE WHEN ERROR_SEVERITY() IS NOT NULL THEN ', Level '+CONVERT(varchar(30),ERROR_SEVERITY()) ELSE '' END+CASE WHEN ERROR_STATE() IS NOT NULL THEN ', State '+CONVERT(varchar(30),ERROR_STATE()) ELSE '' END+CASE WHEN ERROR_PROCEDURE() IS NOT NULL THEN ', Procedure '+ERROR_PROCEDURE() ELSE '' END+CASE WHEN ERROR_LINE() IS NOT NULL THEN ', Line '+CONVERT(varchar(30),ERROR_LINE()) ELSE '' END+CASE WHEN ERROR_MESSAGE() IS NOT NULL THEN ', '+ERROR_MESSAGE() ELSE '' END
    END CATCH
    
    
    --show the functions named like '%test_function%'
    --which will only find 'test_function1', since 'test_function2'
    --was rolled back
    SELECT [name] FROM sys.objects WHERE [name] like '%test_function%'
    

    输出:

    name
    ---------------------------------------------------
    
    (0 row(s) affected)
    
    Msg 50000, Level 16, State 1, Line 14, force catch!
    name
    ---------------------------------------------------
    test_function1
    
    (1 row(s) affected)
    

    【讨论】:

    • 嗨 RacerX,如果上面存在 try/catch 块,您能否使用相同的脚本,即 try/catch 块将包含事务块,然后我需要在事务中使用该脚本。谢谢,小吃
    • RacerX:您的方法似乎取决于用户是否拥有足够的 CREATE 权限……对吗?
    • 是的。使用EXEC 不会以任何方式绕过此要求。
    • @Tapas Mahata,我想不出为什么 begin try 块会导致它的行为有任何不同。为什么不试试看呢?
    • @Tapas Mahata,是的,它的工作原理相同,我对其进行了测试,并将编辑我的问题,显示开始尝试块...
    猜你喜欢
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    相关资源
    最近更新 更多