我正在尝试删除存储过程(如果存在),然后在事务内部重新创建它。
npm run start
当我运行上面的脚本时,我收到以下错误:
BEGIN TRANSACTION
BEGIN TRY
IF OBJECT_ID(N'dbo.GET_DATA', N'P') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[GET_DATA]
END
CREATE PROCEDURE [dbo].[GET_DATA]
@date datetime2
AS
SET NOCOUNT ON
BEGIN
SELECT
dbo.Products.product_cod AS 'product_cod',
dbo.Product_Types.name AS 'product_type_name',
dbo.UM.name AS 'um_name',
dbo.Products.category_id AS 'category_id',
dbo.Bins_Products.bin_id AS 'product_bin_id'
FROM dbo.Products
LEFT JOIN dbo.Product_Types on Products.product_type_id = Product_Types.product_type_id
LEFT JOIN dbo.UM on Products.um_id = UM.um_id
LEFT JOIN Bins_Products ON Bins_Products.product_id = Products.product_id
WHERE
Products.update_date >= @date
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS 'ErrorMessage'
ROLLBACK TRANSACTION
END CATCH
我在SET和@date上有一些波浪线。
IF语句和create语句本身都可以正常工作。
答案 0 :(得分:2)
您可以使用EXEC
在事务中创建过程,但这非常不方便,因为需要对整个身体进行转义。更好的方法是确保存储过程始终存在,然后执行ALTER
,这不需要单独的事务:
IF OBJECT_ID('Foo', 'P') IS NULL
EXEC ('CREATE PROCEDURE Foo AS BEGIN RETURN END;');
GO
ALTER PROCEDURE Foo(@Arg INT) AS BEGIN
...
END;
这种方法的另一个好处(或缺点,取决于您的部署过程)是,这会保留存储过程的任何现有权限,而不像删除和创建它。
答案 1 :(得分:2)
只是为了证明这个可以在一个事务中完成,这是一个演示脚本:
A
尝试创建新的A
过程时会产生错误,并且回滚会恢复为A
的原始版本。这只能真正起作用(如此处),创建新版rollback
会导致硬错误,以便我们可以在之后检测到并决定commit
而不是test
。
话虽这么说,我仍然会自己使用Jeroen's answer。
答案 2 :(得分:0)
过程定义必须在其自己的批次中。在Management Studio中,您需要添加两行
go
在create procedure
之前和end
之后。不幸的是,交易不能跨越多个批次。
你可以在exec
电话中创建程序吗?像:
exec ('create procedure dbo.MyProc as ...');
答案 3 :(得分:0)
使用此代码,这是我的工作示例。
根据您的表格和要求进行修改。
USE [DatabaseName]
GO
/****** Object: StoredProcedure [dbo].[_AdvancePaymentDelete] Script Date: 10/04/2017 15:12:43 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[_AdvancePaymentDelete]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[_AdvancePaymentDelete]
GO
USE [DatabaseName]
GO
/****** Object: StoredProcedure [dbo].[_AdvancePaymentDelete] Script Date: 10/04/2017 15:12:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[_AdvancePaymentDelete]
(
@_ADVANCEPAYMENTID_PK uniqueidentifier,
@_COMPANYID_PK uniqueidentifier ,
@_COMPANYDETID_PK uniqueidentifier ,
@_USERID_PK uniqueidentifier
)
AS
BEGIN
BEGIN TRANSACTION;
SAVE TRANSACTION MySavePoint;
DECLARE @ErrorMessage nvarchar(MAX) = 'OK';
BEGIN TRY
UPDATE [dbo].[_ADVANCEPAYMENT] SET _ISDELETED = N'2'
WHERE _COMPANYID_PK = @_COMPANYID_PK AND _COMPANYDETID_PK = @_COMPANYDETID_PK AND _USERID_PK = @_USERID_PK AND _ADVANCEPAYMENTID_PK = @_ADVANCEPAYMENTID_PK AND _ISDELETED = N'1'
UPDATE [dbo].[_ADVANCEPAYMENTDET] SET _ISDELETED = N'2'
WHERE _COMPANYID_PK = @_COMPANYID_PK AND _COMPANYDETID_PK = @_COMPANYDETID_PK AND _USERID_PK = @_USERID_PK AND _ADVANCEPAYMENTID_PK = @_ADVANCEPAYMENTID_PK AND _ISDELETED = N'1'
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION MySavePoint; -- rollback to MySavePoint
DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
DECLARE @ErrorState INT = ERROR_STATE();
SET @ErrorMessage = 'Error No : ' + CAST ( ERROR_NUMBER() AS nvarchar(MAX)) + CHAR(13) + 'Line No : ' + CAST ( ERROR_LINE() AS nvarchar(MAX))+ CHAR(13) + 'Procedure Name : ' + QUOTENAME(OBJECT_SCHEMA_NAME(@@PROCID)) + '.' + QUOTENAME(OBJECT_NAME(@@PROCID)) + CHAR(13) + 'Error Message : ' + ERROR_MESSAGE();
RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);
END
END CATCH
COMMIT TRANSACTION
END;
SELECT @ErrorMessage
GO
答案 4 :(得分:0)
我不知道你在那里尝试做什么,但是我可以看到这个代码有一些明显的问题,看起来应该是这样......
请注意,创建过程必须是批处理中的唯一语句,这意味着您无法在一个事务中包装drop和create proc。
IF OBJECT_ID(N'dbo.GET_DATA', N'P') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[GET_DATA]
END
GO
CREATE PROCEDURE [dbo].[GET_DATA]
@date datetime2
AS
BEGIN --<-- Proc body start
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
SELECT
dbo.Products.product_cod AS 'product_cod',
dbo.Product_Types.name AS 'product_type_name',
dbo.UM.name AS 'um_name',
dbo.Products.category_id AS 'category_id',
dbo.Bins_Products.bin_id AS 'product_bin_id'
FROM dbo.Products
LEFT JOIN dbo.Product_Types on Products.product_type_id = Product_Types.product_type_id
LEFT JOIN dbo.UM on Products.um_id = UM.um_id
LEFT JOIN Bins_Products ON Bins_Products.product_id = Products.product_id
WHERE
Products.update_date >= @date;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0) -- Check for open transactions before you try to rollback
BEGIN
ROLLBACK TRANSACTION;
END
SELECT ERROR_MESSAGE() AS 'ErrorMessage'
END CATCH
END --<-- Proc body End
GO