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)

Resources