SSRS SQL-Restart subscription runs all scheduled Reports - tsql

I am using the folling SQL-Script to restart faild SSRS mailing subscriptions:
DECLARE #ScheduledReportName varchar(200)
DECLARE #JobID uniqueidentifier
DECLARE #LastRunTime datetime
Declare #JobStatus Varchar(100)
--------------------------------------------------------
DECLARE #RunAllReport CURSOR
SET #RunAllReport = CURSOR FAST_FORWARD
FOR
SELECT
CAT.[Name] AS RptName
, res.ScheduleID AS JobID
, sub.LastRuntime
, CASE WHEN job.[enabled] = 1 THEN 'Enabled'
ELSE 'Disabled'
END AS JobStatus
FROM
dbo.Catalog AS cat
INNER JOIN dbo.Subscriptions AS sub
ON CAT.ItemID = sub.Report_OID
INNER JOIN dbo.ReportSchedule AS res
ON CAT.ItemID = res.ReportID
AND sub.SubscriptionID = res.SubscriptionID
INNER JOIN msdb.dbo.sysjobs AS job
ON CAST(res.ScheduleID AS VARCHAR(36)) = job.[name]
INNER JOIN msdb.dbo.sysjobschedules AS sch
ON job.job_id = sch.job_id
INNER JOIN dbo.Users U
ON U.UserID = sub.OwnerID
----------------Filter der Subscriptions----------------
where sub.subscriptionid in
(
SELECT subscriptionid
FROM Subscriptions AS S
LEFT OUTER JOIN [Catalog] AS C
ON C.ItemID = S.Report_OID
WHERE S.LastStatus like 'Failure sending mail%'
)
----------------Filter der Subscriptions----------------
ORDER BY U.UserName, RptName
OPEN #RunAllReport
FETCH NEXT FROM #RunAllReport
INTO #ScheduledReportName,#JobID,#LastRunTime,#JobStatus
WHILE ##FETCH_STATUS = 0
BEGIN
Print #ScheduledReportName --&' ' & #JobID
EXEC msdb.dbo.sp_start_job #job_name =#JobID
FETCH NEXT FROM #RunAllReport
INTO #ScheduledReportName,#JobID,#LastRunTime,#JobStatus
END
CLOSE #RunAllReport
DEALLOCATE #RunAllReport
I run this if an subscripton fails. In my example I send the same Report to multiple persons as a subscription with differen parameters. Sometime one subscription fails and I want to restart the job. The query in the upper script provides the specific subscriptionID of the failed one.
But even though the ScheduleID is handed over AS JobID all the Reports are beeing resend to all people.
Is there something wrong with the script?
Pleas help me.

Turns out that the procedure in my old query:
EXEC msdb.dbo.sp_start_job #job_name =#JobID
Runs all the Subscriptions under a ScheduleID AS JobID. So all Report with a SharedSchedule are launched again, by a job restart.
To restart only a specific supbscription I have to run the following command at its place, with the subscriptionID instead of the scheduleID:
exec [dbo].[AddEvent] 'TimedSubscription', #SubscriptionID;
This will add an event into the [dbo].[Event] table that will run the subscription passed in the parameter. So only the required Report will be sent.

Related

Don't understand 'CREATE VIEW' must be the first statement in a query batch

