نوشته شده توسط
sara_aryanfar
ممنون دوست من دقیقا دنبال همین مبحث بودم اگر در مورد استفاده در SPها هم نمونه ای در دسترس داشته باشید ممنون میشم
توی SPها شما ابتدا یک transaction رو شروع میکنید
بعد تک تک دستورات رو اجرا میکنید.
بعد از اجرای هر دستور چک میکنید خطایی رخ داده یا خیر
اگر خطایی رخ داده باشه به یک برچسب کنترل خطا پرش می کنید
در نهایت آخر همه دستورات Transaction رو Commit میکنید
برای نمونه:
ALTER PROCEDURE [dbo].[sp_InsertUser]
@Username varchar(20),
@Email varchar(100),
@Password varchar(12),
@FirstName nvarchar(30),
@LastName nvarchar(50),
@Birthday varchar(10),
@CityId int,
@Address nvarchar(300),
@ZipCode varchar(10),
@Mobile varchar(11),
@MobileActiveCode char(4),
@GenderId tinyint,
@MaritalStatusId tinyint,
@DegreeId tinyint,
@Courses nvarchar(50),
@ExpireDate datetime,
@Description nvarchar(500),
@PicturePath nvarchar(300),
@YahooID varchar(30),
@WebSite nvarchar(80),
@MemberTypeId tinyint,
@UserRoles AS UserRolesId READONLY
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TranStarted bit;
SET @TranStarted = 0;
IF( @@TRANCOUNT = 0 )
BEGIN
BEGIN TRANSACTION
SET @TranStarted = 1
END
ELSE
SET @TranStarted = 0
DECLARE @HashedPassword char(32);
SET @HashedPassword = CONVERT(CHAR(32),HashBytes('MD5', @Password),2)
INSERT INTO [dbo].[tbl_Users]
([Username]
,[Email]
,[Password]
,[FirstName]
,[LastName]
,[Birthday]
,[CityId]
,[Address]
,[ZipCode]
,[Mobile]
,[MobileActiveCode]
,[GenderId]
,[MaritalStatusId]
,[DegreeId]
,[Courses]
,[ExpireDate]
,[Description]
,[PicturePath]
,[YahooID]
,[WebSite]
,[MemberTypeId])
VALUES
(
LOWER(@Username),
LOWER(@Email),
@HashedPassword,
@FirstName,
@LastName,
@Birthday,
@CityId,
@Address,
@ZipCode,
@Mobile,
@MobileActiveCode,
@GenderId,
@MaritalStatusId,
@DegreeId,
@Courses,
@ExpireDate,
@Description,
@PicturePath,
@YahooID,
@WebSite,
@MemberTypeId
)
DECLARE @UserId int;
SELECT @UserId = SCOPE_IDENTITY();
IF ( @@ERROR <> 0)
GOTO Cleanup
--************************************************** ***************************************
INSERT INTO [dbo].[tbl_Scores]
(
[UserId]
,[ScoreModeId]
,[Value]
)
VALUES
(
@UserId
,1
,100
)
IF ( @@ERROR <> 0)
GOTO Cleanup
--************************************************** ***************************************
INSERT INTO [dbo].[tbl_ChatSetting]
(
[UserId]
)
VALUES
(
@UserId
)
IF ( @@ERROR <> 0)
GOTO Cleanup
--************************************************** ***************************************
DECLARE @TotalRoles int;
DECLARE @CurrentRow int;
DECLARE @RoleId tinyint;
SELECT @TotalRoles = COUNT(*) FROM @UserRoles;
SET @CurrentRow = 1;
WHILE @CurrentRow <= @TotalRoles
BEGIN
SELECT TOP 1 @RoleId = [RoleId] FROM @UserRoles WHERE ( [No] = @CurrentRow );
INSERT INTO tbl_UsersInRoles (UserId, RoleId) VALUES (@UserId, @RoleId)
SET @CurrentRow = @CurrentRow + 1;
IF ( @@ERROR <> 0)
BEGIN
GOTO Cleanup
BREAK
END
END
--************************************************** ***************************************
IF( @TranStarted = 1 )
BEGIN
SET @TranStarted = 0
COMMIT TRANSACTION
SELECT @UserId AS 'NewRecordId'
RETURN
END
Cleanup:
IF( @TranStarted = 1 )
BEGIN
SET @TranStarted = 0
ROLLBACK TRANSACTION
END
SELECT 0 AS 'NewRecordId'
END
این یک نمونه واقعی و عملی از اجرای همزمان چند دستور Insert به ازای یک کاربر جدید هست. اگر افزودن کاربر جدید با خطایی مواجه بشه هیچکدوم از Insertهای بعدی اجرا نمیشن و در روند اجرای هرکدوم از دستورات خطایی رخ بده به برچسب مورد نظر پرش کرده و عملیات رو کنسل میکنیم.