** Edit: Executing the package with T-SQL script causes an authentication problem:
"Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'." **
** Edit 2: This error is caused by Windows credentials performing a double hop. Here is a solution to this problem **
I'm trying to execute an SSIS package that was already deployed to an SQL Server instance before. This SQL Server instance's version is 14.0.3281 (SQL Server 2017).
I can't use project reference as the wanted package is in another project, and I prefer not to upload it to the server's file system.
Is it really a version problem?
How can I execute a deployed package from another project?
I know I can run the a job with this package with T-SQL, but I want the task to continue only after this package has successfully completed its execution.
This is the error I get:
The attempted operation is not supported with this database version.
------------------------------ ADDITIONAL INFORMATION:
The attempted operation is not supported with this database version.
There is a way to run a package via T-SQL and wait for it to finish using built-in procedures.
-- Create the execution object
DECLARE #execution_id BIGINT
EXEC [SSISDB].[catalog].[create_execution]
#package_name = #PackageName
, #project_name = #ProjectName
, #folder_name = #FolderName
, #use32bitruntime = False
, #reference_id = NULL
, #execution_id = #execution_id OUTPUT
-- Configure execution
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
#execution_id
, #object_type = 50 -- System parameter
, #parameter_name = N'SYNCHRONIZED'
, #parameter_value = 1 -- set this to 1 to wait for completion
-- Start the execution
EXEC [SSISDB].[catalog].[start_execution] #execution_id
You could wrap this into a stored procedure like "startPackage" and also include checking for the result using the execution id:
-- Check package status, and fail script if the package failed
IF 7 <> (SELECT [status] FROM [SSISDB].[catalog].[executions] WHERE execution_id = #execution_id) AND #Syncronized = 1
RAISERROR('The package failed!', 16, 1)
Related
I have just set up a new SQL Server instance on a new server and moved our application to use the new server. So I've had to turn SQL Agent off on the old server - turning it on would start the scheduler and start sending out emails and running things that shouldn't be run any more.
However, I need to take a close look at a SQL Agent Job on the old server, and ideally reverse-engineer the code to recreate it so I can modify it and apply it to the new server.
How do I generate the code for that Job on the old server without turning SQL Agent on?
Thanks
Even if SQL server agent is not running, you can see how jobs and schedules were set up by viewing the following system DMVs.
msdb.dbo.sysjobs_view
msdb.dbo.sysjobs
msdb.dbo.sysjobschedules
msdb.dbo.sysschedules
I use preset scripts to create all my jobs and schedules independent of the server. Here is a sample script to create the recycle log job. You can modify this or use any piece of this as you see fit.
DECLARE #sql nvarchar(max)
BEGIN TRY
IF EXISTS (SELECT job_id
FROM msdb.dbo.sysjobs_view
WHERE name = N'Cycle SQL log')
EXEC msdb.dbo.sp_delete_job #job_name=N'Cycle SQL log'
, #delete_unused_schedule=1
EXEC msdb.dbo.sp_add_job
#job_name = N'Cycle SQL log',
#description = N'This job forces SQL to start a new error log (In the Managment node of SSMS)',
#owner_login_name = N'your_sql_login' ;
EXEC msdb.dbo.sp_add_jobstep
#job_name = N'Cycle SQL log',
#step_name = N'sp_cycle_errorlog',
#subsystem = N'TSQL',
#command = N'exec sp_cycle_errorlog' --put your executable code here
--These next two lines set the target server to local, so that the job can be modified if necessary
SET #sql = 'EXEC msdb.dbo.sp_add_jobserver #job_name=N''Cycle SQL Log'', #server_name = N''' + ##SERVERNAME + ''''
EXEC sys.sp_executesql #stmt = #sql
END TRY
BEGIN CATCH
PRINT 'Uh-oh. Something bad happened when creating the Cycle SQL Log job. See the following error.'
PRINT CAST(ERROR_MESSAGE() AS NVARCHAR(1000))
END CATCH
You can use use code to automate the addition of schedules based on values you pull from the DMVs listed above.
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.
I have multiple SSIS projects, but some of the packages inside them are the same.
I would like to create a project with all the generic packages and keep the others projects with theirs specific packages.
So my question is : is it possible to have a master package that can execute and pass parent variables to packages from another project ?
I'm new to SSIS so sorry if it's an obvious question or if i'm not specific enough
When you configure an Integration Services catalog you can execute the packages from another project.
After deploying your all projects in the SSIS Catalog. Go to SSIS Catalog and browse to the package you want to execute.
Right click and select execute
It will pop up a window and ask for required paramter to fill up then
Click on the script menu and select New query editor window
Extra steps - Delete the Select #execution_id (not neccessary)
Extra steps - Delete the DECLARE #var0 smallint = 1 line and replace #var0 with 1 (in the line it will be #parameter_value=1 )
Do not close the sql query window as you need to copy the generated script
Now in your master package:
Add a Execute SQL Task
Add OLE DB connection manager to SSISDB database
In the Execute SQL Task Editor--> SQLstatement: paste here the generated package script
An example of the script:
Declare #execution_id bigint
EXEC [SSISDB].[catalog].[create_execution] #package_name=N'testpackage.dtsx', #execution_id=#execution_id OUTPUT, #folder_name=N'TestFolder', #project_name=N'TestProject', #use32bitruntime=False, #reference_id=Null
Select #execution_id --delete this line
DECLARE #var0 smallint = 1 `-- delete this line`
EXEC [SSISDB].[catalog].[set_execution_parameter_value] #execution_id, #object_type=50, #parameter_name=N'LOGGING_LEVEL', #parameter_value=#var0 `--(replace this #var0 with 1)`
EXEC [SSISDB].[catalog].[start_execution] #execution_id
GO
Passing parameter: Add the following two line to add pass a paremeter
DECLARE #ReportDate nvarchar(100) = `?`
EXEC [SSISDB].[catalog].[set_execution_parameter_value] #execution_id, #object_type=30, #parameter_name=N'ReportDate', #parameter_value=#ReportDate
Now from "Parameter Mapping" tab on the Execute SQL Task Editor add your variable you want to pass as a parameter.
Remember that variable data type has to be same as the parameter data type.
If you are leaving the Logging level as Basic (1), which is the default, you do not need to set this every time. Also, there is a bug in the SSISDB.[catalog].[set_execution_parameter_value] sp if you run a number of these steps in parallel. This can cause a DEADLOCK on the execution_parameter_values. I've raised this issue with MS.
I would have added as a comment but I don't have enough rep.
I use SQL Server Agent to fill tables in DataWarehouse. I have about 50 steps in the job and every step is run with a proxy account. And every step works correctly besides one:
SSIS package which contains about 20 Execute SQL Tasks which execute procedure. This is what I have in the Execute SQL Task:
DECLARE #RC int
DECLARE #fordate datetime = null
DECLARE #tablename sysname = 'D_ENTITY'
DECLARE #dataFolder varchar(1024) = 'C:\MountPoints1\src_etl\'
DECLARE #logFolder varchar(1024) = 'C:\MountPoints1\src_etl\'
DECLARE #debug bit = 0
EXECUTE #RC = [dbo].[ETL1A_HR]
#fordate
,#tablename
,#dataFolder
,#logFolder
,#debug
GO
The thing is, that if I execute the package from the SSIS catalog, it works ok. But if it is run by job, it succeeds, but only deletes from tables, but doesn't fill it. It seems like the procedure stops somewhere in the middle.
Any ideas?
Please advise, it took me days trying to solve this...
I think it maybe related to permissions. Executing the SSIS package will use your security context but running it from the agent impersonates the credentials defined in the proxy, and then runs the job step by using that security context.
I have a stored procedure which runs and calls an SSIS pacakge using EXEC SSISDB.CATALOG.start_execution #Execution_Id method.
However I need the package to execute under a service account with more privileges and not the user's account.
using the EXECUTE AS LOGIN = doesn't work. Does anyone know how to accomplish this. The only other way I know involves Agent Jobs and proxy accounts.
Surely there is a simply way to accomplish this on SQL 2012 ?
'EXECUTE AS' works fine for me.
One thing to note is to switch context to the SSIS Catalog database, before calling the execute method. Hence the 'USE ' statement on top.
USE SSISDB;
EXECUTE AS LOGIN = 'domain\user'
DECLARE #execution_id BIGINT
EXEC CATALOG.create_execution #folder_name = 'MyFolder1',
#project_name = 'MyProject', #package_name = 'Package.dtsx',
#use32bitruntime = 1, #execution_id = #execution_id OUTPUT;
EXEC CATALOG.start_execution #execution_id;