SQL - Getting Updated Value - sql

I use Sql Server 2008.
I have a table that generates ID.
I want to retrieve the generated ID and store it in a bigint variable.
How can I do it?
Here is the Stored Proc that gives the ID as result set. But I cannot store it in a bigint variable.
ALTER PROC SCN.TRANSACTION_UNIQUE_ID_SELECT
AS
UPDATE COR.TRANSACTION_UNIQUE_ID
SET ID = ID + 1
OUTPUT INSERTED.ID AS ID

If you want to use output you can;
declare #ID table (ID bigint)
update the_table
set ID = ID + 1
output INSERTED.ID into #ID
declare #bi bigint = (select ID from #ID)

The BigInt should be an identity insert column, this will make SQL Server automatically generate bigints in sequence for you. Just pass the rowID as an OUTPUT parameter and set it before the procedure ends after the insert/update.
Then you can read it coming back and set it as needed.
The stored procedure could look something like this (I've only included the rowID for clarity):
CREATE PROCEDURE [Sample].[Save]
(
#rowID bigint OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
--Do your insert/update here
--Set the RowID
SET #rowID = (SELECT SCOPE_IDENTITY())
END

That UPDATE looks fishy...it will increment every ID in your table by one, no?
Anyway, variables have an #sign, so just SET #myvar = ...whatever...

Use OUTPUT INTO:
DECLARE #TblID TABLE ( ID int )
UPDATE COR.TRANSACTION_UNIQUE_ID
SET ID = ID + 1
OUTPUT INSERTED.ID INTO #TblID (ID) --the output values will be inserted
--into #TblID table-variable

DECLARE #id BIGINT
EXEC #id = SCN.TRANSACTION_UNIQUE_ID_SELECT

Related

Update statement, update value is conditionally evaluated

I have the below pseudo code written that I want to implement in T-SQL. I need this code included in an existing stored procedure, I was trying to achieve the below with function call passing in a temp table as a parameter, is it possible to pass a temp table as a function parameter. Please let me know if there is a better approach to this.
Table: #Temp_Table has a column RefId which refers to #TempReadUpdateValue.Id. There are rules to identify if the #TempReadUpdateValue.Id can be applied to #Temp_Table.RefId.
Rule 1: the data qualifies in the DateRange
Rule 2: the #TempReadUpdateValue.Id is available if (Allowed - Used) > 0.
Allowed is fixed value and used will increment as its assigned.
I want to achieve the above with an UPDATE statement on Temp_Table, the challenge that I face is #Temp_Table.RefId = #TempReadUpdateValue.Id, need to increment
#TempReadUpdateValue.Used = #TempReadUpdateValue.Used + #Temp_Table.Units
every next row in #Temp_Table need to re-evaluate rules #1 and #2 for RefId assignment.
Update statement:
DECLARE #OLD INT = 0; -- THIS CAN ALSO BE SET TO 1, basically passed in as param to the stored procedure.
CREATE TABLE #TempReadUpdateValue
(
Id INT,
From_Date DateTime,
Thru_Date DateTime,
Allowed int,
Used int
)
CREATE TABLE #Temp_Table
(
Pk_ID INT,
DOS DateTime,
Units Int,
Ref_Id int
)
UPDATE #Temp_Table
SET Ref_Id = CASE
WHEN #OLD = 0 THEN 121
ELSE NewImplementation(DOS, Units, #TempReadUpdateValue)
END
CREATE OR ALTER FUNCTION NewImplementation
(#DOS DATETIME, #Units INT, #TempReadUpdateValue)
RETURNS INT
AS
BEGIN
DECLARE #Id INT
DECLARE #Allowed INT
DECLARE #Used INT
SELECT
#Id = Id,
#Allowed = Allowed,
#Used = Used
FROM
#TempReadUpdateValue
DECLARE #ReturnValue INT = 0
IF (#Id > 0) AND (#Allowed - #Used ) > 0
BEGIN
#ReturnValue = #Id;
UPDATE #TempReadUpdateValue
SET Used = (Used + #Units);
END
RETURN #ReturnValue
END

Finding MAX value of data type Varchar

Firstly I have a table tblSample with ID as column of datatype INT. To auto generate ID for every transaction, I created a stored procedure:
DECLARE #Id INT
SELECT #Id = MAX(Id)
FROM tblSample
IF #Id IS NULL
BEGIN
SELECT 0 as Id
END
ELSE
SELECT MAX(Id) as ID FROM tblSample
Here as you observe if ID has no rows MAX(Id)=0 then return 0 or else return MAX(ID) value so that next insertion will be greater than max(ID).
That's fine but now I had column ID with datatype VARCHAR I have to do similar operation how can I that?
The code looks fine so it should work with VARCHAR also but my suggestion is to use storage variable also with same datatype so it won't get conflicted anywhere in the operation:
DECLARE #Id VARCHAR(10)
I think you could use MAX(CAST(varcharcolumn AS Int))
DECLARE #Id INT
SELECT #Id=MAX(Id) FROM tblSample
IF #Id IS NULL
BEGIN
SELECT 'Your_VarCharValue' + CAST(0 AS VARCHAR) as Id
END
ELSE
SELECT 'Your_VarCharValue' + CAST(MAX(Id) AS VARCHAR) as ID FROM tblSample

Collect id's of ALL inserted records as result set

I need a stored procedure which returns resultset of IDs for created records. I've already read that SCOPE_IDENTITY gives only last ID. but my SQL skill is not enough to solve this particular case and get all IDs as the output.
here's what I have for now - this only gets the last record's id
USE AdventureWorks2008;
DELETE FROM [HumanResources].[Shift] where [HumanResources].[Shift].Name='c' or [HumanResources].[Shift].Name='d'
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'ShiftUpdateXml')
DROP PROCEDURE ShiftUpdateXml
GO
CREATE PROCEDURE ShiftUpdateXml
#strXML XML, #ShiftID [tinyint] = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT [HumanResources].[Shift](Name,StartTime,EndTime) SELECT
TEMP.Name,TEMP.StartTime,TEMP.EndTime
FROM (SELECT
assignreassignro.value('Name[1]','nvarchar(50)') AS Name,
assignreassignro.value('StartTime[1]','time(7)') AS StartTime,
assignreassignro.value('EndTime[1]','time(7)') AS EndTime
FROM #strXML.nodes('documentelement/assignreassignro')Documentelement(assignreassignro)) AS TEMP
SET #ShiftID = SCOPE_IDENTITY();
END
GO
DECLARE #ShiftID INT;
DECLARE #XmlVal XML= '<?xml version="1.0"?>
<documentelement>
<assignreassignro>
<Name>c</Name>
<StartTime>10:30:00.0000000</StartTime>
<EndTime>17:30:00.0000000</EndTime>
</assignreassignro>
<assignreassignro>
<Name>d</Name>
<StartTime>11:00:00.0000000</StartTime>
<EndTime>18:00:00.0000000</EndTime>
</assignreassignro>
</documentelement>'
EXEC ShiftUpdateXml #XmlVal,#ShiftID = #ShiftID OUTPUT;
PRINT #ShiftID;
You are looking for the output clause. If you just want the ids, you can do:
DECLARE #ids TABLE (id int);
INSERT [HumanResources].[Shift](Name,StartTime,EndTime)
OUTPUT inserted.Id INTO #ids
SELECT assignreassignro.value('Name[1]', 'nvarchar(50)') AS Name,
assignreassignro.value('StartTime[1]', 'time(7)') AS StartTime,
assignreassignro.value('EndTime[1]', 'time(7)') AS EndTime
FROM #strXML.nodes('documentelement/assignreassignro') Documentelement(assignreassignro);
If you want additional values, you can add them to the table and the INSERT statement.
Also, note that you do not need a subquery for the SELECT.
To get multiple rows you'll need to use output from the table inserted with something like this:
CREATE PROCEDURE ShiftUpdateXml
#strXML XML
AS
BEGIN
INSERT [Shift](Name,StartTime,EndTime)
output inserted.id
SELECT
TEMP.Name,TEMP.StartTime,TEMP.EndTime
FROM (SELECT
assignreassignro.value('Name[1]','nvarchar(50)') AS Name,
assignreassignro.value('StartTime[1]','time(7)') AS StartTime,
assignreassignro.value('EndTime[1]','time(7)') AS EndTime
FROM #strXML.nodes('documentelement/assignreassignro')Documentelement(assignreassignro)) AS TEMP
END
That way the procedure will return the list of IDs. I made an example into SQL Fiddle

Save Exec results in variable

I already have a stored procedure GET_ROW that is doing a select, according to input ID:
SELECT TOP 1 *
FROM MyTable
WHERE ID = #ID
Now, I want to create another stored procedure that checks if an #ID exists. If it exists, return the existing row. Otherwise, create a new row with the requested #ID and return it.
So, I'm thinking of something like this:
Declare ResRow
begin tran
ResRow = Exec GET_ROW #ID
if exists (ResRow)
return ResRow
else
Insert into ...
return Exec GET_ROW #ID
commit
After executing this code, I want to be sure that only one row with #ID exists in the database (no duplicated row with same ID)
You must create table variable in first and then use following query:
Declare #T Table(Col1 int, Col2 int ,...)
Insert Into #T
Exec Get_Row #ID
Select * From #T
How about this:
CREATE PROCEDURE dbo.InsertOrFetch #ID INT
AS
BEGIN
-- check if it doesn't exist yet
IF NOT EXISTS (SELECT * FROM dbo.MyTable WHERE ID = #ID)
INSERT INTO dbo.MyTable(ID)
VALUES (#ID)
-- now return the row
SELECT TOP (1) *
FROM dbo.MyTable
WHERE ID = #ID
END
If you first check if the row doesn't exist it, and if so, insert the new data - then the SELECT afterwards will always return the row (pre-existing or newly inserted) to you.

Adding column to a resultset in stored procedure

I'm working on SP, I want to add a column to a resultset. Normally this would not be a proble, but here I'm using an Exec to fill one temp-table. To that temp-table I want to add one column.
Some prestuff that puts data in one of the temp-tables with some conditions
declare #RowCount int
set #RowCount = 1
create table #Temp_HS (row int IDENTITY (1, 1) NOT NULL, h varchar(30))
Create table #tmpS (K varchar(100),
U varchar(100), Counter int, H varchar(100))
--Puts data in one temp_table with employees
insert into #Temp_HS (h)
select Login from database.dbo.Users
where Old <> 1
and TC in ('A_1', 'A_2')
and Login not in ('Steve', 'Peter', 'Gabs')
--Declaring my counter here, it sets the MaxRow which is 19 in this case
declare #Counter int
set #Counter = (select Max(row) from #Temp_HS)
select * from #Temp_HS
-- Looping, That my RowCount must be less or Equal to Counter which is 19.
while #RowCount <= #Counter
begin
Set User which was originally from the Database Login which is declared as H in the temp table.
declare #user varchar(30)
select #user = h from #Temp_HS where row = #RowCount
Here comes the tricky part, this is the Stored procedure that inserts 3 columns into a temp
table, here I want to add one colum which in this case is h from Temp_HS to the resultset.
INSERT INTO #tmpS
EXEC Database.dbo.getListCount #user,
param,
param,
param,
'something',
param
set #RowCount = #RowCount +1
end
drop table #Temp_HS
If you need any further information just ask! :)
Basically I want to add one more column to the results of my Exec SP that inserts the result into a temp_table
INSERT INTO .. EXEC requires that the table you are inserting into already exists, e.g.
-- Given this preexisting proc
CREATE PROC dbo.getListCount #user INT, -- other params
AS
SELECT #User as Col1,
'SomeVarChar' as Col2
FROM [SomeTable];
-- In your code, create the temp table to hold the data
CREATE TABLE #tmpS
(
Col1 INT,
Col2 NVARCHAR(100),
NewColumnH VARCHAR(30) -- Add the additional column up front
-- etc.
);
This is called as
INSERT INTO #tmpS(Col1, Col2)
EXEC dbo.getListCount, #User;
If you then need to do do further processing on your temp table, do this after the PROC call:
UPDATE ts
SET NewColumnH = t.h
FROM #tmpS ts INNER JOIN #Temp_HS th on th.row = #RowCount;
Actually inner join doesnt work as desireed on temp tables that is why I used this solution. Since I already had #User in a variable I choose to do this update instead.
UPDATE ts
SET NewColumnH = #User
FROM #tmpS ts
where ts.Column is null