I have the following SQL script. As you can see I manually set the #listingid value to 30653.
But this script should be executed for all records in the [listings] table where #listingid is assigned the value of the [listings].id column.
DECLARE #profname nvarchar(150)
DECLARE #furl nvarchar(250)
DECLARE #city nvarchar(250)
DECLARE #listingid int
set #listingid=30653
--select the top 1 professionname
SELECT TOP 1 #profname=REPLACE(LOWER(pn.title),' ','-'),#furl=l.friendlyurl,#city=REPLACE(REPLACE(LOWER(l.city),'''',''),' ','-') FROM healthprof_professionnames hpn
INNER JOIN professionname pn ON pn.id=hpn.professionnameid
INNER JOIN listings l on l.id=hpn.healthprofid
WHERE l.id=#listingid ORDER BY pn.title
--check if current friendlyurl already contains profession
IF NOT CHARINDEX(#profname,#furl)>0
SET #furl = #furl + '-' + #profname
IF NOT CHARINDEX(#city,#furl)>0
SET #furl = #furl + '-' + #city
SET #furl = #furl + '-3'
UPDATE listings set friendlyurl=#furl WHERE id=#listingid
You can use a cursor to loop over every row in a result set:
declare cur cursor for
select distinct id from listings
declare #listingid int
open cur
fetch next from cur into #listingid
while ##FETCH_STATUS = 0
BEGIN
-- your code from above goes here
fetch next from cur into #listingid
END
That being said, I agree with Tim's comment above. Rewrite it to work in one set-based operation if at all possible. I think this will work, but I haven't tested it:
;WITH vars AS (
SELECT id, profname, furl, city
FROM (
SELECT l.id,
REPLACE(LOWER(pn.title),' ','-') as profname,
l.friendlyurl as furl,
REPLACE(REPLACE(LOWER(l.city),'''',''),' ','-') as city,
ROW_NUMBER() OVER (PARTITION BY l.id ORDER BY pn.title) as rnk
FROM healthprof_professionnames hpn
INNER JOIN professionname pn ON pn.id=hpn.professionnameid
INNER JOIN listings l on l.id=hpn.healthprofid
) A
WHERE A.rnk = 1
),
vars2 AS (
SELECT id,
CASE WHEN NOT CHARINDEX(profname, furl) > 0
THEN furl + '-' + profname ELSE furl END as furl,
city
FROM vars
),
vars3 as (
SELECT id,
CASE WHEN NOT CHARINDEX(city, furl) > 0
THEN furl + '-' + city ELSE furl END as furl
FROM vars2
)
UPDATE listings SET friendlyurl = vars3.furl + '-3'
FROM listings INNER JOIN vars3 on vars3.id = listings.id
Related
Is it possible to get the max value of a single column which exists in the majority of tables within several different schemas?
If this were one or two tables, I could easily use:
SELECT 'schema1.table1' as rowsource, category, max(date_used) max_date_used from schema1.table1 group by category
UNION ALL
SELECT 'schema1.table2' as rowsource, category, max(date_used) max_date_used from schema1.table2 group by category
UNION ALL
SELECT 'schema2.table3' as rowsource, category, max(date_used) max_date_used from schema2.table3 group by category
UNION ALL
SELECT 'schema3.table4' as rowsource, category, max(date_used) max_date_used from schema3.table4 group by category
However, I am looking at having to query nearly 300 tables across 3 different schemas.
TIA for any advice/insight!
You could try to store all your required table from informationSchema into a temp table, then use Dynamic SQL to go through each one of it. For example
DROP TABLE IF EXISTS #Temp
CREATE TABLE #temp ---identity column will be used to iterate
(
id INT IDENTITY,
TableName VARCHAR(50),
SchemaName VARCHAR(20)
)
INSERT INTO #temp
SELECT TABLE_NAME,TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
-- choose your own results with where conditions
DECLARE #SQL VARCHAR(MAX) = ''
DECLARE #Count INT = 1
DECLARE #SchemaName VARCHAR(20)
DECLARE #Table VARCHAR(20)
WHILE #COUNT <= (SELECT COUNT(*) FROM #temp)
BEGIN
SELECT #SchemaName = SchemaName FROM #temp WHERE id = #Count
SELECT #table = TABLENAME FROM #temp WHERE id = #Count
SELECT #sql = #sql + 'SELECT category, max(date_used) max_date_used from ' + #SchemaName + '.' + #Table + ' group by category
UNION ALL '
SET #Count = #Count + 1
END
PRINT LEFT((#SQL),LEN(#SQL) - LEN('UNION ALL '))
After you check the printed result, change it to EXEC if you think that is correct for you.
I need to separate values and store them in different variables in SQL,
for example
a='3100,3101,3102,....'
And the output should be
x=3100
y=3101
z=3102
.
.
.
create function [dbo].[udf_splitstring] (#tokens varchar(max),
#delimiter varchar(5))
returns #split table (
token varchar(200) not null )
as
begin
declare #list xml
select #list = cast('<a>'
+ replace(#tokens, #delimiter, '</a><a>')
+ '</a>' as xml)
insert into #split
(token)
select ltrim(t.value('.', 'varchar(200)')) as data
from #list.nodes('/a') as x(t)
return
end
GO
declare #cad varchar(100)='3100,3101,3102'
select *,ROW_NUMBER() over (order by token ) as rn from udf_splitstring(#cad,',')
token rn
3100 1
3101 2
3102 3
The results of the Parse TVF can easily be incorporated into a JOIN, or an IN
Declare #a varchar(max)='3100,3101,3102'
Select * from [dbo].[udf-Str-Parse](#a,',')
Returns
RetSeq RetVal
1 3100
2 3101
3 3102
The UDF if needed (much faster than recursive, loops, and xml)
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimiter varchar(25))
Returns Table
As
Return (
with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (IsNull(DataLength(#String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
cte3(N) As (Select 1 Union All Select t.N+DataLength(#Delimiter) From cte2 t Where Substring(#String,t.N,DataLength(#Delimiter)) = #Delimiter),
cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(#Delimiter,#String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By A.N)
,RetVal = LTrim(RTrim(Substring(#String, A.N, A.L)))
From cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
I suggest you to use following query, it's much faster than other functions like cross apply and udf.
SELECT
Variables
,S_DATA
FROM (
SELECT
Variables
,CASE WHEN LEN(LIST2)>0 THEN LTRIM(RTRIM(SUBSTRING(LIST2, NUMBER+1, CHARINDEX(',', LIST2, NUMBER+1)-NUMBER - 1)))
ELSE NULL
END AS S_DATA
,NUMBER
FROM(
SELECT Variables
,','+COMMA_SEPARETED_COLUMN+',' LIST2
FROM Tb1
)DT
LEFT OUTER JOIN TB N ON (N.NUMBER < LEN(DT.LIST2)) OR (N.NUMBER=1 AND DT.LIST2 IS NULL)
WHERE SUBSTRING(LIST2, NUMBER, 1) = ',' OR LIST2 IS NULL
) DT2
WHERE S_DATA<>''
and also you should create a table 'NUMBER' before running the above query.
CREATE TABLE TB (Number INT)
DECLARE #I INT=0
WHILE #I<1000
BEGIN
INSERT INTO TB VALUES (#I)
SET #I=#I+1
END
I am working with an apex environment where I need a dynamic sql query. Apex provides this api with the help of "Classic Report (based on function)". I would like you to draw your attention to line 8. My appoligies the spacing gets messed up when I paste it into stackoverflow. Now the problem is that I am getting the error 'ORA-01008: not all variables bound' Which is funny because when I change the :TEAM_SELECTOR in line 8 to something along the lines of 'MYSQL' (which is a team name) then this code works without error. Notice that :TEAM_SELECTOR is also used in the returned query without problem. Also I am using APEX 5.
DECLARE
v_time INT;
v_start_time int;
v_end_time int;
v_rownum int := 1;
v_max_shifts int;
v_location INT;
v_P4_team_selector varchar2(30) := :TEAM_SELECTOR;
BEGIN
select extract(hour from CAST(sysdate AS TIMESTAMP)) into v_time from dual;
select count(*) into v_max_shifts from oncall_shift
where team = v_P4_team_selector;
FOR i IN 0..v_max_shifts
LOOP
select start_time into v_start_time from (select * from oncall_shift where team =v_P4_team_selector)
where rownum = v_rownum;
select end_time into v_end_time from (select * from oncall_shift where team =v_P4_team_selector)
where rownum = v_rownum;
v_rownum := v_rownum + 1;
if v_time >= v_start_time and v_time <= v_end_time
then
select location into v_location from oncall_shift
where team = v_P4_team_selector
and start_time = v_start_time
and end_time = v_end_time;
return '
SELECT E.FNAME "First Name",E.LNAME "Last Name",E.OFFICE_NUM "Office Number", E.MOBILE_NUM "Mobile Number",L.NAME Location, o.position "Primary/Secondary"
FROM EMPLOYEE E, LOCATION L, ON_CALL O
WHERE E.ID = O.EMP_ID
AND L.ID = O.LOC_ID
AND O.ONCALL_DATE=TRUNC(SYSDATE)
AND O.TEAM=:TEAM_SELECTOR
AND L.ID = ' || v_location ||
' ORDER BY l.name asc
';
EXIT;
END IF;
END LOOP;
END;
Okay so I believe the issue was that the classic report based on a function executes before the host variables (TEAM_SELECTOR) is able to be bound therefore throwing the error. My solution to this was to change it to a normal classic report based on a sql query which runs after host variables are bound, because I needed one separate variable I created a P1_LOCATION item on that page using the same the query expect changing "v_location" to P1_LOCATION. Now in the P1_LOCATION page item I put the procedure to get the location.
P1_LOCATION code:
DECLARE
v_time INT;
v_start_time int;
v_end_time int;
v_rownum int := 1;
v_max_shifts int;
v_location INT;
v_P4_team_selector varchar2(30) := :TEAM_SELECTOR;
BEGIN
select extract(hour from CAST(sysdate AS TIMESTAMP)) into v_time from dual;
select count(*) into v_max_shifts from oncall_shift
where team = v_P4_team_selector;
FOR i IN 0..v_max_shifts
LOOP
select start_time into v_start_time from (select * from oncall_shift where team =v_P4_team_selector)
where rownum = v_rownum;
select end_time into v_end_time from (select * from oncall_shift where team =v_P4_team_selector)
where rownum = v_rownum;
v_rownum := v_rownum + 1;
if v_time >= v_start_time and v_time <= v_end_time
then
select location into v_location from oncall_shift
where team = v_P4_team_selector
and start_time = v_start_time
and end_time = v_end_time;
APEX_UTIL.set_session_state('P1_LOCATION',v_location);
EXIT;
END IF;
END LOOP;
END;
Classic Report (sql query):
SELECT E.FNAME "First Name",E.LNAME "Last Name",E.OFFICE_NUM "Office Number", E.MOBILE_NUM "Mobile Number",L.NAME Location, o.position "Primary/Secondary"
FROM EMPLOYEE E, LOCATION L, ON_CALL O
WHERE E.ID = O.EMP_ID
AND L.ID = O.LOC_ID
AND O.ONCALL_DATE=TRUNC(SYSDATE)
AND O.TEAM=:TEAM_SELECTOR
AND L.ID = :P1_LOCATION
ORDER BY l.name asc
SELECT
PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName,
STORE_ID, STORE_CODE, STORE_NAME,
ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname,
T.TimeIn, T.TimeOut, T.PlannedDate, T.Reason, TaskCode, TotalTime
FROM
[dbo].Report_RD_Coverage T
INNER JOIN
#TempLocationH TL ON TL.LocationId=T.Location_Id
WHERE
CONVERT(Date, PDADate) Between (#Start_Date) AND Isnull(#End_Date, #CurrentDate)
AND T.Account_Id IN
(SELECT
CASE WHEN #Account_Id IS NULL THEN T.Account_Id
ELSE (SELECT * FROM UDF_SplitString(#Account_Id,','))
END
)
AND T.StoreType_Id IN
(SELECT
CASE WHEN #StoreType_Id IS NULL THEN T.StoreType_Id
ELSE (SELECT * FROM UDF_SplitString(#StoreType_Id,','))
END
)
AND T.Store_Id IN
(SELECT
CASE WHEN #Store_Id IS NULL THEN T.Store_Id
ELSE (SELECT * FROM UDF_SplitString(#Store_Id,','))
END
)
If #Account_Id, #StoreType_Id and #Store_Id are null the it should select all the ACCOUNT_ID, STORETYPE_ID and STORE_ID otherwise based on parameter value it should filter.
UDF_SplitString is the function to split up comma-separated strings, and its return value is a table like:
- 1
- 2
- 3
I'm getting this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
CASE must return a scalar value, so try this variation instead:
select PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName, STORE_ID, STORE_CODE,
STORE_NAME, ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname, T.TimeIn, T.TimeOut, T.PlannedDate,
T.Reason, TaskCode, TotalTime
from [dbo].Report_RD_Coverage T
inner join #TempLocationH TL on TL.LocationId = T.Location_Id
where CONVERT(date, PDADate) between (#Start_Date)
and Isnull(#End_Date, #CurrentDate)
and (
#Account_Id is null
or T.Account_Id in (
select *
from UDF_SplitString(#Account_Id, ',')
)
)
and (
#StoreType_Id is null
or T.StoreType_Id in (
select *
from UDF_SplitString(#StoreType_Id, ',')
)
)
and (
#Store_Id is null
or T.Store_Id in (
select *
from UDF_SplitString(#Store_Id, ',')
) end
)
I tried this and reached very closer but you have to do something from what I found a link.
This is my try. the only thing you need to build is the #udf data.
declare #Store_Id INT;
declare #Account_Id INT;
DECLARE #UDF[9] OF VARCHAR(30);
set #Store_Id = 99 --NULL
set #Account_Id = 15
SET #UDF = '11,12,13,14,15,16'
SELECT #Account_Id AS ACID
WHERE CAST(#Account_Id AS VARCHAR(6)) IN (
CASE WHEN #Store_Id IS NULL THEN CAST(#Account_Id AS VARCHAR(6))
ELSE #UDF END
The link is at
http://www.codeproject.com/Questions/473174/CreateplusArrayplusinplusSqlplusServer
DECLARE #INSTR as VARCHAR(MAX)
SET #INSTR = '2,3,177,'
DECLARE #SEPERATOR as VARCHAR(1)
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
SET #SEPERATOR = ','
CREATE TABLE #tempTab (id int not null)
WHILE PATINDEX('%' + #SEPERATOR + '%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%' + #SEPERATOR + '%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #tempTab (id) VALUES (#VALUE)
END
SELECT * FROM myTable WHERE id IN **(SELECT id FROM #tempTab)**
DROP TABLE #tempTab
you can extract for the sql in bold and the logic how to create temp table and its data and I hope you will get what you want.
> This is the my right solultion........now its working correctly
CREATE TABLE #Store_Id (StoreID varchar(20))
IF #Store_Id != '0'
BEGIN
INSERT INTO #Store_Id
SELECT data FROM UDF_SplitString(#Store_Id,',')
END
ELSE
BEGIN
INSERT INTO #Store_Id
SELECT '0'
END
CREATE TABLE #StoreType_Id (StoreTypeID varchar(20))
IF #StoreType_Id != '0'
BEGIN
INSERT INTO #StoreType_Id
SELECT data FROM UDF_SplitString(#StoreType_Id,',')
END
ELSE
BEGIN
INSERT INTO #StoreType_Id
SELECT '0'
END
CREATE TABLE #Account_Id (AccountID varchar(20))
IF #Account_Id != '0'
BEGIN
INSERT INTO #Account_Id
SELECT data FROM UDF_SplitString(#Account_Id,',')
END
ELSE
BEGIN
INSERT INTO #Account_Id
SELECT '0'
END
INSERT INTO #FinalTable(VisitDate,Merchandizer_Id,Merchandizer,MerchandizerLogin,StoreId,StoreCode,StoreName,AccountId,AccountName,
Account_Store_Format_Id,Account_Store_Format,StoreTypeId ,StoreType ,ListId ,ListName,TimeIn ,TimeOut,PlannedDate ,Reason ,TaskCode,TotalTime)
SELECT Visit_Date,T.Merchandizer_ID,T.Merchandizer,Merchandizer_LoginName,STORE_ID,STORE_CODE,STORE_NAME,ACCOUNT_ID,ACCOUNT_NAME,
Account_Store_Format_Id,Account_Store_Format,StoreType_Id,
StoreType,T.Listid,T.Listname,T.TimeIn,T.TimeOut,T.PlannedDate,T.Reason,TaskCode,TotalTime
FROM [dbo].Report_RD_Coverage T
INNER JOIN #TempLocationH TL ON TL.LocationId=T.Location_Id
INNER JOIN #Store_Id on CONVERT(VARCHAR,t.Store_Id) = CASE WHEN #Store_Id = '0' THEN convert(VARCHAR,t.Store_Id) ELSE StoreID END
INNER JOIN #StoreType_Id on CONVERT(VARCHAR,t.StoreType_Id) = CASE WHEN #StoreType_Id = '0' THEN convert(VARCHAR,t.StoreType_Id) ELSE StoreTypeID END
INNER JOIN #Account_Id on CONVERT(VARCHAR,t.Account_Id) = CASE WHEN #Account_Id = '0' THEN convert(VARCHAR,t.Account_Id) ELSE AccountID END
WHERE CONVERT(Date,PDADate) Between #Start_Date AND #End_Date
I have a SQL Script that I execute in a job to transform tables periodically. To speed it up I put that script in a stored procedure and executed it with a job. It worked faster.
The problem occurs at times when the stored procedure even though it executes it doesn't work. I use the script manually and run it and everything works fine.
The whole script is inside a transaction and I have made it so that if some error comes up it gets logged properly. However the script doesn't give any errors.
BEGIN TRANSACTION
BEGIN TRY
-- Rounding off Campaign stats
update Campaigns
set ImpressionsBurned = ImpressionTarget
where ImpressionsBurned > ImpressionTarget and CampaignTypeID = 1
update Campaigns
set ClicksConsumed = ClickTarget
where ClicksConsumed = ClickTarget and CampaignTypeID = 2
-- Updating Campaigns & Banners
update banners
set banners.impressionsburned =
(select sum(impressionsqueue.impressionsburned) from impressionsqueue where impressionsqueue.bannerid = banners.bannerid)
where exists (select impressionsqueue.bannerid from impressionsqueue where impressionsqueue.bannerid = banners.bannerid)
update Campaigns
set ImpressionsBurned =
(select isnull(SUM(ImpressionsQueue.ImpressionsBurned),0) from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID and CampaignID = Campaigns.CampaignID
)
where
exists (
(select ImpressionsQueue.BannerID from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID and CampaignID = Campaigns.CampaignID
)
)
and
(
( Campaigns.ImpressionsBurned < Campaigns.ImpressionTarget and Campaigns.CampaignTypeID = 1)
or ( Campaigns.ClicksConsumed < Campaigns.ClickTarget and Campaigns.CampaignTypeID = 2)
or Campaigns.CampaignTypeID = 3
)
and Campaigns.IsPaused = 0
and Campaigns.StartsOn <= GetDate() and Campaigns.EndsOn >= GetDate()
-- Updating Paused Banners in the Queue
update ImpressionsQueue
set IsPaused = (
select IsPaused from Banners where Banners.BannerID = ImpressionsQueue.BannerID
)
-- Updating the Navigation URLs
update ImpressionsQueue
set NavigateURL = (
select NavigateURL from Banners where Banners.BannerID = ImpressionsQueue.BannerID
)
-- Removing any rows if the Weight of a banner is updated,
-- the banner will be reinserted later with updated impressions
delete from ImpressionsQueue
where BannerID in
(
select ImpressionsQueue.BannerID from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID
group by ImpressionsQueue.BannerID, Banners.Weight
having Banners.Weight <> COUNT(ImpressionsQueue.BannerID)
)
-- Removing entries whose impressions count has reached its target
delete from impressionsqueue where
BannerID in (
select Banners.BannerID from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid
where Campaigns.CampaignTypeID = 1
-- excluding flat fee based campaign
group by Campaigns.ImpressionTarget, Banners.BannerID
having not (Campaigns.ImpressionTarget > sum(ImpressionsQueue.impressionsburned))
-- inverse logic for campaign count
)
-- Removing entries whose campaign click count has reached
delete from impressionsqueue where
BannerID in (
select Banners.BannerID from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid and Campaigns.CampaignTypeID = 2
and Not (Campaigns.ClickTarget > Campaigns.ClicksConsumed)
-- inverse logic for campaign count
)
-- Removing entries whose campaign has expired
delete from impressionsqueue where
BannerID in (
select impressionqueueid from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid
and not (Campaigns.StartsOn <= GETDATE() and Campaigns.EndsOn >= GETDATE())
-- inverse logic for date
)
----------------------------------------------------------------------------------------
-- Begin updating Impressions Queue
----------------------------------------------------------------------------------------
Declare #TempBanners Table(BcID [int] IDENTITY(1,1),ZoneID [int], BannerID [int], Weight [int], FileID [uniqueidentifier], IsPaused [bit], Impressions [int], URL [nvarchar](2048))
/*
Insert into the temp table all the banners that:
1) Belong to an active campaign => c.StartsOn <= GetDate() and c.EndsOn >= GetDate()
2) and Belong to a campaign that is not paused
3) and The banner itself is not paused
4) and Flat Fee campaign banner
*/
Insert Into #TempBanners (ZoneID, BannerID, Weight, FileID, IsPaused, Impressions, URL)
Select
bz.ZoneID,
b.BannerID,
b.Weight,
b.FileID,
b.IsPaused,
b.ImpressionsBurned,
b.NavigateURL
From Banners b
Join Bannerzones bz on b.BannerID = bz.BannerID
Join Campaigns c on b.CampaignID = c.CampaignID
And c.StartsOn <= GetDate() and c.EndsOn >= GetDate()
And c.IsPaused = 0
And b.IsPaused = 0
And (
(c.CampaignTypeID = 1 And c.ImpressionsBurned < c.ImpressionTarget)
Or (c.CampaignTypeID = 2 And c.clicksconsumed < c.clicktarget)
Or (c.campaigntypeid = 3)
);
-- Declaration of Vairables
Declare #index As int,#maxRow As int, #weight Int, #bcid int
Set #index = 1 --Because we will start from First row
Select #maxRow = Count(0) From #TempBanners Where Weight > 1
-- How many rows we have that has weight more then 1
While(#index <= #maxRow)
Begin
Select
#weight = V.Weight,
#bcid = V.BcID
From (
Select
BCid,
Weight,
ROW_NUMBER() Over (Order By Bcid Asc) Row
From #TempBanners
Where Weight > 1
)V
Where V.Row = #index
Set #index = #index + 1
While(#weight <> 1)
Begin
Insert Into #TempBanners (ZoneID, BannerID, Weight, FileID, URL)
Select ZoneID, BannerID, Weight, FileID, URL From #TempBanners Where BcID = #bcid
set #weight = #weight - 1
End
End
-- INSERT INTO THE IMPRESSION QUEUE ALL THE BANNERS THAT ARE NOT YET IN THE QUEUE
Insert Into ImpressionsQueue (BannerID, ZoneID, FileID, ImpressionsBurned, RowUpdated, IsPaused, NavigateURL )
Select V.BannerID, V.ZoneID, V.FileID, V.Impressions, GETDATE(), V.IsPaused, V.URL
From
(
Select m.BannerID, m.ZoneID, m.FileID,
isnull(m.IsPaused,0) as IsPaused,
isnull(m.Impressions,0) as Impressions,
ISNULL(m.URL,'') as URL
From #TempBanners m
where Weight >
(select COUNT(t.bannerid)
from ImpressionsQueue as t
where t.BannerID = m.BannerID
and t.FileID = m.FileID
and t.ZoneID = m.ZoneID
)
)As V;
-- Update the banner file id in case it is modified after the banner was created
Update ImpressionsQueue
Set FileID = CTE.FileID, ImpressionsQueue.IsPaused = isnull(CTE.IsPaused,0), ImpressionsQueue.NavigateURL = CTE.URL
From ImpressionsQueue I
Inner Join #TempBanners As CTE On CTE.BannerID = I.BannerID And CTE.ZoneID = I.ZoneID --And CTE.FileID <> I.FileID
----------------------------------------------------------------------------------------
-- End updating Impressions Queue
----------------------------------------------------------------------------------------
END TRY
BEGIN CATCH
declare #error varchar(3000) = 'Message: ' + ERROR_MESSAGE() + ' ' + ERROR_LINE()
exec master.sys.xp_logevent 50001, #error , 'Warning'
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
IF ##TRANCOUNT > 0
COMMIT TRANSACTION
Not sure if that's the cause of all problem - but if I were you, I'd put the COMMIT TRANSACTION inside the TRY..... block:
-------------------------------------------------------------------------------
-- End updating Impressions Queue
-------------------------------------------------------------------------------
IF ##TRANCOUNT > 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
declare #error varchar(3000) = 'Message: ' + ERROR_MESSAGE() + ' ' + ERROR_LINE()
exec master.sys.xp_logevent 50001, #error , 'Warning'
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
If everything goes okay, you'll execute COMMIT TRANSACTION as the last statement of your TRY... block - and if something blows up, you'll fall into the CATCH block anyway. Might be dangerous to call COMMIT TRANSACTION outside your CATCH block after it....