I am facing a big issue, the below stored procedure taking lot of time for execution. Please help me to find issues with following stored procedure .
We need to insert bulk subscriber list from excel in to database. But only 60 subscribers are getting inserted in to db in one minute.
Please help me to resolve the issue.
USE [SMS]
GO
/****** Object: StoredProcedure [dbo].[SP_ProcessFile] Script Date: 01/30/2015 12:56:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_ProcessFile]
#JobCode varchar(25)
WITH RECOMPILE
AS
declare
#jobCode1 Varchar(50),
#count int,#Code varchar(50),#Name [varchar](50),#Date Datetime,#Status int,
#i int,#EUCount int,#SubCount int,
#Add1 nvarchar(3000) ,
#Add2 nvarchar(500) ,
#Add3 nvarchar(500)
,#refdate [varchar](50) ,
#reference [varchar](50) ,
#Joined [varchar](50),
#Joinmonth [nvarchar](50),
#Activated [varchar](50),
#ActivMonth [nvarchar](50),
#Center [varchar](50) ,
#Region [varchar](50) ,
#Area [varchar](50) ,
#Modem [varchar](50) ,
#Adomstatus [varchar](50)
, #AddCode [varchar](50)
set #i = 1
Set #jobCode1 =#JobCode
BEGIN
SET NOCOUNT ON
Set #Status = (Select Distinct(status) from TSMST1005 where Jobcode = #jobCode1)
if (#Status = 0)
begin
Select '1' as res
end
else
begin
CREATE TABLE #tblSMS(pID int identity(1,1),
[Reference] [nvarchar](50) NULL,
[Date] [varchar](50) NOT NULL,
[Code] [nvarchar](50) NULL,
[Subname] [varchar](500) NULL,
[Address1] [nvarchar](3000) NULL,
[Address2] [nvarchar](500) NULL,
[Address3] [nvarchar](500) NULL,
[Joined] [varchar](50) NULL,
[Joinmonth] [varchar](50) NULL,
[Activated] [varchar](50) NULL,
[ActivMonth] [nvarchar](50) NULL,
[Center] [varchar](50) NULL,
[Region] [varchar](50) NULL,
[Area] [varchar](50) NULL,
[Modem] [varchar](50) NULL,
[Adomstatus] [varchar](50) NULL,
[RefDate] [varchar](50) NOT NULL)
insert into #tblSMS
SELECT Reference,[Date],
Code,Subname ,Address1 ,Address2 ,Address3 ,
Joined , Joinmonth ,Activated, ActivMonth ,
Center,Region,Area,Modem,Adomstatus ,refdate FROM TSMST1005 where jobcode = #jobCode1 and Status =1
WHILE #i <= (SELECT COUNT(*) FROM #tblSMS)
BEGIN
SELECT
#Code =Code,
#Name = Subname,
#Date =[Date],
#Add1 =Address1 ,
#Add2 =Address2 ,
#Add3= Address3,
#reference =Reference ,
#Joined = Joined,
#Joinmonth =Joinmonth,
#Activated =Activated,
#ActivMonth =ActivMonth,
#Center = Center,
#Region = Region,
#Area= Area,
#Modem = Modem ,
#Adomstatus =Adomstatus,
#refdate = RefDate
From #tblSMS where pID = #i
Insert into TCMST5001 (CompanyCode , Address1,Address2 ,Address3 ,CreatedDate ,Status) values('001',#Add1 ,#Add2,#Add3,GETDATE(),1)
Set #count = SCOPE_IDENTITY()
Set #AddCode = 'ADD' + Cast(#count As Varchar(10))
Update TCMST5001 Set Code =#AddCode Where AddressID =#count
Set #EUCount = (Select COUNT(*) from TCCOM0005 where EnterpriseUnitCode = #Center)
if (#EUCount = 0)
Begin
Insert into TCCOM0005(AddressCode,CompanyCode,EnterpriseUnitCode,EnterpriseUnitName,Status) values(#count ,'001',#Center,#Center ,1)
END
Set #SubCount = (Select COUNT(*) from TSMST1001 where Subscriber = #Code)
if (#SubCount =0)
begin
Insert into TSMST1001(ActivationDate ,refdate , Address ,AlternateName ,Area ,Region ,Subscriber,Name ,date ,CreatedDate ,EnterpriseUnit ,Status)
values(#Activated,#refdate ,#count ,#Name,#Area,#Region,#Code,#Name ,#Joined ,GETDATE(),#Center,#Adomstatus)
end
Insert into TSMST1003 (Device ,CreatedDate ,Subscriber,StartDate) values
(#Modem,GETDATE(),#Code,#Activated)
SET #i = #i + 1
Update TSMST1005 Set Status = 0 where Jobcode = #jobCode1
Select '3' as res
END
END
Drop table #tblSMS
end
It is quite hard to give you 100% working procedure. However your problem is that you are inserting records row by row. Instead of doing that you need to insert records in BULK. That would work A LOT faster. There is rewritten procedure. You still need to rewrite 2 inserts by the same logic. Of course there could be bugs as it is fully untested. Anyway, here we are:
USE [SMS]
GO
/****** Object: StoredProcedure [dbo].[SP_ProcessFile] Script Date: 01/30/2015 12:56:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_ProcessFile] #JobCode VARCHAR(25)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
SET #Status = ( SELECT TOP 1 status
FROM TSMST1005
WHERE Jobcode = #jobCode
)
IF ( #Status = 0 )
BEGIN
SELECT '1' AS res
END
ELSE
BEGIN
CREATE TABLE #tblSMS
(
pID INT IDENTITY(1, 1) ,
[Reference] [NVARCHAR](50) NULL ,
[Date] [VARCHAR](50) NOT NULL ,
[Code] [NVARCHAR](50) NULL ,
[Subname] [VARCHAR](500) NULL ,
[Address1] [NVARCHAR](3000) NULL ,
[Address2] [NVARCHAR](500) NULL ,
[Address3] [NVARCHAR](500) NULL ,
[Joined] [VARCHAR](50) NULL ,
[Joinmonth] [VARCHAR](50) NULL ,
[Activated] [VARCHAR](50) NULL ,
[ActivMonth] [NVARCHAR](50) NULL ,
[Center] [VARCHAR](50) NULL ,
[Region] [VARCHAR](50) NULL ,
[Area] [VARCHAR](50) NULL ,
[Modem] [VARCHAR](50) NULL ,
[Adomstatus] [VARCHAR](50) NULL ,
[RefDate] [VARCHAR](50) NOT NULL
)
INSERT INTO #tblSMS
SELECT Reference ,
[Date] ,
Code ,
Subname ,
Address1 ,
Address2 ,
Address3 ,
Joined ,
Joinmonth ,
Activated ,
ActivMonth ,
Center ,
Region ,
Area ,
Modem ,
Adomstatus ,
RefDate
FROM TSMST1005
WHERE jobcode = #jobCode1
AND Status = 1
WHILE #i <= ( SELECT COUNT(*)
FROM #tblSMS
)
BEGIN
DECLARE #minPK INT;
SELECT #minPK = MAX(AddressID ) FROM TCMST5001; -- I believe that it is identity column. If not change it to the proper one
INSERT INTO TCMST5001
( CompanyCode ,
Address1 ,
Address2 ,
Address3 ,
CreatedDate ,
Status
)
SELECT '001', Address1, Address2, Address3, GETDATE(), 1 FROM #tblSMS;
SET #AddCode = 'ADD' + CAST(#count AS VARCHAR(10))
UPDATE TCMST5001
SET Code = 'ADD' + CAST(AddressID AS VARCHAR(10))
WHERE AddressID > #minPK ;
INSERT INTO TCCOM0005
SELECT ee.cnt, t.center, t.Center, 1
FROM #tblSMS t
CROSS APPLY ( SELECT COUNT(*) AS cnt FROM TCCOM0005 e WHERE e.EnterpriseUnitCode = t.Center) ee
WHERE ee.cnt > 0
-- THE SAME LOGIC MUST BE DONE WITH THESE 2 INSERTS
SET #SubCount = ( SELECT COUNT(*)
FROM TSMST1001
WHERE Subscriber = #Code
)
IF ( #SubCount = 0 )
BEGIN
INSERT INTO TSMST1001
( ActivationDate ,
refdate ,
Address ,
AlternateName ,
Area ,
Region ,
Subscriber ,
Name ,
date ,
CreatedDate ,
EnterpriseUnit ,
Status
)
VALUES ( #Activated ,
#refdate ,
#count ,
#Name ,
#Area ,
#Region ,
#Code ,
#Name ,
#Joined ,
GETDATE() ,
#Center ,
#Adomstatus
)
END
INSERT INTO TSMST1003
( Device ,
CreatedDate ,
Subscriber ,
StartDate
)
VALUES ( #Modem ,
GETDATE() ,
#Code ,
#Activated
)
UPDATE t
FROM TSMST1005 t
SET Status = 0
JOIN #tblSMS tmp
ON tmp.jobCode1 = t.Jobcode
SELECT '3' AS res
END
END
DROP TABLE #tblSMS
END
some tips will be. Avoid doing this in every step.
SELECT COUNT(*) FROM #tblSMS
instead assign the count value to a local variable, and check the i against the same.
Also you are selecting values from these tables ( TCCOM0005, TSMST1001, TSMST1003 ) frequently , It will be good to check if these tables have proper indexes.
Related
CREATE TABLE [dbo].[OrderDetails](
[OrderID] [int] NOT NULL,
[ProductID] [int] NOT NULL,
[UnitPrice] [int] NOT NULL,
[Quantity] [tinyint] NULL,
[Discount] [int] NULL,
[IsActive] [bit] NULL,
[IsDeleted] [bit] NULL
) ON [PRIMARY]
I want to create a function which will check if the quantity inserted is greater then the quantity in stock then prevents user from execution.
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE TRIGGER dbo.PreventQtyInsert ON dbo.OrderDetails
AFTER INSERT
AS
BEGIN
DECLARE #returnQuantity INT ,
#Quantity INT ,
#ProductID INT ,
#GetQuantityFromProductsTable INT;
SELECT #returnQuantity = dbo.ReturnUnitsInStock ( #Quantity , #ProductID ) ;
IF #returnQuantity = 0
BEGIN
RAISERROR ( 'This vendor''s credit rating is too low to accept new purchase orders.' , 16 , 1 ) ;
ROLLBACK TRANSACTION;
RETURN;
END;
ELSE
BEGIN
SET #GetQuantityFromProductsTable = ( SELECT UnitsInStock FROM Products WHERE ProductID = #ProductID ) ;
UPDATE OrderDetails SET Quantity = #GetQuantityFromProductsTable - #Quantity
WHERE ProductID = #ProductID;
END;
END;
GO
I need to compare large tables with millions of rows and insert the differences into a log table.
The problem is that stored proc grows (LDF), and the database disk space is limited.
I know that commit will write the LDF to the MDF.
How can I perform the following compare in batches, and commit every hundred thousand rows?
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO dbo.CustomerLog
( OnlineStore ,
PhoneNumber ,
ChangeType
)
SELECT 'Online Store a' ,
AreaCode + PhoneNumber ,
'Added'
FROM dbo.StoreAList a
WHERE NOT EXISTS ( SELECT 1
FROM dbo.StoreAListCompare b
WHERE ( b.AreaCode + b.PhoneNumber ) = ( a.AreaCode
+ a.PhoneNumber ) );
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH;
CREATE TABLE [dbo].[StoreAList](
[ListID] [bigint] IDENTITY(1,1) NOT NULL,
[AreaCode] [char](3) NOT NULL,
[PhoneNumber] [char](7) NOT NULL,
[RecordDate] [datetime] NULL CONSTRAINT [DF_StoreAList_RecordDate] DEFAULT (getdate())
) ON [PRIMARY]
CREATE TABLE [dnc].[StoreAListCompare](
[ListID] [BIGINT] IDENTITY(1,1) NOT NULL,
[AreaCode] [CHAR](3) NOT NULL,
[PhoneNumber] [CHAR](7) NOT NULL,
[RecordDate] [DATETIME] NULL DEFAULT (GETDATE())
) ON [PRIMARY]
You can use the ##rowcount system variable and do the insert in batches until ##rowcount hits 0.
Note the added AND NOT EXISTS in dbo.CustomerLog...
Ex:
DECLARE #BATCHSIZE INT=100000
WHILE #BATCHSIZE>0
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO dbo.CustomerLog
( OnlineStore ,
PhoneNumber ,
ChangeType
)
SELECT TOP(#BATCHSIZE)
'Online Store a' ,
AreaCode + PhoneNumber ,
'Added'
FROM dbo.StoreAList a
WHERE NOT EXISTS ( SELECT 1
FROM dbo.StoreAListCompare b
WHERE ( b.AreaCode + b.PhoneNumber ) = ( a.AreaCode + a.PhoneNumber ) )
AND NOT EXISTS (SELECT 1
FROM dbo.CustomerLog CL
WHERE 'Online Store a'=CL.OnlineStore
AND AreaCode + PhoneNumber=CL.PhoneNumber
AND 'Added'=CL.ChangeType);
SET #BATCHSIZE=##ROWCOUNT
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SET #BATCHSIZE=0
END CATCH;
END
I have a table FlowTrack:
CREATE TABLE [dbo].[FlowTrack]
(
[RowID] [tinyint] IDENTITY(1,1) NOT NULL,
[ApplicationNo] [varchar](50) NOT NULL,
[StatusID] [tinyint] NOT NULL,
[UpdateType] [varchar](100) NULL,
[CreatedDate] [datetime] NULL,
[CreatedBy] [varchar](50) NULL
) ON [PRIMARY]
Sample data:
RowID ApplicationNo StatusID UpdateType CreatedDate CreatedBy
1 BPS/ANA/MO/7/0146215 1 3 2015-06-17 12:59:56.387 Tests
2 BPS/BHI/20/0164615 1 3 2015-06-17 12:57:57.727 Tester
3 BPS/BHI/6/0204815 1 3 2015-06-17 12:57:57.727 Tester
My procedure :
ALTER procedure Flowtrack
(#APPNO varchar(50),
#vc_status CHAR(1),
#CreatedBy varchar(50) )
AS
BEGIN
MERGE INTO [dbo].Flowtrack AS target
USING (SELECT ApplicationNo, StatusID
FROM Flowtrack
WHERE ApplicationNo = #APPNO AND [StatusID] = #vc_status) AS source
ON target.ApplicationNo = Source.ApplicationNo
WHEN MATCHED THEN
UPDATE
SET
target.ApplicationNo = source.ApplicationNo,
target.StatusID = source.StatusID,
target.UpdateType = 3,
target.CreatedDate = getdate(),
target.CreatedBy = #CreatedBy
WHEN NOT MATCHED BY TARGET THEN
INSERT
([ApplicationNo], [StatusID], [UpdateType],
[CreatedDate], [CreatedBy])
VALUES (source.ApplicationNo, source.StatusID, 3,
getdate(), #CreatedBy);
end
When I'm doing update it is updating
EXEC Flowtrack 'BPS/ANA/MO/7/0146215',3,'Tests'
but when trying to insert, it is not inserting a new record
I'm unable to find out why it is not inserting
To insert new application no
EXEC Flowtrack 'BPS/ANA/MO/7',3,'Test'
Here is the problem:
MERGE INTO [dbo].Flowtrack AS target
USING (SELECT ApplicationNo, StatusID
FROM Flowtrack
WHERE ApplicationNo = #APPNO AND [StatusID] = #vc_status) AS source
ON target.ApplicationNo = Source.ApplicationNo
AND target.StatusID = Source.StatusID
The problem is when you pass new AppNo, then source is empty and there is nothing to insert.
Change to:
MERGE INTO [dbo].Flowtrack AS target
USING (SELECT ApplicationNo, StatusID
FROM (VALUES(#APPNO, #vc_status, #CreatedBy)) t(ApplicationNo, StatusID , CreatedBy)
) AS source
ON target.ApplicationNo = Source.ApplicationNo
AND target.StatusID = Source.StatusID
I'm trying to call this procedure with the usp_TimesheetsAuditsLoadAllbyId 42747, NULL command.
But I always get an error
Msg 8114, Level 16, State 5, Procedure usp_TimesheetsAuditsLoadAllById, Line 9
Error converting data type varchar to bigint.
The ID of TimesheetsAudits table is a bigint type. I tried several types of conversions and casts, but I'm really stuck right now.
Hope somebody can help. Thanks
ALTER PROCEDURE [dbo].[usp_TimesheetsAuditsLoadAllById]
(
#Id INT,
#StartDate DATETIME
)
AS
BEGIN
SET NOCOUNT ON
SELECT TOP 51 *
FROM
(SELECT TOP 51
ID,
Type,
ReferrerId,
CAST(Description AS VARCHAR(MAX)) AS Description,
OnBehalfOf,
Creator,
DateCreated
FROM
TimesheetsAudits
WHERE
(ReferrerID = #Id) AND
(#StartDate IS NULL OR DateCreated < #StartDate)
ORDER BY
DateCreated DESC
UNION
SELECT TOP 51
tia.ID,
tia.Type,
tia.ReferrerId,
'[Day: ' + CAST(DayNr AS VARCHAR(5)) + '] ' + CAST(tia.Description AS VARCHAR(MAX)) AS Description,
tia.OnBehalfOf,
tia.Creator,
tia.DateCreated
FROM
TimesheetItemsAudits tia
INNER JOIN
TimesheetItems ti ON tia.ReferrerId = ti.ID
WHERE
(ti.TimesheetID = #Id) AND
(#StartDate IS NULL OR tia.DateCreated < #StartDate)
ORDER BY
tia.DateCreated DESC) t
ORDER BY
t.DateCreated DESC
END
Table definition for tables from comments:
CREATE TABLE [dbo].[TimesheetsAudits](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Type] [tinyint] NOT NULL,
[ReferrerId] [varchar](15) NOT NULL,
[Description] [text] NULL,
[OnBehalfOf] [varchar](10) NULL,
[Creator] [varchar](10) NOT NULL,
[DateCreated] [datetime] NOT NULL
)
CREATE TABLE [dbo].[TimesheetItemsAudits](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Type] [tinyint] NOT NULL,
[ReferrerId] [varchar](15) NOT NULL,
[Description] [text] NULL,
[OnBehalfOf] [varchar](10) NULL,
[Creator] [varchar](10) NOT NULL,
[DateCreated] [datetime] NOT NULL
)
You perform an INNER JOIN of [dbo].[TimesheetsAudits] and TimesheetItems ti ON tia.ReferrerId = ti.ID
tia.[ReferrerId] is varchar and ti.[ID] is [bigint].
I'd expect a value in tia.[ReferrerId] that cannot be converted to bigint.
Try the following:
SELECT [ReferrerId] FROM TimesheetItemsAudits WHERE ISNUMERIC(ReferrerId) = 0
This may help you to find the "offending rows".
I am creating a simple table with automatically generated employee id with a prefix like
sale_900000,sale_900001,sale_900002,sale_900003
It is a self-referencing table.
When I insert data into the table I get errors like this:
*Msg 547, Level 16, State 0, Procedure tr_generate_emp_id, Line 42
The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint "Registration_Registration". The conflict occurred in database "test", table "dbo.Registration", column 'empid'.*
For automatic employee id I am using an instead of insert trigger on the table
This is my table
CREATE TABLE [dbo].[Registration](
[empid] [varchar](40) NOT NULL,
[id] [int] IDENTITY(900000,1) NOT NULL,
[First_Name] [varchar](40) NULL,
[Last_Name] [varchar](40) NULL,
[Address] [varchar](40) NULL,
[E_Mail] [varchar](40) NULL,
[Country] [varchar](40) NULL,
[Mobile_No] [varchar](40) NULL,
[Designation] [varchar](40) NULL,
[managerID] [varchar](40) NULL,
CONSTRAINT [PK_Registration] PRIMARY KEY CLUSTERED
(
[empid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[Registration] WITH CHECK ADD CONSTRAINT [Registration_Registration] FOREIGN KEY([managerID])
REFERENCES [dbo].[Registration] ([empid])
and this is my trigger
ALTER TRIGGER [dbo].[tr_generate_emp_id] ON [dbo].[Registration]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #id INT
DECLARE #id1 INT
DECLARE #id_s VARCHAR(50)
DECLARE #empid VARCHAR(50)
DECLARE #First_Name VARCHAR(50)
DECLARE #Last_Name VARCHAR(50)
DECLARE #Address VARCHAR(50)
DECLARE #E_Mail VARCHAR(50)
DECLARE #Country VARCHAR(50)
DECLARE #Mobile_No VARCHAR(50)
DECLARE #Designation VARCHAR(50)
DECLARE #managerID VARCHAR(50)
SELECT #id = Id
FROM dbo.Registration
IF #id IS NULL
SET #id = 899999
SET #id1 = #id + 1
SELECt #First_Name = First_Name ,
#Last_Name = Last_Name ,
#Address = Address ,
#E_Mail = E_Mail ,
#Country = Country ,
#Mobile_No = Mobile_No ,
#Designation = Designation ,
#managerID = managerID
FROM INSERTED
SET #id_s = CONVERT(VARCHAR(50), #id1)
SET #empid = 'Sale_' + #id_s
INSERT INTO dbo.Registration
( empid ,
First_Name ,
Last_Name ,
Address ,
E_Mail ,
Country ,
Mobile_No ,
Designation ,
managerID
)
VALUES ( #empid , -- empid - varchar(40)
#First_Name , -- First_Name - varchar(40)
#Last_Name , -- Last_Name - varchar(40)
#Address , -- Address - varchar(40)
#E_Mail , -- E_Mail - varchar(40)
#Country, -- Country - varchar(40)
#Mobile_No , -- Mobile_No - varchar(40)
#Designation , -- Designation - varchar(40)
#managerID -- managerID - varchar(40)
)
END
i am inserting
INSERT INTO dbo.Registration
( empid ,
First_Name ,
Last_Name ,
Address ,
E_Mail ,
Country ,
Mobile_No ,
Designation ,
managerID
)
VALUES ( '' , -- empid - varchar(40)
'admin' , -- First_Name - varchar(40)
'jon' , -- Last_Name - varchar(40)
's-24' , -- Address - varchar(40)
'abc#gmail.com' , -- E_Mail - varchar(40)
'india' , -- Country - varchar(40)
'098735322211' , -- Mobile_No - varchar(40)
'manager' , -- Designation - varchar(40)
'' -- managerID - varchar(40)
)
and error
Msg 547, Level 16, State 0, Procedure tr_generate_emp_id, Line 42
The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint "Registration_Registration". The conflict occurred in database "test", table "dbo.Registration", column 'empid'.
The statement has been terminated.
The main issue is that you're doing this in the first place. I just read through your trigger. Just changed empid to be a computed field...
CREATE TABLE [dbo].[Registration](
[empid] AS ('Sale_' + Convert(Varchar(50),id)) PERSISTED,
[id] [int] IDENTITY(900000,1) NOT NULL,
[First_Name] [varchar](40) NULL,
[Last_Name] [varchar](40) NULL,
[Address] [varchar](40) NULL,
[E_Mail] [varchar](40) NULL,
[Country] [varchar](40) NULL,
[Mobile_No] [varchar](40) NULL,
[Designation] [varchar](40) NULL,
[managerID] [varchar](40) NULL,
CONSTRAINT [PK_Registration] PRIMARY KEY CLUSTERED
(
[empid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
In your trigger I think this line
SELECT #id = Id
is meant to read
SELECT #id = MAX(Id)
I'm surprised you havent received PK violation errors as a result. The FK violation error can only be due to trying to insert MangerId value that doesn't match an empid value (as far as I can see from the code). So check what managerId value you are supplying.
Check your Nest Level.
http://msdn.microsoft.com/en-us/library/ms182737(v=sql.100).aspx
I would put this value in a (dbo.) AuditTable, something that has nothing to do with your primary table.
trigger_nestlevel()
Change from Row Based to Set Based Logic.
I re-did your trigger to be set based but I think #Love2Learn may have a better solution for you.
ALTER TRIGGER [dbo].[tr_generate_emp_id] ON [dbo].[Registration]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #id INT
-- Get the last id used.
SELECT #id = MAX(Id)
FROM dbo.Registration
IF #id IS NULL
SET #id = 899999
WITH MyInserted AS (SELECT
ROW_NUMBER() OVER(ORDER BY E_Mail) AS rownum-- Email is just a random order by here. Could be anything you want.
,*
FROM inserted)
INSERT INTO dbo.Registration
( empid ,
First_Name ,
Last_Name ,
Address ,
E_Mail ,
Country ,
Mobile_No ,
Designation ,
managerID
)
SELECT -- add the last id used with the rownum (ranges from 1 to num of rows)
'Sale_'+CONVERT(VARCHAR(50), #id+rownum) -- empid - varchar(40)
First_Name, -- First_Name - varchar(40)
Last_Name, -- Last_Name - varchar(40)
Address, -- Address - varchar(40)
E_Mail, -- E_Mail - varchar(40)
Country, -- Country - varchar(40)
Mobile_No, -- Mobile_No - varchar(40)
Designation, -- Designation - varchar(40)
ManagerID -- managerID - varchar(40)
FROM MyInserted
END