I am trying to create a View for temporary data I only need during the SQL run.
I get the error:
"'CREATE VIEW' must be the first statement in a query batch."
I searched on that and see it was asked about on Stack Overflow already here: 'CREATE VIEW' must be the first statement in a query batch
However, my SQL code looks like it should but I still get the error. First, I create a table called #StatusTable but that table wasn't working like I wanted. So I tried creating a View.
DECLARE #DOC INT;
DECLARE #StatusTable TABLE
(
status VARCHAR(8000)
)
INSERT INTO #StatusTable
Select Status = ( select CONCAT(ls.ItemText, '/', st.ItemText ) as Status from Inmate_Legal_Status ils
Left join jt_list_items ls on ls.ItemID = ils.LegalStatusID
Left join jt_list_items st on st.ItemID = ils.StatusTypeId
where ArrestNo = #doc and ils.RecordDeleted = 0
order by ils.CreatedTime desc FOR XML PATH('')
)
-- table
USE #StatusTable;
GO
create view MyView as
Select Status = ( select CONCAT(ls.ItemText, '/', st.ItemText ) as Status from Inmate_Legal_Status ils
Left join jt_list_items ls on ls.ItemID = ils.LegalStatusID
Left join jt_list_items st on st.ItemID = ils.StatusTypeId
where ArrestNo = #doc and ils.RecordDeleted = 0
GO
I get three errors:
Incorrect syntax near GO.
'CREATE VIEW' must be the first statement in a query batch
Incorrect syntax near #StatusTable

TSQL OUTPUT clause in MERGE statement raise Msg 596 "Cannot continue the execution because the session is in the kill state"

I wrote T-SQL MERGE query to merge staging data into a data warehouse (you can find it at the bottom).
If I uncomment the OUTPUT statement the I get error mentioned in the title.
However, if I do not include it, everything works perfectly fine and MERGE succeeds.
I know that there are some issue connected to the MERGE clause, however there are more connected to the type of merge.
I checked the following answer: [https://dba.stackexchange.com/questions/140880/why-does-this-merge-statement-cause-the-session-to-be-killed], however in my execution plan I cannot find exactly index insert followed by index merge.
Rather, what I see is the following execution plan
Code was developed on database attached to SQL Server 2012 (SP4) instance
I would really appreciate good explanation of this problem, ideally referencing steps from my execution plan.
Thank you.
declare #changes table (chgType varchar(50),Id varchar(18))
begin try
set xact_abort on
begin tran
;with TargetUserLogHsh as (select
hsh =hashbytes('md5',concat(coalesce([AccountName],'')
,coalesce([TaxNumber],'')))
,LastLoginCast = coalesce(CONVERT(datetime,LastLogin,103),getdate())
,* from
dw.table1)
,SourceUserLogHsh as (select
hsh =hashbytes('md5',concat(coalesce([AccountName],'')
,coalesce([TaxNumber],'')))
,LastLoginCast = coalesce(CONVERT(datetime,LastLogin,103),getdate())
,* from
sta.table1)
merge TargetUserLogHsh target
using SourceUserLogHsh source
on target.ContactId = source.ContactId and target.Lastlogincast >= source.LastLoginCast
when not matched then insert (
[AccountName]
,[TaxNumber]
,[LastLogin]
)
values (
source.[AccountName]
,source.[TaxNumber]
,source.[LastLogin]
)
when matched and target.lastlogincast = source.lastlogincast
and target.hsh != source.hsh then
update
set
[AccountName] = source.[AccountName]
,[TaxNumber] = source.[TaxNumber]
,[LastLogin] = source.[LastLogin]
output $action,inserted.contactid into #changes
;
commit tran
end try
begin catch
if ##TRANCOUNT > 0 rollback tran
select ERROR_MESSAGE()
end catch

PostgreSQL subquery split rows (error is more than one row returned by a subquery used as an expression)

this is my first post on stackoverflow so please be gentle. I have researched this problem and came up with many varied solutions...all of which seem to be just off from what I need. I have a postgresql subquery in a SELECT statement that returns multiple rows, which I know is obviously not ideal/allowed/sensible/etc.... However, this is the case for my current problem and I need to be able to take those multiple returned rows and apply them to every previous corresponding record row that they originally came out of.
Current Query:
SELECT cohead_number "Sales Order#",
cohead_custponumber "Purchase Order#",
item_number "Part Number",
item_descrip1 "Part Description",
CAST(shipitem_qty AS integer) "Item Quantity",
getPacklistItemLotSerial(shiphead_id, coitem_id) AS "LotNumbers" --this is the duplicating row subquery that I need listed in separate rows without changing other respective columns--
FROM cohead
LEFT JOIN coitem
ON coitem_cohead_id = cohead_id
LEFT JOIN shipitem
ON coitem_id = shipitem_orderitem_id
LEFT JOIN itemsite
ON coitem_itemsite_id = itemsite_id
LEFT JOIN item
ON itemsite_item_id = item_id
LEFT JOIN shiphead
ON shiphead_order_id = cohead_id
WHERE cohead_number = '79464' --this is just to test with one sales order instead of all (sales order being the input for the query)--
Results:
LINK: Results of above query here
What I Have Tried
Now, this line lets me split the column results via the delimiter ',' but I can't figure out how to get the results from this back into my original query's results:
(SELECT lot from regexp_split_to_table(getPacklistItemLotSerial(shiphead_id, coitem_id),', ') AS lot)
Results:
Here I input the shiphead_id and coitem_id for the example sales order so it can show you the resulting split column into rows.
SELECT lot from regexp_split_to_table(getPacklistItemLotSerial(22082, 50351),', ') AS lot
LINK: Results of Example
Please help walk me through what I need to do to achieve this. I imaging we need to declare some things and maybe join 2 tables in a more complex query...I don't really know. Thank you for any help you can offer.
EDIT
Added in the requested source code for the Function "getpacklistitemlotserial"
DECLARE
pShipheadId ALIAS FOR $1;
pOrderItemId ALIAS FOR $2;
_lotserial text;
_r RECORD;
_first BOOLEAN;
BEGIN
--Test to see if Lot/Serial Enabled
SELECT metric_value INTO _lotserial
FROM metric
WHERE ((metric_name='LotSerialControl')
AND (metric_value ='t'));
IF (FOUND) THEN
_lotserial := '';
_first := true;
FOR _r IN SELECT DISTINCT ls_number
FROM invdetail, invhist, shipitem, ls
WHERE ((shipitem_shiphead_id=pShipheadId)
AND (shipitem_orderitem_id=pOrderItemId)
AND (shipitem_invhist_id=invhist_id)
AND (invhist_id=invdetail_invhist_id)
AND (invdetail_ls_id=ls_id)) LOOP
IF (_first = false) THEN
_lotserial := _lotserial || ', ';
END IF;
_lotserial := _lotserial || _r.ls_number;
_first := false;
END LOOP;
RETURN _lotserial;
ELSE
RETURN '';
END IF;
END
Try:
SELECT DISTINCT cohead_number "Sales Order#",
cohead_custponumber "Purchase Order#",
item_number "Part Number",
item_descrip1 "Part Description",
CAST(shipitem_qty AS integer) "Item Quantity",
-- getPacklistItemLotSerial(shiphead.shiphead_id, coitem.coitem_id) AS "LotNumbers" --this is the duplicating row subquery that I need listed in separate rows without changing other respective columns--
CASE WHEN EXISTS(
SELECT metric_value FROM metric
WHERE metric_name='LotSerialControl' AND metric_value ='t'
)
THEN x.ls_number
ELSE ''
END AS "LotNumbers"
FROM cohead
LEFT JOIN coitem
ON coitem_cohead_id = cohead_id
LEFT JOIN shipitem
ON coitem_id = shipitem_orderitem_id
LEFT JOIN itemsite
ON coitem_itemsite_id = itemsite_id
LEFT JOIN item
ON itemsite_item_id = item_id
LEFT JOIN shiphead
ON shiphead_order_id = cohead_id
LEFT JOIN (
SELECT ls_number,
shipitem_shiphead_id, -- parameter: pShipheadId
shipitem_orderitem_id -- parameter pOrderItemId
FROM invdetail, invhist, shipitem, ls
WHERE
-- (shipitem_shiphead_id=pShipheadId)
-- AND (shipitem_orderitem_id=pOrderItemId)
(shipitem_invhist_id=invhist_id)
AND (invhist_id=invdetail_invhist_id)
AND (invdetail_ls_id=ls_id)
) x
ON ( x.shipitem_shiphead_id = shiphead.shiphead_id
AND
x.shipitem_orderitem_id = coitem.coitem_id
)
WHERE cohead_number = '79464'

SQL Server batch update, user-defined Table types

i need to batch updates on a table from a stored procedure that is has user defined table types. The updates are causing table locking and i would like to mitigate that. I would like to batch them in updates of 1000. The code would look as below
CREATE PROCEDURE [dbo].[updatestuff]
#update1 AS udtupdate1 READONLY ,
#update2 AS udtupdate2 READONLY ,
#time DATETIME
AS
BEGIN
SET NOCOUNT ON
-- uses udtupdate1
UPDATE lms
SET lms.col1 = lsp.col1 ,
lms.TimeStamp = #time
FROM dbo.tlivetable1 lms
INNER JOIN #update1 lsp ON lms.livetable1Id = lsp.colId
UPDATE ms
SET ms.col1 = lsp.col1 ,
ms.TimeStamp = #time
FROM dbo.tmrks ms
INNER JOIN #update1 lsp ON ms.mrksId = lsp.Colid
-- uses udtupdate2
UPDATE mms
SET mms.col2 = msp.col2 ,
mms.Date = #time
FROM dbo.tMMSel mms
INNER JOIN #update2 msp ON msp.col1Id = mms.MMId
AND msp.col2Id = mms.MMSId
END
Any help would be really appreciated
I haven't tested this as I don't have any sample data but this should do it.:
CREATE PROCEDURE [dbo].[updatestuff]
#update1 AS udtupdate1 READONLY ,
#update2 AS udtupdate2 READONLY ,
#time DATETIME
AS
BEGIN
SET NOCOUNT ON
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION
UPDATE top (1000) lms
SET lms.col1 = lsp.col1 ,
lms.TimeStamp = #time
FROM dbo.tlivetable1 lms
INNER JOIN #update1 lsp ON lms.livetable1Id = lsp.colId
IF ##ROWCOUNT = 0 -- terminating condition;
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
--WAITFOR DELAY '00:00:01'; --<-- you can uncomment wait for delay to increase the delay between batches
END
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION
UPDATE top (1000) ms
SET ms.col1 = lsp.col1 ,
ms.TimeStamp = #time
FROM dbo.tmrks ms
INNER JOIN #update1 lsp ON ms.mrksId = lsp.Colid
IF ##ROWCOUNT = 0 -- terminating condition;
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
--WAITFOR DELAY '00:00:01'; --<-- you can uncomment wait for delay to increase the delay between batches
END
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION
UPDATE top (1000) mms
SET mms.col2 = msp.col2 ,
mms.Date = #time
FROM dbo.tMMSel mms
INNER JOIN #update2 msp ON msp.col1Id = mms.MMId
AND msp.col2Id = mms.MMSId
IF ##ROWCOUNT = 0 -- terminating condition;
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
--WAITFOR DELAY '00:00:01'; --<-- you can uncomment wait for delay to increase the delay between batches
END
END

Service Broker only receiving one message at a time

Even when I specify Receive Top(25), etc I am only getting one message to be dequeued at a time. Not sure what i am doing wrong inside my sproc? Probably something trivial, but I don't see the problem.
Sproc:
CREATE PROCEDURE dbo.SPP_DEQUEUE_MESSAGE
AS
BEGIN
DECLARE #receiveTable TABLE(
message_type sysname,
message_body xml,
message_dialog uniqueidentifier);
BEGIN TRANSACTION;
WAITFOR
( RECEIVE TOP(25)
message_type_name,
message_body,
conversation_handle
FROM TargetQueue1DB
INTO #receiveTable
), TIMEOUT 3000;
SELECT
*
From #receiveTable;
Delete from #receiveTable;
COMMIT TRANSACTION;
END --End Sproc
Any idea what I am doing wrong?
Thanks,
B
My guess would be that each message belongs to a different conversation (and therefore by default to a different conversation group). If this is the case, then this is expected behavior.
From Books Online - Receive (Transact-SQL):
All messages that are returned by a
RECEIVE statement belong the same
conversation group
If you want to receive multiple messages at once, send multiple messages on a single conversation or group multiple conversations into a single conversation group on the receiving end.
Do you know how many messages are in that queue, before the proc is run?
If you run the following query to get the count in all your queues
SELECT sq.name,
p.rows
FROM sys.service_queues sq
Join sys.internal_tables it ON sq.object_id = it.parent_id
AND it.parent_minor_id = 0
AND it.internal_type = 201
Join sys.indexes as i on i.object_id = it.object_id and i.index_id = 1
Join sys.partitions as p on p.object_id = i.object_id and p.index_id = i.index_id
WHERE
sq.object_id = it.parent_id AND
it.parent_minor_id = 0 AND
it.internal_type = 201
If there is more than 1 message in that queue, you should get more than 1 in your receive.