Sql Server - Merge Statement - tsql

The following stored procedure is not performing good. i wanted to change it into a Merge Statement. How do i do it? I have not used the Merge Statement before. Please help
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[pa_CPE_TUA_RD]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[pa_CPE_TUA_RD]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[pa_CPE_TUA_RD]') AND type in (N'P', N'PC'))
BEGIN
CREATE PROCEDURE [dbo].[pa_CPE_TUA_RD]
AS
-- This procedure moves RewardDistribution records from UploadTemp_RD
SET NOCOUNT ON;
declare #NumRecs int;
select #NumRecs=count(*) from CPE_UploadTemp_RD with (NoLock) where WaitingACK=-5;
if #NumRecs=0 begin
set rowcount 1800;
update CPE_UploadTemp_RD with (RowLock) set WaitingACK=-5;
set rowcount 0;
end
-- Move records to CPE_RewardDistribution
insert into CPE_RewardDistribution with (RowLock) (LocalID, ServerSerial, LocationID, IncentiveID, RewardOptionID, Phase, CustomerPK, DistributionDate, LogixTransNum, PresentedCustomerID, PresentedCardTypeID, ResolvedCustomerID, HHID, Deleted, LastUpdate, WaitingACK, LastServerID, POSTimeStamp)
select Col1, Col2, Col9, Col3, Col4, Col5, Col6, Col7, Col8, Col10, Col11, Col12, Col13, 0 as Deleted, getdate() as LastUpdate, -5 as WaitingACK, ServerSerial as LastServerID, POSTimeStamp from CPE_UploadTemp_RD with (NoLock)
where WaitingACK=-5;
-- Move records to CPE_RD_Output
insert into CPE_RD_Output with (RowLock) (LocalID, ServerSerial, IncentiveID, RewardOptionID, Phase, CustomerPK, DistributionDate, Deleted, LastUpdate, WaitingACK, TargetLocationID, POSTimeStamp)
select BT.Col1 as LocalID, BT.Col2 as ServerSerial, BT.Col3 as IncentiveID, BT.Col4 as RewardOptionID, BT.Col5 as Phase, BT.Col6 as CustomerPK, BT.Col7 as DistributionDate,
0 as Deleted, getdate() as LastUpdate, 0 as WaitingACK, CL.LocationID as TargetLocationID, BT.POSTimeStamp as POSTimeStamp
from CPE_UploadTemp_RD as BT with (NoLock) Inner Join CustomerLocations as CL with (NoLock) on BT.Col6=CL.CustomerPK and not(CL.LocationID=BT.LocationID) and BT.WaitingACK=-5;
Delete from CPE_UploadTemp_RD with (RowLock) where WaitingACK=-5;
END
GO
GRANT EXECUTE ON [dbo].[pa_CPE_TUA_RD] TO [Copient_Logix_uspRole] AS [dbo]
GO

Related

Postgres - SELECT FOR UPDATE with union all

I am trying to put row level lock on a table in one postgres function.
do $$
declare tabname text :='locktest' ;
begin
execute 'create temp table temp1 as
select v.* from (
select row_number() over (partition by a.id) as row_num,a.*
from '||tabname||' a,locktest2 b where a.id=b.id and b.val=111
union all
select row_number() over (partition by a.id) as row_num,a.*
from '||tabname||' a,locktest2 b where a.id=b.id and b.val=222
)v where v.row_num=1 for update';
raise notice 'Completed';
end $$;
But while compiling it , getting below error.
ERROR: FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT
Please suggest.
The way the statement is written, the database does not know in which table to lock the rows.
Rewrite the query along these lines:
SELECT ... FROM
(SELECT ...
FROM tab1
WHERE ...
FOR NO KEY UPDATE) AS t1
UNION ALL
(SELECT ...
FROM tab2
WHERE ...
FOR NO KEY UPDATE) AS t2;
FOR NO KEY UPDATE is the correct lock if you plan to update. FOR UPDATE is the lock if you intend to delete.

Issue with PK violation on insert

