use stored procedure to select last item value - sql

i am trying to select the last record value from my database by using stored procedure, to do this i set my #UPID parameter as SCORE_IDENTITY(), but there are no output result as all after i execute my stored procedure
CREATE PROCEDURE [dbo].[spAuditLogSelect_NewUser]
#UPID int
AS
BEGIN
SET #UPID = SCOPE_IDENTITY()
SELECT
siUserProfile.UPID
,siUserProfile.ProfileType, siProfileType.RGDName AS ProfileTypeName
,siUserProfile.CBID, siCompany.ComName + ' - ' + siComBranch.ComBranchName AS CBName
,siUserProfile.FullName
,siUserProfile.ShortName
,siUserProfile.SerialCode
,siUserProfile.Serial
,siUserProfile.Gender
from siUserProfile WITH (NOLOCK)
inner join siUserProfileDetail WITH (NOLOCK) on siUserProfile.upid = siUserProfileDetail.UPID
left outer join siReferenceGroupDetail siProfileType WITH (NOLOCK) ON siUserProfile.ProfileType = siProfileType.RGDID
left outer join siComBranch WITH (NOLOCK) on siComBranch.CBID = siUserProfile.CBID
left outer join siCompany WITH (NOLOCK) ON siComBranch.CompanyID = siCompany.CompanyID
where siUserProfile.UPID = #UPID

SCOPE_IDENTITY() is meant to be used right after insert. It won't work in a different session.
To retrieve the latest entry, try top 1:
select top 1 *
...
where siUserProfile.UPID = #UPID
order by
siUserProfile.ID desc

You require to use IDENT_CURRENT(‘tablename’).
Please refer below link which illustrate difference between ##IDENTITY,SCOPE_IDENTITY() and IDENT_CURRENT(‘tablename’).
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
Hope this will help you.

I am assuming that you have some primary key(PK) in your table. Write the procedure, in that procedure fire the query
select * from Your_Table where PK_Column in(select max(PK_Column) from Your_Table)
This way you will be able to fetch the latest record from DB. By opening a cursor, you can play with record in your procedure.

Related

How do I display the count value of the results from one column in a new column?

This stored procedure returns two values but it repeats multiple times.
I am trying to get the count value of PLTGRN so that it shows up in a new column like in this image:
My code:
ALTER PROCEDURE[dbo].[GreenTire_Fits_In_Press]
#Press varchar(10)
AS
BEGIN
SELECT FAC,PLTGRN
FROM [TireTrack].[dbo].[cos_work] cosw WITH (nolock)
INNER JOIN [DataWarehouse].[dbo].[v_Curing_Tooling] CURE WITH (Nolock) ON Cure.MLDNBR = Cosw.MOLD
WHERE Cosw.FAC = #Press
END
I tried adding COUNT(PLTGRN) in the select statement to the code above but that throws this error :
you need to use GROUP BY :
ALTER PROCEDURE[dbo].[GreenTire_Fits_In_Press]
#Press varchar(10)
AS
BEGIN
Select PLTGRN , COUNT(*) QTY
FROM [TireTrack].[dbo].[cos_work] cosw with (nolock)
Inner Join [DataWarehouse].[dbo].[v_Curing_Tooling] CURE with (Nolock)
On Cure.MLDNBR=Cosw.MOLD
Where Cosw.FAC=#Press
GROUP BY PLTGRN
End
SUM is used with a GROUP BY clause. The aggregate functions summarize the table data. Once the rows are divided into groups, the aggregate functions are applied in order to return just one value per group. It is better to identify each summary row by including the GROUP BY clause in the query result.
ALTER PROCEDURE[dbo].[GreenTire_Fits_In_Press]
#Press varchar(10)
AS
BEGIN
SELECT FAC,PLTGRN, COUNT(PLTGRN)
FROM [TireTrack].[dbo].[cos_work] cosw WITH (nolock)
INNER JOIN [DataWarehouse].[dbo].[v_Curing_Tooling] CURE WITH (Nolock) ON Cure.MLDNBR = Cosw.MOLD
WHERE Cosw.FAC = #Press
GROUP BY FAC, PLTGRN
END
-- you are missing group by and the part of the query to get count
ALTER PROCEDURE[dbo].[GreenTire_Fits_In_Press]
#Press varchar(10)
AS
BEGIN
Select FAC,PLTGRN, count(*)
FROM [TireTrack].[dbo].[cos_work] cosw with (nolock)
Inner Join [DataWarehouse].[dbo].[v_Curing_Tooling] CURE with (Nolock)
On Cure.MLDNBR=Cosw.MOLD
Where Cosw.FAC=#Press
Group By FAC,PLTGRN
End

