alternative to xp_cmdshell bcp? - sql-server

Is there an alternative to xp_cmdshell BCP to write to a file from MSSQL?
Some context: This is to be built into a stored procedure called by an external program. I do not have the luxury to work through executable files, export functions of ssms, or any such things which require more than the calling of this stored procedure.
The reason; there's a lot of odd stuff on this server to do with user rights, and I'm not the SA. I cannot create the ##xp_cmdshell_proxy_account## (let alone assign credentials to it), and xp_cmdshell 'whoami' returns a user noone has ever seen or heard from. I've tried creating a new user based on an existing windows user and granting xp_cmdshell execute rights to it, but this still did nothing. I'm not sure if I don't have the rights or if it's something else.
So long story short, I'm fed up with trying to get this to work on this environment and am looking for an alternative. Is there one?

Write a SQL Agent Job and kick it off with sp_start_job. You can control the identity the job uses with a SQL Agent Proxy.
Or write an SSIS package, deploy it to the SSIS Catalog and run it from your stored procedure.

Related

Run SSIS package using T-SQL under different account

I normally run an SSIS package using a Sql Agent Job and a proxy user as described here: https://www.sqlservercentral.com/articles/run-an-ssis-package-under-a-different-account
I now need to run the same package using the same proxy user using T-SQL. I've been trying to use the [catalog].[create_execution] and [catalog].[start_execution] procedures to do this but there doesn't seem to be a way to specify a user.
How do I execute a package as a different user?
Is my best recourse the use of T-SQL to execute a SQL Agent Job that is configured to use the proxy user instead?
I don't know how agent actually works to make proxy users work - especially with regard to SSIS packages.
In a "normal" sql session say in SSMS, if I wanted to run a query as another user
EXECUTE AS USER = 'TurgidWizard';
SELECT USER_NAME() AS WhoAmI;
REVERT;
That code would allow me to impersonate you until I hit the REVERT call.
But, if you swap out calls to create_execution/start_execution you'll run into the same issue as trying to use a local sql server user runs into with using the methods in the SSISDB - it doesn't work. The methods in the SSISDB all run checks before they begin to ensure users have the correct access level and there isn't impersonation going on. Because once those methods start running, they themselves do impersonation so I guess that doesn't work well.
How can I run a package using tsql under a different account? I would start SSMS/sqlcmd under the credentials using RUNAS For example, the following will open a new command window as you.
runas /netonly /user:corpdomain.com\turgiwizard "cmd"
From there, things I do will be under the aegis of your user so I could run sqlcmd calls like
sqlcmd -S TheServer -d SSISDB -Q "EXECUTE catalog.create_execution ...;"
Mouse click will be Ctrl+Shift+right click executable.
Your SSMS install location is version dependent but try various ten digit increments of 140 in the following path
C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Ssms.exe
The downside for me with regard to runas is that I could not automate getting my credentials passed into it. I've seen articles about use auto hot key and such but never had any luck with it.
Cleanest/easiest approach for something that needs to run regularly is to use sql agent with a proxy, or you could use Windows Task Scheduler and create it as the target user. One off executions, I'd likely use the runas approach.

Run batch file from SQL

I want to run batch file from SQL Job without using exec xp_cmdshell.
Any idea?
Thanks
You could use a SQL Server Job, otherwise i cannot think of a way you could without xp_cmdshell.
Take a look at this
I want to run batch file from SQL Job without using exec xp_cmdshell.
Any idea?
Worth to mention that you can also leverage SQLCLR.
Example: CLR Stored procedure to execute command
Some other googlable threads:
How to execute a DOS command when xp_cmdshell is disabled in SQL Server
Executing an external process() in SQLCLR Project
Such approach introduces severe risks like memory leaks, crashing of underlying .net app pool etc
Therefore another link: Security in the CLR World Inside SQL Server
Instead of running batch file, i have created power shell and ran it from SQL job. It satisfy my requirement and resolved my issue.
Do it like the picture: like this image.
The drive containing the batch file should be other than the C drive, to avoid trouble.
Add execute, read and write permissions for the user, which you are using to run the batch file, to get the username run this query: EXEC master..xp_cmdshell 'whoami', get the name after the \ sign. For example "nt service\mssqlserver". Add permission for this user: mssqlserver
Finally make sure you put the batch file on the same server as where you execute your Job.