I have a scenario where almost all of the tables have issues with the PK value as follows. This results is a database error or the violation of the PK insert.
When using the DBCC CheckIdent it displays an inconsistency between the next value and the current one.
Can anyone have a reason for the mismatch happening on several tables?
Since this database is then replicate, I'm afraid this error will propagate across the environment.
I adapted this script to fix it, but really trying to figure out the root of the problem.
/** Version 3.0 **/
if object_id('tempdb..#temp') is not null
drop table #temp
;
with cte as (
SELECT
distinct
A.TABLE_CATALOG AS CATALOG,
A.TABLE_SCHEMA AS "SCHEMA",
A.TABLE_NAME AS "TABLE",
B.COLUMN_NAME AS "COLUMN",
IDENT_SEED (A.TABLE_NAME) AS Seed,
IDENT_INCR (A.TABLE_NAME) AS Increment,
IDENT_CURRENT (A.TABLE_NAME) AS Curr_Value
, DBPS.row_count AS NumberOfRows
FROM INFORMATION_SCHEMA.TABLES A
inner join INFORMATION_SCHEMA.COLUMNS B on b.TABLE_NAME = a.TABLE_NAME and b.TABLE_SCHEMA = a.TABLE_SCHEMA
inner join sys.identity_columns IC on OBJECT_NAME (IC.object_id) = a.TABLE_NAME
inner join sys.dm_db_partition_stats DBPS ON DBPS.object_id =IC.object_id
inner join sys.indexes as IDX ON DBPS.index_id =IDX.index_id
WHERE A.TABLE_CATALOG = B.TABLE_CATALOG AND
A.TABLE_SCHEMA = B.TABLE_SCHEMA AND
A.TABLE_NAME = B.TABLE_NAME AND
COLUMNPROPERTY (OBJECT_ID (B.TABLE_NAME), B.COLUMN_NAME, 'IsIdentity') = 1 AND
OBJECTPROPERTY (OBJECT_ID (A.TABLE_NAME), 'TableHasIdentity') = 1 AND
A.TABLE_TYPE = 'BASE TABLE'
)
select 'DBCC CHECKIDENT ('''+A.[SCHEMA]+'.'+a.[TABLE]+''', reseed)' command
, ROW_NUMBER() OVER(ORDER BY a.[SCHEMA], a.[TABLE] asc) AS ID
, A.Curr_Value
, a.[TABLE]
into #temp
from cte A
ORDER BY A.[SCHEMA], A.[TABLE]
declare #i int = 1, #count int = (select max(ID) from #temp)
declare #text varchar(max) = ''
select #COUNT= count(1) FROM #temp
WHILE #I <= #COUNT
BEGIN
SET #text = (SELECT command from #temp where ID=#I)
EXEC (#text + ';')
print #text
select Curr_Value OldValue, ident_current([TABLE]) FixValue, [TABLE] from #temp where ID=#I
SET #I = #I + 1
SET #text='';
END
go
maybe someone or something with enough permissions made a mistake by reseeding?
As simple as this:
create table testid (
id int not null identity (1,1) primary key,
data varchar (3)
)
insert into testid (data) values ('abc'),('cde')
DBCC CHECKIDENT ('testid', RESEED, 1)
insert into testid (data) values ('bad')

T-SQL - populating data in temp table in stored procedure.

I need help with my stored procedure which I'm currently working on. Basically stored procedure works fine and gets me required data. I would like to keep this funcionality and add new temporary table within stored procedure and populate this temp table with the data that I get.
I don't know where/and how should I use INSERT INTO SELECT statement or SELECT INTO in my particular stored procedure.
Below I'm submiting my symplified stored procedure :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetHourReportData]
#dateFrom SMALLDATETIME,
#dateTo SMALLDATETIME,
#hourFrom INT,
#hourTo INT
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE tempTable
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
END
Thanks. Any help will be appreciated.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetHourReportData]
#dateFrom SMALLDATETIME,
#dateTo SMALLDATETIME,
#hourFrom INT,
#hourTo INT
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #tempTable --notice the #
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
END
CREATE TABLE tempTable
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
ELSE
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
END
select * from tempTable

getting distinct rows based on two column values

I am trying to get distinct rows from a temporary table and output them to an aspx page. I am trying to use the value of one column and get the last entry made into that column.
I have been trying to use inner join and max(). However i have been unsuccessful.
Here is the code i have been trying to do it with.
Declare #TempTable table (
viewIcon nvarchar(10),
tenderType nvarchar(20),
diaryIcon int,
customerName nvarchar(100),
projectName nvarchar(100),
diaryEntry nvarchar(max),
diaryDate nvarchar(20),
pid nvarchar(20)
)
insert into #TempTable(
viewIcon,
tenderType,
diaryIcon,
customerName,
projectName,
diaryEntry ,
diaryDate ,
pid
)
select p.viewicon,
p.[Tender Type],
1 diaryicon,
c.[Customer Name],
co.[Last Project],
d.Action,
co.[Diary Date],
p.PID
From Projects2 p Inner Join
(select distinct Pno, max(convert(date,[date of next call],103)) maxdate from ProjectDiary group by Pno
) td on p.PID = td.Pno
Inner Join contacts3 co on co.[Customer Number] = p.[Customer Number]
Inner Join Customers3 c on p.[Customer Number] = c.[Customer Number]
Inner Join ProjectDiary d on td.Pno = d.Pno
Where CONVERT(Date, co.[Diary Date], 103) BETWEEN GETDATE()-120 AND GETDATE()-60
DECLARE #contactsTable TABLE
(pid nvarchar(200),
diaryDate date)
insert into #contactsTable (t.pid, t.diarydate)
select distinct pid as pid, MAX(CONVERT(DATE, diaryDate, 103)) as diaryDate from # TempTable t group by pid
DECLARE #tempContacts TABLE
(pid nvarchar(200))
insert into #tempContacts(pid)
select pid from #contactsTable
DECLARE #tempDiaryDate TABLE (diaryDate date)
insert into #tempDiaryDate(diaryDate)
select distinct MAX(CONVERT(DATE, diaryDate, 103)) from #TempTable
select t.* from #TempTable t inner join (select distinct customerName, M AX(CONVERT(DATE, diaryDate, 103)) AS diaryDate from #TempTable group by customerName) tt on t t.customerName=t.customerName
where t.pid not in
(select Pno from ProjectDiary where convert(date,[Date Of Next Call],103) > GETDATE())
and t.viewIcon <> '098'
and t.viewIcon <> '163'
and t.viewIcon <> '119'
and t.pid in (select distinct pid from #tempContacts)
and CONVERT(DATE, t.diaryDate, 103) in (select distinct CONVERT(DATE, diaryDate, 103) f rom #tempDiaryDate)
order by CONVERT(DATE, tt.diaryDate, 103)
I am trying to get all the distinct customerName's using the max date to determine which record it uses.
Use a subquery. Without going through your entire sql statement, the general idea is:
Select [Stuff]
From table t
Where date = (Select Max(Date) from table
where customer = t.customer)

Stored procedure to delete rows - SQL Server 2008 R2

I have written a stored procedure that only allowed to have 100 rows with same CustomerPK, so if we want to insert row 101, the oldest row with the same CustomerPK needs to be deleted.
I'm sure there are several ways of doing this and I'm not sure which one is best. Here is the code for the procedure.
DECLARE
#TokenCount INT;
SELECT
#TokenCount = COUNT(*)
FROM
CustomerAuthTokens
WHERE
CustomerPK = #CustomerPK;
IF #TokenCount > 99
BEGIN
DELETE FROM CustomerAuthTokens
WHERE AuthToken IN (SELECT TOP(#TokenCount - 99) AuthToken
FROM CustomerAuthTokens
WHERE CustomerPK = #CustomerPK
ORDER BY TokenCreateTime ASC);
END
--Insert your row first
-- This will delete customer rows if there are more than 100 rows for that customer
;WITH cte as
(
SELECT row_number() over (partition by CustomerPK order by TokenCreateTime desc) rn
FROM CustomerAuthTokens
WHERE CustomerPK = #CustomerPK
)
DELETE CTE
WHERE rn > 100