Slow SQL Update using sub query

Hi all … Wonder if anyone out there can help me with this one please.
I am running a query to update product categories against sales lines and need to back file a few million records so I wrote the query below to run for a specific order ID
DECLARE #ID INT
SET #ID = 659483
UPDATE [TradeSpace].[TradeSpace].[dbo].[SalesLine]
SET [ProductCategory] = [curSync].[pc_Cat]
FROM (SELECT [SC_ID],
[pc_cat]
FROM [MW_MereSys].[dbo].[MWSLines]
INNER
JOIN [MW_MereSys].[dbo].[MWProductCats]
ON [MWSLines].[pc_catref] = [MWProductCats].[pc_catref]
WHERE [sh_id] = #ID
) AS [curSync]
WHERE [SalesLine].[slID] = [curSync].[sc_id]
AND [salesline].[soid] = #ID
The sub SELECT runs in less than one second but the update has yet to finished (have left it for an hour at most). Indexes exist for [slID] and [soid] .. a manual update for one line takes less than one seconds but run like this (10 lines) is desperately slow.
Does anybody have any clues please. I've written plenty of queries like this and never had a problem … stumped :(
Your query rewritten with no changes:
UPDATE s SET
ProductCategory = curSync.pc_Cat
FROM TradeSpace.TradeSpace.dbo.SalesLine s
INNER JOIN
(
SELECT [SC_ID], [pc_cat]
FROM [MW_MereSys].[dbo].[MWSLines] l
INNER JOIN [MW_MereSys].[dbo].[MWProductCats] c ON l.[pc_catref] = c.[pc_catref]
WHERE [sh_id] = #ID
) AS [curSync]
on s.[slID] = [curSync].[sc_id]
WHERE s.[soid] = #ID
Are your sure everything is correct here? That single row from SalesLine always matches only one row from subquery?
Try this then. Will fail if this is not true. Original query would silently update same row with different values in same situation.
UPDATE s SET
ProductCategory = (
SELECT [pc_cat]
FROM [MW_MereSys].[dbo].[MWSLines] l
INNER JOIN [MW_MereSys].[dbo].[MWProductCats] c ON l.[pc_catref] = c.[pc_catref]
WHERE [sh_id] = #ID
AND [sc_id] = s.[slID]
)
FROM TradeSpace.TradeSpace.dbo.SalesLine s
WHERE s.[soid] = #ID
And please check estimated execution plan. Does it hit indexes?
We need other detail like a I mention in comments.
Your update is slow because of very high cardinality estimate when update table is join with Sub query result.
It may be because of wrong join and where predicate.
you can put the sub query result in #Temp table and try.Also you can create same index in #temp table.
DECLARE #ID INT
SET #ID = 659483
create #temp table([SC_ID] int,[pc_cat] int)
insert into #temp
SELECT [SC_ID],
[pc_cat]
FROM [MW_MereSys].[dbo].[MWSLines]
INNER JOIN [MW_MereSys].[dbo].[MWProductCats]
ON [MWSLines].[pc_catref] = [MWProductCats].[pc_catref]
WHERE [sh_id] = #ID
UPDATE SalesLine
SET [ProductCategory] = [curSync].[pc_Cat]
FROM [TradeSpace].[TradeSpace].[dbo].[SalesLine] as SalesLine
inner join #temp AS [curSync]
WHERE [SalesLine].[slID] = [curSync].[sc_id]
AND [salesline].[soid] = #ID
drop table #temp

Replacement of "IN" in stored procedure

