SP_Start_job fails, on local call to local execute - tsql

I'm trying to set up a cycle to send the same report to multiple managers, with the parameters altered to suit their teams.
I've got a subscription set up which I test fired successfully, both immediately before my first attempt and after the code I've used has cycled (by setting a schedule to fire in 1 min)
However SP_Start_job is failing to start the job, and simply returning a 1. Every 5th run is reutrning the error:
Msg 14262, Level 16, State 1, Procedure sp_verify_job_identifiers, Line 41
The specified #job_id ('5274E5CB-9D5A-4998-96E4-B82017CA0588') does not exist.
DECLARE #MID VARCHAR(max),
#MEmail VARCHAR(max),
#UpdatedSettings VARCHAR(max),
#SubscriptionID VARCHAR(36), #passed int
--Declares a cycle getting UID for manager and their EMAIL.
--Email will be used to update the job destination
SELECT #SubscriptionID = a.SubscriptionID
FROM ReportServer$TOFINOREPORTING.dbo.[Subscriptions] a
INNER JOIN ReportServer$TOFINOREPORTING.dbo.[Catalog] AS b ON a.[Report_OID] = b.[ItemID]
WHERE b.NAME = 'Automation OperativePerformence'
DECLARE ManagerCursor CURSOR STATIC
FOR
(
SELECT U.ID AS ManagerID,
u.Email AS Email
FROM [dbo].[Global.User] U
INNER JOIN [dbo].[Global.UserRole] UR ON UR.UserId = U.ID
INNER JOIN [dbo].[Global.Role] R ON R.ID = UR.RoleID
WHERE R.NAME = 'ReportingAutomation'
AND U.IsActive = 1
AND U.Title LIKE 'Repairs Field Manager%'
)
OPEN ManagerCursor
--UPDate cycle
FETCH NEXT
FROM managerCursor
INTO #MID,
#MEMail
SELECT #MID,
#MEmail
WHILE ##FETCH_STATUS = 0
BEGIN
--TEST EMAIL OVERRIDE
SET #MEmail = 'Stephen.Wallace#email.org.uk'
UPDATE dbo.BAT_SubscriptionController
SET MID = #MID,
MEmail = #MEmail
SELECT *
FROM BAT_SubscriptionController
SELECT #UpdatedSettings = LEFT(Cast(a.extensionSettings AS NVARCHAR(max)), (- 1 + CHARINDEX('<Name>TO</Name><Value>', Cast(a.extensionSettings AS NVARCHAR(max))) + LEN(cast('<Name>TO</Name><Value>' AS NVARCHAR(max)))
)) + #MEmail + RIGHT(Cast(a.extensionSettings AS NVARCHAR(max)), len(Cast(a.extensionSettings AS VARCHAR(max))) - Charindex(
'</Value></ParameterValue><ParameterValue><Name>IncludeReport</Name>', Cast(a.extensionSettings AS NVARCHAR(max))) + 1)
FROM ReportServer$TOFINOREPORTING.dbo.[Subscriptions] a
INNER JOIN ReportServer$TOFINOREPORTING.dbo.[Catalog] AS b ON a.[Report_OID] = b.[ItemID]
WHERE a.SubscriptionID = #SubscriptionID
SELECT #UpdatedSettings,
LEN(#UpdatedSettings),
#SubscriptionID
UPDATE ReportServer$TOFINOREPORTING.dbo.[Subscriptions]
SET extensionSettings = #UpdatedSettings
WHERE SubscriptionID = #SubscriptionID
EXEC #passed = msdb.dbo.sp_start_job #job_id = #SubscriptionID
Select #passed
WAITFOR DELAY '00:00:30'
FETCH NEXT
FROM managerCursor
INTO #MID,
#MEMail
END
CLOSE ManagerCursor
DEALLOCATE ManagerCursor

Obvious solution - My mistake
SP_Start_job requires The Job_Name/id , not the subscription Name ID.
Changing my Subscription ID stage to use
SELECT #SubscriptionID = a.SubscriptionID , #jobID= s.ScheduleID
FROM ReportServer$TOFINOREPORTING.dbo.[Subscriptions] a
INNER JOIN ReportServer$TOFINOREPORTING.dbo.[Catalog] AS b ON a.[Report_OID] = b.[ItemID]
INNER JOIN ReportServer$TOFINOREPORTING.dbo.ReportSchedule rs
ON rs.SubscriptionID = a.SubscriptionID
INNER JOIN ReportServer$TOFINOREPORTING.dbo.Schedule S
ON rs.ScheduleID = S.ScheduleID
WHERE b.NAME =
and the exec to
St_Start_job #Job_Name=#jobID
Solves the issue.
thank you #Manoj for the code. it took me multiple looks to see the obvious.

Related

How can I update a table using the following CROSS APPLY?

UPDATE ItemDim_DEV
set ActiveFlag = 0,
EndUTCDate = GETUTCDATE()
from (select i.SKU, i.itemname, i.category, i.CategoryInternalId, i.itemtype, i.IsActive, i.assetaccount, i.InternalId,
ni.sku,
ni.itemname,
ni.class_name,
ni.productclass,
ni.ItemType,
ni.isactive,
ni.assetaccount,
i.CalculatedHash, ni.hashid
from (
SELECT i.*
FROM itemDim_Dev i
WHERE i.SourceSystem = 'NetSuite'
--and InternalId = '1692'
) i
CROSS APPLY (
SELECT (CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) hashid,
ISNULL(im.TargetSKU, ni.sku) sku,
ni.itemname,
pc.class_name,
ni.productclass,
ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ) isactive, ni.assetaccount
FROM NetSuiteInventory ni
INNER JOIN Product_Class pc ON ni.productclass = pc.class_id
LEFT JOIN ItemMapping im ON ni.sku = im.SourceSKU
WHERE ni.ItemInternalId = CAST(i.InternalId as bigint)
and
(CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) = i.CalculatedHash
) ni
I understand that I can put a select after the from of the update but in the CROSS APPLY that is in the query starts with a select as in the second one, can you help me please.
Make a join to the target table
UPDATE A
SET XXX = YYY
FROM ItemDim_DEV A
JOIN (
--huge SELECT that I recommend you try to shorten in the next questions
CROSS APPLY (any secrets...)
) B ON A.PK = B.PK

Trigger SQL Server for Firebird

I have a SQL Server trigger that I have tried to convert for Firebird but seems like I have some trouble with it.
Here is my SQL trigger:
CREATE TRIGGER [dbo].[IDSOFT_INTERV_UI]
ON [MMAINT_SOCO_PROD].[dbo].[T_ZONES_LIBRES_UI]
AFTER UPDATE
AS
BEGIN
IF UPDATE(STR_ZONE_LIBRE)
BEGIN
DECLARE #ui_id int,
#num_interv int;
SELECT #ui_id = d.LIEN_UI,
#num_interv = e.NUM_INTERV
FROM T_LIGNE_BT a
inner join T_BT b on b.NUM_BT = a.CLE_BT
inner join T_UI c on c.NUM_UI = b.CLE_UI
inner join T_ZONES_LIBRES_UI d on d.LIEN_UI = c.NUM_UI
inner join T_INTERV e on e.NOM_INTERV = d.STR_ZONE_LIBRE
WHERE d.LIEN_UI in (select LIEN_UI from INSERTED) and d.INDICE_ZONE_LIBRE = 20;
Update a
set a.cle_element = e.NUM_INTERV
from t_ligne_bt a
inner join T_BT b on b.NUM_BT = a.CLE_BT
inner join T_UI c on NUM_UI = b.CLE_UI
inner join T_ZONES_LIBRES_UI d on d.LIEN_UI = c.NUM_UI
inner join T_INTERV e on e.NOM_INTERV = d.STR_ZONE_LIBRE
where d.LIEN_UI = #ui_id
and b.cle_ip is not null
and b.cle_ip <> 100000
and a.type_ligne_bt like 'I'
END
END
I'm really having problems to replicate the same for Firebird.
Can anyone help me please.

View query without sub selecting T-SQL

so I'm trying to build a view query but I keep failing using only joins so I ended up with this deformation.. Any tips on how I can write this query so I don't have to use 6 subselects?
The FeeSum and PaymentSum can be null, so ideally I do not want those in my result set and I also wouldn't like results where the FeeSum and the PaymentSum are equal.
Quick note: client is the table where the clients informations are stored (name, adress, etc..)
customer has a fk on client and is kind of a shell table for the client that store more information for the client,
payment is a list of all payments a customer did,
order is a list of all orders a customer did.
The goal is to get a list where we can track which customer has open fees to pay, based on the orders. It's a legacy project so don't ask why people can order before paying :)
SELECT
cu.Id as [CustomerId]
, CASE
WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName
END as [Name]
, cl.CustomerNumber
, (SELECT SUM(o.Fee) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [FeeSum]
, (SELECT SUM(p.Amount) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [PaymentSum]
, (SELECT MAX(o.OrderDate) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [LastOrderDate]
, (SELECT MAX(p.PaymentDate) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [LastPaymentDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Reminder' AND f.ClientId = cl.Id) as [LastReminderDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Warning' AND f.ClientId = cl.Id) as [LastWarningDate]
FROM
[publication].[Customer] cu
JOIN
[client].[Client] cl
ON cl.Id = cu.ClientId
WHERE
cu.[Type] = 0
Thanks in advance and I hope I didn't do anything wrong.
Kind regards
You could rewrite the correlated subqueries to instead use joins:
SELECT
cu.Id AS [CustomerId],
CASE WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName END AS [Name],
cl.CustomerNumber,
o.FeeSum,
p.PaymentSum,
o.LastOrderDate,
p.LastPaymentDate,
f.LastReminderDate,
f.LastWarningDate
FROM [publication].[Customer] cu
INNER JOIN [client].[Client] cl
ON cl.Id = cu.ClientId
INNER JOIN
(
SELECT CustomerId, SUM(Fee) AS [FeeSum], MAX(OrderDate) AS [LastOrderDate]
FROM [publication].[Order]
WHERE o.[State] = 2
GROUP BY CustomerId
) o
ON o.CustomerId = cu.Id
INNER JOIN
(
SELECT CustomerId, SUM(Amount) AS [PaymentSum], MAX(PaymentDate) AS [LastPaymentDate]
FROM [publication].[Payment]
WHERE o.[State] = 2
GROUP BY CustomerId
) p
ON p.CustomerId = cu.Id
INNER JOIN
(
SELECT ClientId,
MAX(CASE WHEN TemplateName = 'Reminder' THEN Created END) AS [LastReminderDate],
MAX(CASE WHEN TemplateName = 'Warning' THEN Created END) AS [LastWarningDate]
FROM [client].[File]
GROUP BY ClientId
) f
ON f.ClientId = cl.Id
WHERE
cu.[Type] = 0;

T-SQL Populate Column Using While Loop

I have the following problem, and SQL isn't my strongest skill yet. I have the following procedure in SQL Server 2014 that works for returning the amount of money in each individual Quote for a Quoting System. Each Quote has Groups, which in turn have Parts in them.:
USE [My_DB_Name]
GO
DECLARE #QuoteNumberID int;
SELECT #QuoteNumberID = QuoteNumberId FROM [Quote].[Quote]
WHILE #QuoteNumberID IS NOT NULL
BEGIN
INSERT INTO [Quote].[ZQuoteBackupGL117] (QuoteAmount)(
SELECT ISNULL(SUM(ExtendedPrice) ,0) AS QuoteTotal
FROM(
SELECT (Quantity * ((UnitPrice - ISNULL(DollarDiscount, 0)) -
ROUND((((ISNULL(PercentDiscount,0)/100 + ISNULL(CustomerPercentDiscount,0)/100))) * UnitPrice, 2))) AS ExtendedPrice
FROM [Quote].[PartGroupPart] p
INNER JOIN [Quote].[QuotePartGroup] g ON p.PartGroupID = g.PartGroupID
INNER JOIN [Quote].[ZQuoteBackupGL117] q ON g.QuoteID = q.QuoteID
WHERE QuoteNumberId = #QuoteNumberID AND g.IsRecommended = 0 AND g.ExcludeFromTotal = 0 AND (q.GrandTotalValue IS NULL OR q.GrandTotalValue = 0)
)tmp)
SELECT #QuoteNumberID = MAX(QuoteNumberId) FROM [Quote].[Quote] WHERE #QuoteNumberId > QuoteNumberID
END
What I'm trying to do is get the value of QuoteTotal and put it in a new field in the [Quote].[ZQuoteBackupGL117] backup table named QuoteAmount(money, allow nulls) in each entry in the table. I will also run it on my production table later. Normally, I would avoid using a loop for this, but this query is only meant to run once to populate QuoteAmount for retroactive Quotes, of which there are thousands. I have looked into using INSERT INTO, but I'm not sure how I am supposed to structure it using this loop. Any help you guys can give me would be appreciated.
You probably want something like this.
UPDATE [Quote].[ZQuoteBackupGL117]
SET QuoteAmount = (
SELECT (Quantity * ((UnitPrice - ISNULL(DollarDiscount, 0)) - ROUND((((ISNULL(PercentDiscount,0)/100 + ISNULL(CustomerPercentDiscount,0)/100))) * UnitPrice, 2))) AS ExtendedPrice
FROM [Quote].[PartGroupPart] p
JOIN [Quote].[QuotePartGroup] g ON p.PartGroupID = g.PartGroupID
JOIN [Quote].[ZQuoteBackupGL117] q ON g.QuoteID = q.QuoteID
WHERE QuoteNumberId = #QuoteNumberID AND g.IsRecommended = 0 AND g.ExcludeFromTotal = 0 AND COALESCE(q.GrandTotalValue,0) = 0
)
WHERE QuoteNumberId = #QuoteNumberID
but I wouldn't bet any money on it.

TSQL Faster In Cursor Loop

Building up a query.
The single query is shown below and runs in 7.0 seconds. It does return the correct answer. Need to count rows based on certain conditions and then get the maximum count. My problem is performance of this stand along query. That same query wrapped in a cursor is 0.15 seconds. In the cursor the query plan is much different. How can I make the stand alone query run faster?
Using hints was able to get the stand alone to plan to look like the cursor plan and that fixed the speed problem.
Fixed query: (not all the way fixed as OPTION fails)
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [docSVenum1] with (nolock)
INNER LOOP JOIN [FTSindexWordOnce] as w1 with (NOLOCK, FORCESEEK)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER HASH JOIN [FTSindexWordOnce] as w2 with (NOLOCK)
ON w1.wordID = w2.wordID and w2.[sID] = '2'
GROUP BY W1.[sID]
-- OPTION (HASH GROUP)
) as list;
problem query:
select getdate();
go
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = '2'
GROUP BY W1.[sID]
) as list;
go
select getdate(); -- 7.0 seconds
I also need to run that single query against multiple values and put it in a cursor with a loop. I know cursor is bad but I could not figure out how to do it without a cursor.
The query stand alone and inside the loop both return the same correct answer.
My surprise is the exact same query inside a cursor loop is 40 times faster.
DECLARE #sid int
DECLARE sID_cursor CURSOR FOR
SELECT top 80 sID
FROM docSVsys
WHERE sID = '2' -- actually I want to not have this and let it loop through all
-- when i built the loop i saw performance improvement
ORDER BY sID
OPEN sID_cursor
FETCH NEXT FROM sID_cursor
INTO #sID
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #sID
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = #sID
GROUP BY W1.[sID]
) as list
FETCH NEXT FROM sID_cursor
INTO #sID
END
CLOSE sID_cursor;
DEALLOCATE sID_cursor;
go
select getdate(); -- 0.15 seconds
Using hints was able to get the stand alone to plan to look like the cursor plan and that fixed the speed problem.
Fixed query: (not all the way fixed as OPTION fails)
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [docSVenum1] with (nolock)
INNER LOOP JOIN [FTSindexWordOnce] as w1 with (NOLOCK, FORCESEEK)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER HASH JOIN [FTSindexWordOnce] as w2 with (NOLOCK)
ON w1.wordID = w2.wordID and w2.[sID] = '2'
GROUP BY W1.[sID]
-- OPTION (HASH GROUP)
) as list;