SQL Server SCOPE_IDENTITY does not run linked server - sql-server
I have two servers that are connected using a linked server. When I run this procedure, it inserts a record one to other and that time I want ID from my second server - how do this?
Alter PROCEDURE [dbo].[stp_TransferJob]
(
#JOB_id AS bigint,
#PartyId as int,
#Commission as decimal(18,2),
#myid as varchar(max),
#ident_out as bigint output
)
AS
BEGIN
INSERT INTO [111.163.103.122].Taxi.dbo.booking (FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,DriverId,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,BookingDate,NoofPassengers,NoofLuggages,NoofHandLuggages,PickupDateTime,ReturnPickupDateTime,IsCompanyWise,CompanyId,FareRate,PaymentTypeId,SpecialRequirements,FromAddress,ToAddress,FromPostCode,ToPostCode,FromDoorNo,ToDoorNo,FromStreet,ToStreet,FromFlightNo,FromComing,BookingStatusId,DistanceString,AutoDespatch,AutoDespatchTime,AddOn,AddBy,AddLog,EditOn,EditBy,EditLog,OrderNo,PupilNo,ParkingCharges,WaitingCharges,ExtraDropCharges,MeetAndGreetCharges,CongtionCharges,TotalCharges,DepartmentId,ReturnFareRate
,ArrivalDateTime,MasterJobId,DisablePassengerSMS,DisableDriverSMS,IsCommissionWise,DriverCommission,DespatchDateTime,JobOfferDateTime,BookingTypeId,DriverCommissionType,IsBidding,IsQuotation,CostCenterId,CashRate,AccountRate,WaitingMins
,ExtraMile,AcceptedDateTime,POBDateTime,STCDateTime,ClearedDateTime,CancelReason,TotalTravelledMiles,CompanyPrice,SubCompanyId,PartyId,
FromOther,ToOther,TransferJobId,TransferJobCommission,BookingTypeId,ViaString)
SELECT
FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,null,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,BookingDate,NoofPassengers,NoofLuggages,NoofHandLuggages,PickupDateTime,ReturnPickupDateTime,IsCompanyWise,null,FareRate,PaymentTypeId,SpecialRequirements,FromAddress,ToAddress,FromPostCode,ToPostCode,FromDoorNo,ToDoorNo,FromStreet,ToStreet,FromFlightNo,FromComing,BookingStatusId,DistanceString,AutoDespatch,AutoDespatchTime,AddOn,AddBy,AddLog,EditOn,EditBy,EditLog,OrderNo,PupilNo,ParkingCharges,WaitingCharges,ExtraDropCharges,MeetAndGreetCharges,CongtionCharges,TotalCharges,DepartmentId,ReturnFareRate
,ArrivalDateTime,MasterJobId,DisablePassengerSMS,DisableDriverSMS,IsCommissionWise,DriverCommission,DespatchDateTime,JobOfferDateTime,BookingTypeId,DriverCommissionType,IsBidding,IsQuotation,CostCenterId,CashRate,AccountRate,WaitingMins
,ExtraMile,AcceptedDateTime,POBDateTime,STCDateTime,ClearedDateTime,CancelReason,TotalTravelledMiles,CompanyPrice,1,#PartyId
,FromOther,ToOther,#JOB_id,#Commission,10,ViaString
FROM Booking
WHERE Id = #JOB_id ;
select SCOPE_IDENTITY()
SET #ident_out = ##IDENTITY
-------------------------------------------------------------------------
INSERT INTO [111.163.103.122].Taxi.dbo.booking_ViaLocations (
BookingId,ViaLocTypeId,ViaLocTypeLabel,ViaLocTypeValue,ViaLocId,ViaLocValue,ViaLocLabel )
SELECT
#ident_out,ViaLocTypeId,ViaLocTypeLabel,ViaLocTypeValue,ViaLocId,ViaLocValue,ViaLocLabel
FROM Booking_ViaLocations
WHERE BookingId = #JOB_id
END
return #ident_out
GO
SCOPE_IDENTITY() AND ##IDENTITY SHOW NULL VALUE HOW TO GET ID please help me
You can return int values using a stored procedure
create PROCEDURE [dbo].[stp_TransferJob]
(
#JOB_id AS bigint,
#PartyId as int,
#Commission as decimal(18,2)
)
AS
BEGIN
INSERT INTO [111.163.103.122].Taxi.dbo.booking (FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,DriverId,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,
FromOther,ToOther,TransferJobId,TransferJobCommission,BookingTypeId,ViaString)
SELECT
FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,null,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,FromOther,ToOther,#JOB_id,#Commission,10,ViaString
FROM Booking
WHERE Id = #JOB_id
RETURN (##IDENTITY)
END
Then when you call your procedure on other server:
DECLARE #ident INT;
EXECUTE #ident = stp_TransferJob (plus other parameters)
Since it is more common to do this with error codes, you might prefer an output parameter:
create PROCEDURE [dbo].[stp_TransferJob]
(
#JOB_id AS bigint,
#PartyId as int,
#Commission as decimal(18,2),
#ident_out as int output
)
AS
BEGIN
INSERT INTO [111.163.103.122].Taxi.dbo.booking (FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,DriverId,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,
FromOther,ToOther,TransferJobId,TransferJobCommission,BookingTypeId,ViaString)
SELECT
FromLocTypeId,ToLocTypeId,FromLocId,ToLocId,VehicleTypeId,null,ReturnDriverId,CustomerId,CustomerName,CustomerEmail,CustomerPhoneNo,CustomerMobileNo,JourneyTypeId,BookingNo,FromOther,ToOther,#JOB_id,#Commission,10,ViaString
FROM Booking
WHERE Id = #JOB_id
SET #ident_out = ##IDENTITY
END
Then when you call the procedure you add a declared parameter with an output keyword. Please see msdn
Related
How to display the result of stored procedure in the temporary table?
I want to display the result of a stored procedure in a temporary table. I have the following code: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER procedure [dbo].[insertpropertylisting] #propertyname VARCHAR(150), #propertyaddress VARCHAR(250), #propertyprice MONEY, #availableunits VARCHAR(100), #propertyid INT OUTPUT AS BEGIN INSERT INTO propertylisting (propertyname, propertyaddress, propertyprice, availableunits) VALUES (#propertyname, #propertyaddress, #propertyprice, #availableunits) PRINT #propertyname SELECT #propertyaddress AS 'address' SET #propertyid = SCOPE_IDENTITY() SELECT #propertyname = propertyname, #propertyaddress = propertyaddress, #propertyprice = propertyprice, #availableunits = availableunits FROM propertylisting WHERE property_id = #propertyid RETURN #propertyid END CREATE TABLE #propertylisting ( propertyname VARCHAR(150), propertyaddress VARCHAR(250), propertyprice MONEY, availableunits VARCHAR(100), propertyid INT ) INSERT INTO #propertylisting EXEC [dbo].[insertpropertylisting] SELECT propertyname, propertyaddress, propertyprice, availableunits FROM #propertylisting DROP TABLE #propertylisting I am not getting the output as table.
A few problems that I can see: Not supplying parameters to the SP. Stand-alone SELECT in the middle of SP that you don't want (also a PRINT). The lack of a batch separator when issuing the ALTER PROCEDURE command. You are assigning the values of the inserted row back to the variables and not actually selecting them back to the caller. It's recommended to always include the column list on INSERT statements, and specially when doing INSERT INTO EXEC. First make some changes to the SP; remove unused statements and parameters (including the OUT property of the parameter since it seems you aren't using it). You can return inserted values with the OUTPUT clause of the INSERT statement, including computed and IDENTITY columns. ALTER procedure [dbo].[insertpropertylisting] #propertyname varchar(150), #propertyaddress varchar(250), #propertyprice money, #availableunits varchar(100) as BEGIN insert into propertylisting ( propertyname, propertyaddress, propertyprice, availableunits) OUTPUT inserted.propertyname, inserted.propertyaddress, inserted.propertyprice, inserted.availableunits, inserted.property_id -- Can return IDENTITY and computed columns values( #propertyname, #propertyaddress, #propertyprice, #availableunits) END After you run this ALTER, you can bring inserted records with a INSERT INTO EXEC. Make sure to pass proper values to the SP. Create table #propertylisting ( propertyname varchar(150), propertyaddress varchar(250), propertyprice money, availableunits varchar(100), propertyid int ) Insert into #propertylisting ( propertyname, propertyaddress, propertyprice, availableunits, propertyid) Exec [dbo].[insertpropertylisting] #propertyname = 'Value', #propertyaddress = 'Value', #propertyprice = 999, #availableunits = 'Value' select propertyname, propertyaddress, propertyprice, availableunits, propertyid from #propertylisting Drop table #propertylisting
Try to use like this first create temp table and then execute the sql procedure USE [Joins] GO /****** Object: StoredProcedure [dbo].[insertpropertylisting] Script Date: 1/29/2019 3:55:43 PM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER procedure [dbo].[insertpropertylisting] #propertyname varchar(150), #propertyaddress varchar(250), #propertyprice money, #availableunits varchar(100), #propertyid int OUTPUT as BEGIN insert into propertylisting(propertyname,propertyaddress,propertyprice,availableunits) values(#propertyname,#propertyaddress,#propertyprice,#availableunits) print #propertyname select #propertyaddress as 'address' SET #propertyid=SCOPE_IDENTITY() SELECT #propertyname=propertyname,#propertyaddress=propertyaddress,#propertyprice=propertyprice, #availableunits=availableunits ,#propertyid FROM propertylisting WHERE property_id=#propertyid -- Return #propertyid u can write in selecting it self END Create table #propertylisting ( propertyname varchar(150), propertyaddress varchar(250), propertyprice money, availableunits varchar(100), propertyid int ) Insert into #propertylisting Exec [dbo].[insertpropertylisting]
Read INSERT output from stored procedure
I have a following stored procedure CREATE PROCEDURE [dbo].[InsertCategory] #Name nvarchar(100) AS BEGIN INSERT INTO [dbo].[Category]([Name]) OUTPUT INSERTED.CategoryId, INSERTED.[Timestamp] VALUES (#Name) END And I call it like this: EXEC [dbo].[InsertCategory] #Name= #Name I would like to know what the id of inserted Category is (it is output in insert statement). It is written to the output, but I can't figure out how to assign it to a variable without modifying stored procedure. In C# I can use command.ExecuteReader and I get it, but I do not know how to get it in SQL Server. I also cannot use SCOPE_IDENTITY as we have our own system of generating ids.
Try this: -- count use a temp table as well -- syntax: CREATE TABLE #t(CategoryId int,[Timestamp] datetime) DECLARE #t table(CategoryId int,[Timestamp] datetime) INSERT #t(CategoryId, [TimeStamp]) EXEC [dbo].[InsertCategory] #Name= #Name SELECT CategoryId, [TimeStamp] FROM #t
You can Declare a table and insert output into it. CREATE PROCEDURE [dbo].[InsertCategory] #Name nvarchar(100) AS BEGIN DECLARE #Result AS TABLE ( CategoryId int, TimeStamp varchar(50) ) INSERT INTO [dbo].[Category]([Name]) OUTPUT INSERTED.CategoryId, INSERTED.[Timestamp] INTO #Result(CategoryId, TimeStamp) VALUES (#Name) SElect * from #Result END
SQL - Return Output To Stored Procedure
I have a stored procedure I have created so that I can enter lines into a table and subsequently return the INSERTED.ID so I can return this ID to the SQL Command that sent it to input the ID into that table. I have used OUTPUT INSTEAD.ID before and this works fine when I do it as just an insert statement but how do I get the same result with a Stored Procedure. I have done the following but can't seem to get it to output correctly. CREATE PROCEDURE sp_XStream_Send -- Add the parameters for the stored procedure here #Dept VARCHAR(30), #Process VARCHAR, #RequestDT DATETIME, #RequestType VARCHAR, #RequestBranch INT, #RequestPolRef VARCHAR, #RequestXML VARCHAR, #ReturnID INT OUTPUT AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; DECLARE #OutputTbl TABLE (ID INT) INSERT INTO dbo.XStream_Log ( Department , Process , RequestDT , RequestType , RequestBranch , RequestPolicyRef , RequestXML ) OUTPUT INSERTED.ID INTO #OutputTbl(ID) VALUES ( #Dept, #Process, #RequestDT, #RequestType, #RequestBranch, #RequestPolRef, #RequestXML ) SELECT #ReturnID = ID FROM #OutputTbl RETURN END GO When i do the EXEC it wants me to send the #ReturnID but I don't want to Input anything into it, I want the output of the inserted ID. Any help, cheers. UPDATE I am executing my stored procedure like so: DECLARE #ID INT; EXEC dbo.sp_XStream_Send #Dept = 'IT', -- varchar(1) #Process = 'XStream Test', -- varchar(1) #RequestDT = '2016-05-09 09:28:38', -- datetime #RequestType = 'create-broomsrisk', -- varchar(1) #RequestBranch = 0, -- int #RequestPolRef = 'POMS01PC01', -- varchar(1) #RequestXML = '<TestXML></TestXML>', -- varchar(1) #ReturnID = #ID OUTPUT; I am just getting 'Command(s) completed successfully' and not the actual ID.
Returning Scope_Identity from 2 insert statements simultaneously in SQL Server
I am having problem with my stored procedure: CREATE PROCEDURE [dbo].[Project] #Code as nvarChar(255) = null, #Id as nvarChar(255) = null, #Status as nvarChar(max) = null, #Project as nvarChar(max) = null, #ClientSystem as nvarchar(max) = null, #UserId as bigint = 0, #ProjectId as bigint = 0, #ProjectDetailsId bigint = 0 Output AS SET NOCOUNT OFF; IF NOT EXISTS (SELECT [Code] FROM [dbo].[Project] WHERE Project.Code = #Code) BEGIN INSERT INTO [dbo].[Project]([Code], [Id], [Status], [Project]) VALUES(#Code, #Id, #Status, #Project) SELECT #ProjectId = SCOPE_IDENTITY() INSERT INTO [dbo].[ProjectDetails]([FK_ProjectId], [ClientSystem], [UserId]) VALUES(#ProjectId, #ClientSystem, #UserId) SELECT #ProjectDetailsId = SCOPE_IDENTITY() END ELSE BEGIN SELECT [ProjectId] AS 'ProjectId' FROM [dbo].[Project] WHERE Project.Code = #Code END I want to return Scope_Identity from both Insert statements and pass the values of first insert as parameter to 2nd Insert and return the Scope_Identity of 2nd Insert statement also. I am getting error is when I get the identity of first Insert, the identity in the specific table increases 2 times like in db table it will be inserted 2 but in coding it will return 1. And that return when i pass to other insert it s giving conflict.
Solution: Instead of using SCOPE IDENTITY(), you need to make use of he OUTPUTclause of the INSERT statement, like this: INSERT INTO [dbo].[Project]([Code], [Id], [Status], [Project]) OUTPUT inserted.ID into #ProjectID SELECT ... Explanation: SCOPE_IDENTITY() returns the value of the last insert, regardless where the insert takes place. So, when when another insert is running in parallel, then your call to SCOPE_IDENTITY() will return the value from the other parallel running procedure. This then leads to an error. However, the usage of the OUTPUT clause will guarantee to return the value from the current INSERT. Here is an interesting article regarding SCOPE_IDENTITY and parallel plans: http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/
You need use OUTPUT clause at the procedure parameter #ProjectId as bigint = 0 output,
SQL Server OUTPUT clause
I am a little stuck with why I can not seem to get the 'new identity' of the inserted row with the statement below. SCOPE_IDENTITY() just returns null. declare #WorkRequestQueueID int declare #LastException nvarchar(MAX) set #WorkRequestQueueID = 1 set #LastException = 'test' set nocount off DELETE dbo.WorkRequestQueue OUTPUT DELETED.MessageEnvelope, DELETED.Attempts, #LastException, GetUtcdate(), -- WorkItemPoisened datetime DELETED.WorkItemReceived_UTC INTO dbo.FaildMessages FROM dbo.WorkRequestQueue WHERE WorkRequestQueue.ID = #WorkRequestQueueID IF ##ROWCOUNT = 0 RAISERROR ('Record not found', 16, 1) SELECT Cast(SCOPE_IDENTITY() as int) Any assistance would be most appreciated. For now I use a workaround this like so. declare #WorkRequestQueueID int declare #LastException nvarchar(MAX) set #WorkRequestQueueID = 7 set #LastException = 'test' set nocount on set xact_abort on DECLARE #Failed TABLE ( MessageEnvelope xml, Attempts smallint, LastException nvarchar(max), WorkItemPoisened_UTC datetime, WorkItemReceived_UTC datetime ) BEGIN TRAN DELETE dbo.WorkRequestQueue OUTPUT DELETED.MessageEnvelope, DELETED.Attempts, #LastException, GetUtcdate(), -- WorkItemPoisened datetime DELETED.WorkItemReceived_UTC INTO #Failed FROM dbo.WorkRequestQueue WHERE WorkRequestQueue.ID = #WorkRequestQueueID IF ##ROWCOUNT = 0 BEGIN RAISERROR ('Record not found', 16, 1) Rollback END ELSE BEGIN insert into dbo.FaildMessages select * from #Failed COMMIT TRAN SELECT Cast(SCOPE_IDENTITY() as int) END
EDITED FEB'2013 #MartinSmith alerts us that this bug don't want be fixed by Microsoft. "Posted by Microsoft on 2/27/2013 at 2:18 PM Hello Martin, We investigated the issue and found that changing the behavior is not an easy thing to do. It would basically require redefining some of the behavior when both INSERT & OUTPUT INTO target has identity columns. Given the nature of the problem & the uncommon scenario, we have decided not to fix the issue. -- Umachandar, SQL Programmability Team" EDITED OCT'2012 This is caused by a bug: Testing bug: Quoting OUTPUT Clause doc: ##IDENTITY, SCOPE_IDENTITY, and IDENT_CURRENT return identity values generated only by the nested DML statement, and not those generated by the outer INSERT statement. After test it It seems that scope_identity() only works if outer operation is an insert in a table with identity columns: Test 1: Delete create table #t ( a char(1) ); create table #d ( a char(1), i int identity ); insert into #t values ('a'),('b'),('c'); delete #t output deleted.a into #d; select SCOPE_IDENTITY(), * from #d; a i ---- - - null a 1 null b 2 null c 3 Test 2: Inserting in outer table with identity create table #t ( a char(1), i int identity ); create table #d ( a char(1), i int identity ); insert into #t values ('x'),('x'),('x'); insert into #t output inserted.a into #d values ('a'),('b'); select scope_identity(), * from #d; a i - - - 2 a 1 2 b 2 Test 3: Inserting in outer table without identity create table #t ( a char(1) ); create table #d ( a char(1), i int identity ); insert into #t values ('x'),('x'),('x'); insert into #t output inserted.a into #d values ('a'),('b'); select scope_identity(), * from #d; a i ---- - - null a 1 null b 2
You might try to use a table variable for your output clause, thus allowing you to explicitly insert into FaildMessages: declare #WorkRequestQueueID int declare #LastException nvarchar(MAX) set #WorkRequestQueueID = 1 set #LastException = 'test' set nocount off -- Declare a table variable to capture output DECLARE #output TABLE ( MessageEnvelope VARCHAR(50), -- Guessing at datatypes Attempts INT, -- Guessing at datatypes WorkItemReceived_UTC DATETIME -- Guessing at datatypes ) -- Run the deletion with output DELETE dbo.WorkRequestQueue OUTPUT DELETED.MessageEnvelope, DELETED.Attempts, DELETED.WorkItemReceived_UTC -- Use the table var INTO #output FROM dbo.WorkRequestQueue WHERE WorkRequestQueue.ID = #WorkRequestQueueID -- Explicitly insert INSERT INTO dbo.FaildMessages SELECT MessageEnvelope, Attempts, #LastException, GetUtcdate(), -- WorkItemPoisened datetime WorkItemReceived_UTC FROM #output IF ##ROWCOUNT = 0 RAISERROR ('Record not found', 16, 1) SELECT Cast(SCOPE_IDENTITY() as int)