How do I get the user who invoked a SQL Agent job? - sql

I'm working on a job step which needs to reference the Login Name value for the user who started the job. It'll be passed as a value into a table field, which is then referenced by other processes.
I haven't been able to find if or where the starting username is stored in system tables. It must be stored somewhere as the (job outcome) step in msdb.dbo.sysjobhistory references is thusly:
The job succeeded. The Job was invoked by User [domain]\[username]. The last step to run was...
I'd like to capture that [domain]\[username] value for my job step. I know it can be done as a subsequent job, referencing the original and doing some string manipulation, but I'd prefer to do it in the same job, if possible.
Thanks in advance!

That is logged in the message column of the msdb.dbo.sysjobhistory table.
You may want to do some joins to the sysjobs table as well. I.E.
select
j.name as 'JobName',
run_date,
run_time,
msdb.dbo.agent_datetime(run_date, run_time) as 'RunDateTime',
case
when left(h.message,16) = 'Executed as user'
then substring(h.message,19,charindex('.',h.message,1) - 18)
when h.message like '%invoked by%'
then substring(h.message,charindex('invoked by ',h.message) + 11,charindex('.',substring(h.message,charindex('invoked by ',h.message) + 11,99)) - 1)
else h.message
end
From
msdb.dbo.sysjobs j
INNER JOIN
msdb.dbo.sysjobhistory h
ON j.job_id = h.job_id
where
j.enabled = 1 --Only Enabled Jobs
order by
JobName,
RunDateTime desc
REF

Related

SQL Server - keep restarting EXEC as long as dependent job completes

I need to automate element in my backups schedule for differential copies.
DIFF must be performed only when job_a is not running.
The only moment when below code clashes with job_a is when job_a may be still running in scheduled time for job_b to start. I need some pattern to keep re-running job_b till job_a won't be returned by first NOT EXISTS
I did a test where job_a starts run one second before job_b. While job_b should be trying to restart as long as job_a disappears from system logs, it abandons the retries.
IF NOT EXISTS
(SELECT job.name FROM msdb.dbo.sysjobs_view job
INNER JOIN msdb.dbo.sysjobactivity activity ON job.job_id = activity.job_id
INNER JOIN msdb.dbo.syssessions sess ON sess.session_id = activity.session_id
INNER JOIN (SELECT MAX(agent_start_date) AS max_agent_start_date FROM msdb.dbo.syssessions) sess_max ON sess.agent_start_date = sess_max.max_agent_start_date
WHERE run_requested_date IS NOT NULL
AND stop_execution_date IS NULL
AND job.name = 'job_a')
BEGIN
DECLARE #path_diff varchar(max)
SET #path_diff = 'H:\MSSQL13.MSSQLSERVER\MSSQL\Backup\dev\db_name' + CONVERT(varchar, GETDATE(), 112) + REPLACE(CONVERT(varchar, GETDATE(), 114),':','') + '_DIFF_COMP.BAK'
BACKUP DATABASE [db_name] TO DISK = #path_diff WITH COMPRESSION, DIFFERENTIAL , STATS = 10
END
--need a step that will re-start the job once job_a doesn't appear in NOT EXISTS
ELSE
EXEC msdb.dbo.sp_stop_job N'job_b'
PRINT 'Full backup is taking longer then usual, please inspect!'
EXEC msdb.dbo.sp_start_job N'job_b'

Find the ‘total sent’ for each JOB IDs in last 1 month along with ‘list name’ it was sent to in Marketing cloud

Currently by using this query, I get the number of total_sends for a particular JOB id. But I want to modify the Query so that it shows total_sends , ListName , Date for that each job ID within a specified timeframe.
Select
count(s.EmailAddress)
from [_Job] j
join [_Sent] se
on j.JobID = se.JobID
join [_Subscribers] s
on se.SubscriberID = s.SubscriberID
where
se.IsUnique = 1 and
se.EventDate > dateadd(d,-20,getdate()) and
j.JobID =11111
Here is the example of how my final Table should look like,
enter image description here
Here is the link to Data View/Table I am querying - https://sfmarketingcloudhome.files.wordpress.com/2021/02/dataviews_2021_v2.png
I haven't tested it yet but will something like this work for you? Make sure to modify / add the columns in your data extension if you are using Automation Studio.
Select
count(s.EmailAddress) as total_sends,
j.SchedTime,
ls.Listname
from [_Job] j
join [_Sent] se
on j.JobID = se.JobID
join [_Subscribers] s
on se.SubscriberID = s.SubscriberID
join _ListSubscribers ls ON se.SubscriberID = ls.SubscriberID
where
se.IsUnique = 1 and
se.EventDate > dateadd(d,-20,getdate()) and
j.JobID =11111

Running two sql server jobs into a single job not working

