I'm running a SQL Server 2008 64 bit Developer Edition with Service Pack 1 installed.
I have a SQL Server Agent Job. Within this job I want to get the job_id of my own job.
On MSDN (http://msdn.microsoft.com/en-us/library/ms175575(v=SQL.100).aspx) you can find a description of using tokens in job steps. Wow, great, that's what I'm looking for!! Just use (JOBID).
Since SQL Server 2005 SP1 you have to use macro like $(ESCAPE_NONE(JOBID)). No problem.
But if you try the example:
DECLARE #name NVARCHAR(128)
select #name = name from msdb.dbo.sysjobs where job_id = $(ESCAPE_SQUOTE(JOBID))
PRINT #name
you get:
Incorrect syntax near 'ESCAPE_SQUOTE'. (Microsoft SQL Server, Error: 102)
Ok, now from the scratch:
PRINT N'$(ESCAPE_SQUOTE(JOBID))'
results in 0xE33FE637C10B3C49A6E958BB3EF06959 but the job_id is
37E63FE3-0BC1-493C-A6E9-58BB3EF06959
The "N'" I think makes an implicit conversion to NVARCHAR of the (JOBID)...
Ok, I think I have to care about the datatype of (JOBID). In the book "SQL Server 2008 Administration" on page 168/169 there's also an example of using (JOBID):
declare #jobid binary(16)
SELECT #jobid =Convert(Uniqueidentifier,$(ESCAPE_NONE(JOBID)))
results in:
Incorrect syntax near '('. (Microsoft SQL Server, Error: 102)
I'm totally confused now. Could please someone help me with a good advice or solution. Every kind of help is appreciated.
Best regards
Helmut
We had trouble with this recently and did not go the route you found in MSDN. Instead, we recovered the jobid from dbo.sysjobs by name directly (the opposite of your example) and then used that within the job to check execution status (exiting out of long running while loop if job state had changed).
declare #jobid uniqueidentifier
SELECT #jobid = job_id from msdb.dbo.sysjobs where name = '[blah]'
thanks for your answers. The problem is that I tried to parse the statement in job step. Then I got this error. While running the job there's no problem.
My very best solution now is:
declare #JobID uniqueidentifier
SELECT #JobID = $(ESCAPE_NONE(JOBID));
PRINT 'My JobID is ' + Convert(char(255), #JobID)
Now you handle with #JobID, but as far as I know until now you have to convert always to char(255).
Thanks to user state_dba on MSDN.
Just forget what parser is saying - variable resolution is done at runtime. Parser does not know about that.
This may sound obvious, but I get the error you quoted from your first sample, if I run it in a query window, but it runs perfectly well when I paste that script into a job step.
You can only use these tokens within job steps. And, given that we're not expecting any quotes in the jobid token, I'd use ESCAPE_NONE whenever you reference it.
For those that need an alternative method to get your own job ID without macros, for example, from within a stored procedure that a job step calls. I found the following here
DECLARE #SQL NVARCHAR(72),
#jobID UNIQUEIDENTIFIER,
#jobName SYSNAME
IF SUBSTRING(APP_NAME(),1,8) = 'SQLAgent'
BEGIN
SET #SQL = 'SET #guid = CAST(' + SUBSTRING(APP_NAME(), 30, 34) + ' AS UNIQUEIDENTIFIER)'
EXEC sp_executesql #SQL, N'#guid UNIQUEIDENTIFIER OUT', #guid = #jobID OUT
SELECT #jobName = name
FROM msdb..sysjobs
WHERE job_id = #jobID
END
Related
Can I make an IF statement that only executes when run manually from SSMS?
I have a SQL Server job that executes TSQL code. That TSQL code is maintained in a separate .sql text file. When it needs to be edited, I edit the text file and copy&paste the final results into the job.
This normally works very well but there is one critical line that is only used for testing (it sets a variable to a specific value). How can I guarantee that line only executes when run manually?
Is there something like If ManualExecution() then Blah?
IF APP_NAME() LIKE 'Microsoft SQL Server Management Studio%'
BEGIN
PRINT 'Running inside SSMS'
END;
If you use SQL Agent to run the job, it's app name should be SQLAgent - TSQL JobStep (Job 0x... : Step ...). If you use some other software, just make sure that it doesn't set its Application Name to "Microsoft SQL Server Management Studio"...
You can use the following code to get the SQL Server Agent JobId of the current process (otherwise NULL):
declare #JobId as UniqueIdentifier;
begin try
-- The executed statement will result in a syntax error if not in a SQL Server Agent job.
execute sp_executesql
#stmt = N'select #JobId = Cast( $(ESCAPE_NONE(JOBID)) as UniqueIdentifier );',
#params = N'#JobId UniqueIdentifier output',
#JobId = #JobId output;
end try
begin catch
if ##Error != 102 -- 102 = Syntax error.
select ##Error; -- Handle unexpected errors here.
end catch
select #JobId as JobId; -- NULL if not running as a SQL Server Agent job.
Note that the JobId can be used to access additional information about the current job in dbo.sysjobs.
On SQL Server, I am testing to create a Plan guide to force a query from Java to use a specific optimal execution-plan always. Some how the SQL query not using this Plan Guide
I followed, https://technet.microsoft.com/en-us/library/ms190772%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
SQL comes from Java,
declare #p1 int
set #p1=1986
exec sp_prepexec #p1 output,N'#P0 nvarchar(4000)',N'SELECT Top 1 Amount,col2 from dbo.table1
where ExId=#P0
order by id
',N'0a8e8e31-2a05-0000-8ece-0003fd69e692'
select #p1
Plan Guide I created,
DECLARE #xml_showplan nvarchar(max);
SET #xml_showplan = (select cast(query_plan as nvarchar(max)) from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text (cp.plan_handle) st
cross apply sys.dm_exec_query_plan (cp.plan_handle) qp
where st.text like '%Top 1 Amount%'
and objtype='Prepared')
--select (#xml_showplan)
EXEC sp_create_plan_guide
#name = N'ForceuserLoanAmountRequests',
#stmt = N'SELECT Top 1 Amount,col2 from dbo.table1 where ExId=#P0 order by id',
#type = N'SQL',
#module_or_batch = NULL,
#params = N'#P0 nvarchar(4000)',
#hints = #xml_showplan;
Appreciate if you can help me to get thru the plan guide used by SQL query from java.
Created a Plan Guide with the SQL collected from SQL Profiler,
EXEC sp_create_plan_guide
#name = N'ForceuserLoanAmountRequests',
#stmt = N'SELECT Top 1 Amount,col2 from table1
where ExId=#P0
order by ID
',
#type = N'SQL',
#module_or_batch = NULL,
#params = N'#P0 nvarchar(4000)',
#hints = #xml_showplan;
GO
Please read the article sp_create_plan_guide (Transact-SQL) pay attention to Remarks:
Plan Guide Matching Requirements
For plan guides that specify #type = 'SQL' or #type = 'TEMPLATE' to
successfully match a query, the values for batch_text and
#parameter_name data_type [,...n ] must be provided in exactly the
same format as their counterparts submitted by the application. This
means you must provide the batch text exactly as the SQL Server
compiler receives it. To capture the actual batch and parameter text,
you can use SQL Server Profiler. For more information, see Using SQL
Server Profiler to Create and Test Plan Guides.
This means that the statement should exactly match to what is written in your plan guide, but in your code plan guide is created for a statement that differs from those sending by java: it has only one row while java code has 4 rows with CR and additional spaces.
If you evaluate any hash from java statement and your statement provided in sp_create_plan_guide you'll see they are different.
Another thing I suspect that may be wrong is how you get a "good plan". Since you just assign #xml_showplan the result of a query that can produce many rows, I'm not sure you get the plan you want. How do you ensure that you capture the "good£ plan and not the same plan that java code produced?
I know this has come up a lot in the past but none of the fixes I've Googled or found on here has worked for me in this instance.
I'm running a fairly standard SQL Server Agent Job as a Transact-SQL script with the follow details: (replaced some stuff as *** for my boss's sanity)
-- Start T-SQL
USE msdb
EXEC sp_send_dbmail
#profile_name = 'MainProfile',
#recipients = 'test#test.co.uk',
#subject = 'T-SQL Query Result',
#execute_query_database = 'test30',
#query = 'SELECT ReferralReceivedDate,testRef,testcoMetadata.testcoRef,testcoMetadata.TimeSpentWithtester
FROM TestCasesTable, TestcoMetadata
WHERE testcasestable.CaseID = TestcoMetadata.CaseID AND AgencyName = [Test Injury] AND TestcoMetadata.TestcoRef IS NOT NULL AND TestcoRef <> ''
order by ReferralReceivedDate desc',
#attach_query_result_as_file=1,
#query_attachment_filename = 'Results.csv',
#query_result_separator = ','
-- End T-SQL --
The query itself runs fine as a normal query with no issues. The owner of this job has been used on other jobs again with no problems. In the step properties the Database selected is the same one as that mentioned in the #execute line.
I have a feeling this is either falling over the way it's trying to create the csv or something to do with permissions with dbmail part. I'm only a part time DBA so this has now lost me and I need help.
Replace this:
TestcoRef <> ''
With this:
TestcoRef <> ''''
You are creating dynamic sql, so you need to escape the single quotes.
So I never did get this working, but it turns out my boss already had something cooked up.
He had a stored procedure set up to run a batch file that was using an emailer exe to send the mail out, as its apparently better/more powerful than SQL mail.
I simply copied his S.P and amended it to include my query.
I've been given a user account to a SQL Server database that only has privileges to execute a stored procedure. I added the JTDS SQL Server JDBC jar file to SQL Developer and added it as a Third Party JDBC driver. I can successfully log in to the SQL Server database. I was given this syntax for running the procedure:
EXEC proc_name 'paramValue1' 'paramValue2'
When I run this as either a statement or a script, I get this error:
Error starting at line 1 in command:
EXEC proc_name 'paramValue1' 'paramValue2'
Error report:
Incorrect syntax near the keyword 'BEGIN'.
I tried wrapping the statement in BEGIN/END, but get the same error. Is it possible to call the procedure from SQL Developer? If so, what syntax do I need to use?
You don't need EXEC clause. Simply use
proc_name paramValue1, paramValue2
(and you need commas as Misnomer mentioned)
You are missing ,
EXEC proc_name 'paramValue1','paramValue2'
You need to do this:
exec procName
#parameter_1_Name = 'parameter_1_Value',
#parameter_2_name = 'parameter_2_value',
#parameter_z_name = 'parameter_z_value'
EXECUTE [or EXEC] procedure_name
#parameter_1_Name = 'parameter_1_Value',
#parameter_2_name = 'parameter_2_value',
#parameter_z_name = 'parameter_z_value'
I know this is the old one. But this may help others.
I have added SP calling function between BEGIN/END. Here is a working script.
ALTER Proc [dbo].[DepartmentAddOrEdit]
#Id int,
#Code varchar(100),
#Name varchar(100),
#IsActive bit ,
#LocationId int,
#CreatedBy int,
#UpdatedBy int
AS
IF(#Id = 0)
BEGIN
INSERT INTO Department (Code,Name,IsActive,LocationId,CreatedBy,UpdatedBy,CreatedAt)
VALUES(#Code,#Name,#IsActive,#LocationId,#CreatedBy,#UpdatedBy,CURRENT_TIMESTAMP)
EXEC dbo.LogAdd #CreatedBy,'DEPARTMENT',#Name
END
ELSE
UPDATE Department SET
Code = #Code,
Name = #Name,
IsActive = #IsActive,
LocationId = #LocationId,
CreatedBy = #CreatedBy,
UpdatedBy = #UpdatedBy,
UpdatedAt = CURRENT_TIMESTAMP
where Id = #Id
You need to add a , between the paramValue1 and paramValue2. You missed it.
EXEC proc_name 'paramValue1','paramValue2'
EXEC proc_name #paramValue1 = 0, #paramValue2 = 'some text';
GO
If the Stored Procedure objective is to perform an INSERT on a table that has an Identity field declared, then the field, in this scenario #paramValue1, should be declared and just pass the value 0, because it will be auto-increment.
There are two ways we can call stored procedure
CALL database name'. 'stored procedure name(parameter values);
example:- CALL dbs_nexopay_sisd1_dec_23.spr_v2_invoice_details_for_invoice_receipt_sub_swiss(1, 1, 1, 1);
From your MySQL workbench also you can do that.
i. Right-click on stored procedure.
ii. Send to SQL editor
iii. Procedure call.
If you simply need to excute your stored procedure
proc_name 'paramValue1' , 'paramValue2'...
at the same time you are executing more than one query like one select query and stored procedure you have to add
select * from tableName
EXEC proc_name paramValue1 , paramValue2...
The stored procedures can be run in sql developer tool using the below syntax
BEGIN
procedurename();
END;
If there are any parameters then it has to be passed.
Select * from Table name ..i.e(are you save table name in sql(TEST) k.
Select * from TEST then you will execute your project.
I have used sp_addlinkedserver to access the remote machines db now i am writing queries explicitly on database like,
select * from [server\instance].database.owner.tablename
Now with this,
[Server\instance] : this has to be provided explicitly
[database] : can we find databases on specified instance using query like ms_ForEachDB ?
[owner] : Can we find the database owner name using query ?
If these values are found using queries do we need to use EXEC() to execute this or we can still achieve it using nice queries ?
Thanks all,
The "nice" format you mention is simply a 4 part object reference.
select * from [server\instance].database.owner.tablename
3 part
select * from database.owner.tablename
2 part
select * from owner.tablename
If you want to dynamically change any of the server, db or schema values then you have one option:
EXEC (#sqlstring)
However, if you only access stored procs remotely...
DECLARE #RemoteSP varchar(500)
SET #RemoteSP = '[server\instance].database2.schema.proc2'
EXEC #RemoteSP #p1, #p2, #p3 OUTPUT
SET #RemoteSP = '[server\instance].database1.schema.proc1'
EXEC #RemoteSP #p4, #p5, #p6 OUTPUT
However, changing the components of the object reference makes no sense arguably: if you know you're going to query a table then just call that table in that database...
you should make a query string and then run it by exec() function.
getting server name :
SELECT ##SERVERNAME
getting current db name :
SELECT DB_NAME() AS DataBaseName
You do not have to use EXEC you could use something like select * from openquery(MyLinkedServer,#sql) THough i prefer EXEC(#sql) AT MyLinkedServer
But all work
If it happens that you need to use some sort of variable in your arguments(e.g. collect remote's server updates since yesterday):
DECLARE #yesterday NVARCHAR(20) = '2016-09-23 08:16:20';
DECLARE #sql NVARCHAR(MAX) = N'SELECT * FROM database.targetTable AS origin
WHERE origin.columnWithDateTime >'''+#yesterday+''';';
PRINT #sql;
EXEC(#sql) AT linkedServer
______
Where:
database.targetTable : For some reason SSMS 2008 R2 returns error if you describe it as [database].[targetTable], and i don't know why that happens.
#yesterday: Is the variable you want to insert (this case, a string containing datetime-like element)
PRINT #sql: Just to verify if the quotes are correctly placed.
columnWithDateTime: Should be a column with datetime format (e.g. "timestamp", or similar to the #yesterday variable format.
"OPENQUERY does not accept variables for its arguments.": See Here (MSDN: OPENQUERY (Transact-SQL)).