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.
Related
I'm trying to create a program that upload an excel table to SQL server and run a procedure of that takes the table as an input. The procedure is pretty complex with declare statement using injected variable, and dynamic variable (e.g. derived from injected variable, or select the latest table in the database). I tried several things but the proc were not executed.
Server='IP address'
Database='database name'
Driver='ODBC Driver 17 for SQL Server'
date = '20221220'
MONTH = '202211'
db = pyodbc.connect(driver=Driver, server=Server, Trusted_Connection='yes')
dbc = db.cursor()
stored_proc = f"exec db..proc #date = '{date}',#Month='{MONTH}'"
dbc.execute(stored_proc)
#I also tried this, but it did not worked either
#dbc.execute(f"db..proc {date}, {MONTH}")
#dbc.execute("db..proc ?,?", [date,MONTH])
I expected that the procedure was successfully executed and data are updated. However, no error were shown in python terminal, but data in the needed SQL table were not updated either. I suspect that pyodbc can run select, insert into, update, ... statements, but not the declare statement.
Can any one help me with this?
Many thanks
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 am using a FileTable in SQL Server 2014 and need to run an executable that parses the file name of any inserted/updated/deleted file and then in turn the executable inserts into other tables on the database the information that was parsed from the name. I do not expect the .exe to run long at all but if it runs into issues, I do not want to lock it for an extended period of time.
For instance:
CREATE PROCEDURE filename_parser
#name nvarchar(255)
AS
BEGIN
DECLARE #exe nvarchar(255)
SET #exe = 'c:\test\my.exe "' + #name + '"'
EXEC master..xp_cmdshell #exe
END
GO
If I run the stored procedure from an INSERT or UPDATE trigger, for instance:
USE [db_1]
GO
CREATE TRIGGER [dbo].[i_table_a]
ON
[dbo].[table_a]
AFTER
INSERT
AS
DECLARE #file nvarchar(255)
SELECT TOP 1
#file = name
FROM
inserted
EXEC filename_parser #name = #file
will I end up locking table_a until the executable completes? Sorry, if the answer is obvious. I have not found a straight forward answer. Any help/pointing in the appropriate direction is appreciated.
Related links:
Do stored procedures lock tables/rows?
SQL Server - How to lock a table until a stored procedure finishes
Microsoft docs say xp_cmdshell will run synchronously. Triggers run synchronously too. So, if your exe gets stuck, it will hang the trigger, which will hang the insert, and other stuff. msdn.microsoft.com/en-us/library/ms175046.aspx#remarks
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;
I need to add start-up trace flags to a SQL Service from a batch file. I have struggled to work out how to do this, and have finally come-up with the following, slightly clumsy approach, of using undocumented TSQL procedure and then calling it with SQLCMD. The problem is that it throws an error: RegCreateKeyEx() returned error 5, 'Access is denied.' However, another script on the same server, allows me to change other registry values, such as TCP Port. Any idea what I'm doing wrong, or a more elegant way of doing it?
DECLARE #VALUE nvarchar(200)
DECLARE #Key nvarchar(2000)
SET #VALUE = '-T1118 -3604 -E'
SET #Key = 'SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.' + (select SUBSTRING(##SERVERNAME,CHARINDEX('\',##SERVERNAME)+1,LEN(##SERVERNAME)-1)) + '\MSSQLServer\Parameters'
EXECUTE master..xp_regwrite
'HKEY_LOCAL_MACHINE',
#Key,
'SQLArg3',
'REG_SZ',
#VALUE
The expression to create the #Key variable elavuates to: SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MYINSTANCE\MSSQLServer\Parameters
which seems correct to me.
The registry key for the default instance of SQL Server is:
SET #Key = 'SOFTWARE\Microsoft\Microsoft SQL Server
\MSSQL11.MSSQLSERVER\MSSQLServer\Parameters';
(I wrapped the key above for readability - you need this all on one line.)
Unless you have named instances, you can use this #Key instead of yours. If you have named instances on the servers, you'd need to inspect SOFTWARE\Microsoft\Microsoft SQL Server\InstalledInstances to obtain the name(s) of the instance(s) on the server.
I imagine there is more elegant way of doing this using PowerShell.