SQL Server to check for files in directory

I was wondering if it is possible for SQL Server to check a directory for files and run a stored procedure. I did some research and found this, but I am wondering if there is a way to do what I want WITHOUT SSIS.
EDIT: After reading my post, I realized I should have been more specific. Is there a way to AUTOMATICALLY or set SQL Server to check for files in a directory and run a stored procedure?
You can use xp_cmdshell to run file related commands. To get a directly listing:
exec xp_cmdshell 'dir *.csv';
You can also use bulk insert to load a file from disk into a table and take actions based on the loaded contents.
Normally you'd use the File Watcher Task with SSIS. But you can also use SQL Server Agent to schedule a task for periodic execution, schedule a task with Windows Task Scheduler, or configure a stored procedure to runs at startup with sp_procoption that pauses (using waitfor) between processing times.

Run an SSIS package remotely and programatically

Problem
I have developed an SSIS package for an ETL process, which I have deployed successfully to a remote server. I have windows and SQL logins for this server, but not admin. The data that this ETL process loads is generated on a different machine on a different domain early in the morning each day (i.e. before I get to work) and needs to be automatically loaded after the data generation process as soon as possible.
Currently, I manually run the ETL package in SSMS, and authenticate this by spoofing the windows user credentials on the remote server by launching SSMS with runas.exe. This is currently okay since we are in early development, but this is obviously not an acceptable solution in production. Hence, I would like to automate this process, since a) the data is extremely time sensitive and b) manually running this process is a PITA.
How should I go about automating execution of the ETL package such that:
Execution happens immediately after the data is available, and
No user input is required from me e.g. to enter passwords?
Attempted solutions
Scheduling a SQL server agent job on a schedule is not an option, because of the time sensitivity. (Also my sysadmin seems to have not enabled/disabled the SQL server agent)
Continuing to use runas.exe is not an option either, as the /netonly flag, which is required, and the /savecred flag, which would prevent the need for manual password entry, are mutually exclusive.
sqlcmd.exe can be scripted to run with a SQL user and password (bad practice putting passwords in plain text, I know) but then running a stored procedure that calls the SSIS package fails, as windows authentication is required to run the package.
I would strongly advice you to ask for working SQL Agent and create an Agent Job to run the package. This way has a lot of advantages:
Native Windows user credentials management with proxy accounts
You can configure specific values for package/project parameters, connection managers via SSMS interface
You can use environment references of SSIS 2012 and above, and manage it via SSMS as well
Job can be started on schedule or manually from SQL command. Thus you can automate package start.
In a nutshell - it is much easier to manage and you do not disclose user credentials needed to run the package - you might even do not know it.
For the alternative - you can try PsExec from SysInternals tools. It allows to start program on another computer explicitly specifying username and password as psexec \\server -u user -p password .... However, I would opt against it.

Opens DB & works fine on hoster, but on localhost: "Could not find stored procedure xyz"

I need to make some changes to an existing app that is running fine on my hoster. I download the database and can open it in Visual Studio for development and testing, but my localhost will not let me use the stored procedures that are there: "Could not find stored procedure xyz". I have made no changes yet, I want to make sure I have a fully functional environment before I start doing things.
The stored procedures are there -- I can see and use them all in SSMS.
I think I have permissions set correctly via SSMS, but I don't do this very often can easily have missed something somewhere. What do I do now? My connection strings for local vs hoster are identical, except of the server name.
Are you sure that the login for the DB is finding the correct database? Each login has a default database that it will look in for executing queries when the objects are not fully qualified. So if you are calling ProcName or dbo.ProcName in MyDatabase but the login has a default database of "master" then you can get that error. Either fully qualify the objects (not a bad idea anyway) or update the settings for the login to have the correct default database.

Resources