we have a sql server agent job which is running two sql servant jobs.The job is designed in the way that the second job will wait till the first job completed. But sometimes the wait is not working and it causes both jobs ends up running at same time. This causes failure of both jobs. We uses below code for waiting mechanism.
WHILE
(
SELECT COUNT(*) AS cnt
FROM msdb.dbo.sysjobs J
INNER JOIN msdb.dbo.sysjobactivity JA
ON J.job_id = JA.job_id
WHERE start_execution_date IS NOT NULL
AND stop_execution_date IS NULL
AND J.name = "first job name"
AND last_executed_step_date > DATEADD(DD,-1,GETDATE())--//Added to bypass historical corrupt data
) > 0
BEGIN
--WAIT
WAITFOR DELAY '00:01';
END
any suggestion why this is not working sometimes?

Access Update not working

I have an Access Database which links into Excel for a college database project. The goal is to fix incorrect/incomplete data before importation through the use of Update/SQL queries. There is one item in particular which is a field containing the order status. If an order is complete = Complete, if an order is missing a few parts = Backorder and nothing at all = Open. The issue I have is there is multiple parts on one PO ID# which makes it difficult to determine if an order is on backorder as 2/5 parts may be complete while 3/5 may be on backorder. Any ideas on how I can force access to automatically set a default order status or is this a long sql query?
Thanks
With SQL you can return a query to find the order status, using a CASE statement. I'm not sure of the table/column names in the parent table you have but you can probably tweak it from here (I'm just assuming identity columns):
SELECT P.Id, P.Name, "Status" =
CASE
WHEN R.QuantityReceived < I.QuantityOrdered THEN 'Backorder'
WHEN R.QuantityReceived = I.QuantityOrdered THEN 'Complete'
WHEN R.QuantityReceived > I.QuantityOrdered THEN 'Open'
END
FROM PurchaseOrders P INNER JOIN POItem I on P.PurchaseOrderId = I.PurchaseOrderId
INNER JOIN POReceipt R on I.ItemId = R.ItemId
So first you need to join your tables to get the related records (this is also assuming that there is only one of each), then use a CASE statement to return the value you are looking for based on a comparison between fields.

Return data entered in column order by row

I am working on a simple timesheet module for a larger production system and need to display a table of information to the user. I have the following tables to work with:
TimeRecords
ID
WorkerID
AssyLineID
Station
Sequence
NbrHours
DateSubmitted
Workers
ID
Name
AssyLines
Name
During data entry, time is entered by AssyLine for each worker. A given worker may work on 2 or more different stations during the course of the day. The Sequence value is assigned based on the order of names as entered during data entry.
Now I want to return this data for all assembly lines and all workers in the following format:
ResultSet
Worker.ID
Worker.Name
AssyLine.Name - group returned rows by assembly line, in alphabetical order
Sequence - within each assembly line, group by sequence
NbrHours - total hours for worker for this assembly line, all stations
TotalHours - total hours for this worker across all assembly lines and stations
Other caveats:
1) The rows for a given worker should be grouped together, starting with the assembly line where they logged the most hours, in the sequence for that assembly line. I plan to consolidate all entries for a given worker into one row for display to the user and this is much easier if all rows for one user are grouped together. If that can't be done I will have to group and sort the row data in code...
Here is the query I have come up with so far:
SELECT
w.ID
,w.Name
,a.Name
,tr.NbrHours
,tr.Seq
FROM
TimeRecords tr
INNER JOIN
Workers w ON
w.ID = tr.WorkerId
INNER JOIN
AssyLines a ON
a.AssyLineID = tr.AssyLineId
WHERE
tr.DateSubmitted < '2000-01-01'
ORDER BY
w.Name
,a.Name
,tr.Seq
,NbrHours DESC
Obviously this leaves a lot to be desired. The worker entries are not grouped together and there is no overall total for the worker.
Can anyone help me get this right? I'm thinking I will need to do this with a Stored Proc rather than a view...
Thanks,
Dave
Most of this can be done with a simple group by clause; the messy part comes with your requirement for showing all hours, but I believe something like this should work depending on what DB you are using:
SELECT
w.ID
,w.Name
,a.Name
,tr.Seq
,SUM(tr.NbrHours) as nbrHours
(SELECT SUM(tr.NbrHours)
FROM TimeRecords tr2
WHERE tr2.WorkerId = w.id and tr2..DateSubmitted < '2000-01-01') as TotalHours
FROM
TimeRecords tr
INNER JOIN
Workers w ON
w.ID = tr.WorkerId
INNER JOIN
AssyLines a ON
a.AssyLineID = tr.AssyLineId
WHERE
tr.DateSubmitted < '2000-01-01'
GROUP BY
w.ID
,w.Name
,a.Name
,tr.Seq
ORDER BY
ReportName
,ShortName
,tr.Seq