I have huge store procedure. I only paste small part of this.
My Query:
--declare variable and Select Statement goes here
WHERE ((v.[RoleID] IN (
SELECT [dbo].[aspnet_UsersInRoles].roleid
FROM [dbo].[aspnet_UsersInRoles]
INNER JOIN [dbo].[aspnet_Users]
ON [dbo].[aspnet_Users].userid = [dbo].[aspnet_UsersInRoles].userid
WHERE
[dbo].[aspnet_Users].username = #UserName
UNION ALL
SELECT [RoleId]
FROM dbo.aspnet_roles
WHERE loweredrolename = 'anonymous user')
OR v.username = #UserName))
Query works perfect but its take long time to execute. There is so many condition inside WHERE condition with IN. I think the subquery inside IN take time. Is there any way to optimize this query and replace IN inside WHERE condition. Or suggest me an alternative way to optimize this type of query. Thanks.
Since the output of inner subquery is always the same. You can take that outside and insert those values into a temptable like below and u could just query to the temp table. So each time it doesnt go in a loop executing the same
`create table #temp(roleid int); `
` insert into #temp as (sSELECT [dbo].[aspnet_UsersInRoles].roleid
FROM [dbo].[aspnet_UsersInRoles]
INNER JOIN [dbo].[aspnet_Users]
ON [dbo].[aspnet_Users].userid = [dbo].[aspnet_UsersInRoles].userid
WHERE
[dbo].[aspnet_Users].username = #UserName
UNION ALL
SELECT [RoleId]
FROM dbo.aspnet_roles
WHERE loweredrolename = 'anonymous user');`
WHERE ((v.[RoleID] IN ( select roleid from #temp);
You could make a temp table with the result of the IN clause and join to it. This would break the problem to two much simpler tasks.
according to Orangecrush recommendation
--declare variable and Select Statement goes here
WHERE EXISTS (
SELECT 1
FROM [dbo].[aspnet_UsersInRoles]
INNER JOIN [dbo].[aspnet_Users]
ON [dbo].[aspnet_Users].userid = [dbo].[aspnet_UsersInRoles].userid
WHERE
[dbo].[aspnet_Users].username = #UserName
AND [dbo].[aspnet_UsersInRoles].roleid = v.[RoleID]
UNION ALL
SELECT 1
FROM dbo.aspnet_roles
WHERE loweredrolename = 'anonymous user'
AND dbo.aspnet_roles.roleid = v.[RoleID])
OR v.username = #UserName)

DB2 set default when null on join / Open table after FETCH

This is kind of a double question, just thinking of ways to accomplish my problem.
Also, I'm pretty new to DB2 and stored procedures, so bear with me.
I'm creating a stored procedure that gets a value from two tables using a Left Join statement. This will result in some of the values in the second table returning a null value (since they don't exist in tableB).
DECLARE CURSOR C1 WITH RETURN FOR
select a.name, a.title, b.order from tableA a
left outer join tableB b on a.name = b.name;
Now, I need some way to set these null values to a default value of 0.
The program I'm working with can do it ( CAST-IRON ) but if the result set is too large, it slows down the orchestrations and truncates the job log. So I'm trying to figure it out using the stored procedure.
My first thought was to use the FETCH INTO statement and a WHILE loop.
WHILE AT_END = 0 DO
FETCH C1 INTO CHNAME, CHTITLE, CHORDER;
IF CHORDER IS NULL
THEN SET CHORDER = 0;
END IF;
IF SQLCODE = 100
THEN SET AT_END = 1;
END IF;
END WHILE;
But it seems like that would require a temporary table being created, and declaring another cursor with that table, using an insert command after the 'FETCH INTO'. So I was wondering if there were another way to do this, or to automatically set a default in the select statement?
Set a default in the select statement using COALESCE.
DECLARE CURSOR C1 WITH RETURN FOR
select a.name, a.title, COALESCE(b.order,0) as order
from tableA a
left outer join tableB b on a.name = b.name;

How can I select none duplicate rows with inner join?

My MS SQL Server stored procedure is:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_close]
#DATE NVARCHAR(8)
AS
BEGIN
SELECT appointment_datas.appointment_date
,appointment_datas.appointment_no
,costumer_datas.costumer_name
,appointment_datas.appointment_type
,personel_datas.personel_ADI
FROM [LONI].[dbo].appointment_datas
INNER JOIN [LONI].[dbo].costumer_datas ON appointment_datas.appointment_costumer = costumer_datas.costumer_id
INNER JOIN [LONI].[dbo].personel_datas ON appointment_datas.appointment_personel = personel_datas.personel_id
INNER JOIN [GUONU].[dbo].dayend ON appointment_datas.appointment_no <> dayend.appointment_no COLLATE Turkish_CI_AS
WHERE CONVERT(nvarchar(8),appointment_datas.appointment_date,112) = #DATE
END
With this code, I select duplicate rows from the same records. Actually I want to select fields from [LONI].[dbo].appointment_datas but if appointment_no
is not in [GUONU].[dbo].dayend
SELECT DISTINCT removes duplicates in your output.
But your SQL looks wrong. Are you sure you mean to write:
TABLE1.FIELD1 <> TABLE1.FIELD1
This always evaulates to false. I think you may have an error in your SQL, and that might be why you are getting duplicate values. You should rarely use <> in a join clause, and you shouldn't have the same field on both sides.
Maybe you intended:
ON [DB1].[dbo].TABLE1.FIELD1 <> [DB2].[dbo].TABLE1.FIELD1
but this will generate a Cartesian product of all the rows that don't match. I doubt this is what you really mean. Perhaps you want this:
ON [DB1].[dbo].TABLE1.ID = [DB2].[dbo].TABLE1.ID
WHERE[DB1].[dbo].TABLE1.FIELD1 <> [DB2].[dbo].TABLE1.FIELD1
This matches the rows from each database that have the same ID, but differ in a certain column. Notice that the <> is not in the JOIN clause.
--- UPDATE ---
Perhaps you mean to select the results from the two different databases and then union them?
SELECT appointment_datas.appointment_date
,appointment_datas.appointment_no
,costumer_datas.costumer_name
,appointment_datas.appointment_type
,personel_datas.personel_ADI
FROM [LONI].[dbo].appointment_datas
INNER JOIN [LONI].[dbo].costumer_datas ON appointment_datas.appointment_costumer = costumer_datas.costumer_id
INNER JOIN [LONI].[dbo].personel_datas ON appointment_datas.appointment_personel = personel_datas.personel_id
WHERE CONVERT(nvarchar(8),appointment_datas.appointment_date,112)
UNION
SELECT appointment_datas.appointment_date
,appointment_datas.appointment_no
,costumer_datas.costumer_name
,appointment_datas.appointment_type
,personel_datas.personel_ADI
FROM [GUONU].[dbo].appointment_datas
INNER JOIN [GUONU].[dbo].costumer_datas ON appointment_datas.appointment_costumer = costumer_datas.costumer_id
INNER JOIN [GUONU].[dbo].personel_datas ON appointment_datas.appointment_personel = personel_datas.personel_id
WHERE CONVERT(nvarchar(8),appointment_datas.appointment_date,112)
--- SOLUTION ---
Use NOT EXISTS in WHERE clause. Read comments to see why.
The line
INNER JOIN [DB2].[dbo].TABLE1 ON TABLE1.FIELD1 <> TABLE1.FIELD1
makes no sense, you want to rephrase that...
If I understand your question correctly (after your edit)
but if appointment_no is not in
[GUONU].[dbo].dayend
, you actually want a NOT EXISTS subquery:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_close]
#DATE NVARCHAR(8)
AS
BEGIN
SELECT appointment_datas.appointment_date
,appointment_datas.appointment_no
,costumer_datas.costumer_name
,appointment_datas.appointment_type
,personel_datas.personel_ADI
FROM [LONI].[dbo].appointment_datas
INNER JOIN [LONI].[dbo].costumer_datas ON appointment_datas.appointment_costumer = costumer_datas.costumer_id
INNER JOIN [LONI].[dbo].personel_datas ON appointment_datas.appointment_personel = personel_datas.personel_id
WHERE CONVERT(nvarchar(8),appointment_datas.appointment_date,112) = #DATE
AND NOT EXISTS (SELECT 'X' FROM [GUONU].[dbo].dayend WHERE dayend.appointment_no = appointment_datas.appointment_no)
END
SELECT DISTINCT TABLE1.FIELD1
,TABLE2.FIELD1
,TABLE1.FIELD3
,TABLE3.FIELD1
FROM ...
NB in some variants you will have to bracket the field list ie
SELECT DISTINCT (TABLE1.FIELD1
,TABLE2.FIELD1
,TABLE1.FIELD3
,TABLE3.FIELD1 ) FROM ...