How to execute nested scripts in Sql Server 2005+ - sql-server

Do any sql ninja's know how to execute a script (.sql) from within another script? Specifically for the Sql Server 2005+ platform. E.g. psudeo code follows:
ScriptA contents
RESTORE DATABASE [MyDbName]
FROM
DISK = N'path' WITH FILE = 1
.......
GO
Exec c:\scripts\ScriptB.sql
ScriptB contents
USE [MyDbName]
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MyTableName]') AND type in (N'U'))
CREATE TABLE [dbo].[MyTableName]
........
GO

You can turn SQLCMD mode on from SSMS or run your script in SQLCMD.exe.
SQLCMD supports script variables and script references.
---script1-----
create table ....
:r path/to/another/script (which can reference others)
---------------
hope this helps

The following article provides examples of how you can achieve this.
http://www.sqlservercentral.com/articles/Administering/scriptrunner/292/
Here is a free tool that can run multiple scripts but not from within an existing script.
http://www.xsqlsoftware.com/Product/ProductDetails.aspx?ProdID=ScriptExecutor
Here is an example of executing a script from within another script by calling the isql utility using the xp_cmdshell stored procedure.
http://www.sqlservercentral.com/articles/Administering/scriptscheduling/450/
Should be what you need to get going but drop me a line if you need further assistance.
Cheers, John

Core MS SQL doesn't do this, but some tools have some macro capabilities (i.e. done client site).
SQLCMD supports ":r" to import another file.

As far as i can see you dont have to combine the two scripts. You can just execute the first and then the other.
You can do this by making a vbscript that loads the .sql files and then uses an ADODB.Connection to execute the two scripts.
This vbscript should do it:
Set con = CreateObject("ADODB.Connection")
con.ConnectionString = "*** Database connection string here ***"
con.Open
Set fso = CreateObject("Scripting.FileSystemObject")
Set sqlFile = fso.OpenTextFile("scriptA.sql", 1)
con.Execute sqlFile.ReadAll
sqlFile.Close
Set sqlFile = fso.OpenTextFile("scriptB.sql", 1)
con.Execute sqlFile.ReadAll
sqlFile.Close
Set fso = Nothing
Set con = Nothing

Related

Export password protected xlsx file and e-mail it

Currently I'm working with SSIS package that is executing a Stored Procedure and generating an .XLSX file with the results of the query.
What I'm needing to do is to encrypt the .xlsx file. it could be done either encrypting the file after being populated with the SSIS package, or by putting a password on the .xlsx file beforehand and opening it (reading password protected file) and exporting data to it.
*I know that password protected files are not super safe, but for this case I only need it to be password protected for compliance.
I was investigating with SSIS and I believe I can do it with a powershell script that can be run using an "Execute Process Task" tool from SSIS, please correct me if I'm wrong on this.
Update: I'm executing with an "Execute Process Task" a PowerShell script (script.ps1):
Set objExcel = CreateObject(“Excel.Application”)
objExcel.Visible = True
objExcel.DisplayAlerts = FALSE
Set objWorkbook = objExcel.Workbooks.Add
Set objWorksheet = objWorkbook.Worksheets(1)
objWorksheet.Cells(1, 1).Value = Now
objWorkbook.SaveAs “C:\Scripts\Test.xlsx”,,”Password123”
objExcel.Quit
However here I don't knowhow to point to the Excel file I created with the package to password protect it, am I missing something?
this is what my package design looks in SSIS:
And this is the detail of the "Execute Process Task" called "Lock excel file generated":
*This comes from source: https://techcommunity.microsoft.com/t5/SQL-Server-Integration-Services/Run-PowerShell-scripts-in-SSIS/ba-p/388340
You can create encrypted Excel spreadsheets in Powershell.
You'd create a scheduled task to fire of a Powershell script, along the lines of
Set objExcel = CreateObject(“Excel.Application”)
objExcel.Visible = True
objExcel.DisplayAlerts = FALSE
Set objWorkbook = objExcel.Workbooks.Add
Set objWorksheet = objWorkbook.Worksheets(1)
//Whatever you do to populate the workbook
Set filename = [System.IO.Path]::GetRandomFileName()
objWorkbook.SaveAs filename,,”%reTG54w”
objExcel.Quit

vbscript call isql script

I have a current vbscript that runs a simple sql statement and passes this to a crystal report to run against a sybase database - like below
SybaseRecordSet.Open "SELECT * FROM v2Region where code IN ('BTN', 'MAN', 'IRE', 'DUB')", SybaseConnection, adOpenStatic, adLockOptimistic
I would like to run a more complex sql statement and have tried various ways to add this into the sql script without success
Is there a way for the command below to open an external sql txt file into a variable and then open like below
Function do_something
Dim fso
Set file = fso.OpenTextFile("D:\ideal v2.5\Amalgamated_Overdue_Report.sql", 1)
sql_content = file.ReadAll
SybaseRecordSet.Open sql_content, SybaseConnection, adOpenStatic, adLockOptimistic
currently this is giving
Error - Object required: 'fso'
code - 800A01A8

Executing Stored Procedure From MS Access Causes Timeout

The weirdest thing. I have a simple procedure that I developed in Microsoft Access 2010 with a SQL Server 2012 backend. I am now trying to deploy this into production which is Access 2016 and a SQL Server 2014 backend.
I've compiled, compact and repaired in the new environment... but I can not get Access to execute this simple stored procedure. Even worse it still executes several other stored procedures fine... but a couple of them it times out and refuses to execute?
Here is my VBA and stored procedure:
Private Sub GenerateUnitKey(UnitColumns As String)
Dim Msg, Style, Title, Response As Variant
Dim lngProcessID As Long
Dim Conn As ADODB.Connection
Dim Cmd As ADODB.Command
Dim CurrentConnection As String
CurrentConnection = LinkMasterConnection()
Msg = "Are you sure you want to update the UnitKey with the selected columns?"
Style = vbYesNo + vbCritical + vbDefaultButton2
Title = "Save Campaign?"
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
Call OpenSixHatLoader("Generating Unit Key Across Campaign Records", 1, "")
Set Conn = New ADODB.Connection
Conn.Open CurrentConnection
Set Cmd = New ADODB.Command
With Cmd
.ActiveConnection = CurrentConnection
.CommandText = "usp_GenerateUnitKey"
.CommandType = adCmdStoredProc
.CommandTimeout = 30
.Parameters.Append .CreateParameter("#UnitColumns", adVarChar, adParamInput, 4000, UnitColumns)
.Execute
End With
End If
End Sub
And stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_GenerateUnitKey]
#UnitColumns AS VARCHAR(4000)
AS
SET NOCOUNT ON
DECLARE #SQL AS VARCHAR(MAX)
UPDATE tblStagingTable SET UnitKey =''
SET #SQL = 'UPDATE tblStagingTable SET UnitKey = ' + #UnitColumns + ' FROM tblStagingTable st'
EXEC(#SQL)
-- UPDATE Interests to match Staging Table
UPDATE tblInterests SET UnitKey = st.[UnitKey] FROM tblInterests i
INNER JOIN tblStagingTable st ON i.StagingTableID = st.StagingTableID
I am fairly confident there is nothing wrong with the code... as I said it worked fine in my development environment... even more I am manually able to execute the stored procedure within SQL Server. My SQL Server Native Client 11.0 connection works in executing other stored procedures... but for a couple of them it does not work. I am thinking I need to configure something within SQL Server itself or maybe within the Native Client 11.0 driver?
Unfortunately it gives no exception. I've set the CommandTimeout property to 0 and let it chug for a few hours hoping it would throw and exception to give me a clue but nothing... it just was frozen trying to execute. Any suggestions or ideas would be greatly appreciated because this one has me really stumped because it should be fine!
I would first launch SSMS, and from the SQL studio type in
Exec xxxxx ''
And ensure it runs (and use the SAME logon and connection to SSMS that you currently have for Access.
I would also consider creating a pass-though query, and saving that query in access. (set returns records = false if the sp does not return records). Then in code to run any proc, you can go:
With CurrentDb.QueryDefs("qryPass")
.SQL = "exec usp_GenerateUnitKey '" & UnitColumns & "'"
.Execute
End With
You note how simple the above code is - so if sp works from SSMS, then try the above code.
This was a difficult one that took me about 3 solid days of troubleshooting to get a solution to. Although I am not satisfied with the end solution as it should have just worked... but in the end my theory of the server being an Virtual Machine proved correct. When I deployed this exact same setup to Microsoft Access 2016 32 bit and SQL Server 2014 32 bit on a dedicated server it worked exactly as it was supposed to compared to the Azure VM and 1&1 Cloud Servers I had attempted to deploy to.
SQL Server integration with VM's is getting better from what all I have read, but apparently there is a ways to go. Maybe SQL Server needs to release a special VM version. Thank you to all those who took the time to look into this.

Excel VBA - Executing a job within SQL Server via a macro

I have a job stored on a database, scheduled to run every day. But its sometimes necessary to want to execute this job at any given time to view up to date data (I'm using SQL Server Management Studio 2008).
The job itself simply takes data from a view which contains live data and puts it into a table which will then be used as a data source for an excel file. Executing the job drops and re-creates the table with fresh data.
In excel (2010), i wish to have a 'button' which which pressed will execute the job and then hitting refresh on the data tab in excel will then update the data on the sheet with the fresh data.
My question is: How do i execute this job from an excel macro?
Private Sub CmdRunJob_Click()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
con.Open = "DRIVER={SQL Server};SERVER=YourServer;" & _
"USER=YourUser;PASSWORD=YourPassword;"
con.Execute "exec msdb.dbo.sp_start_job 'YourJob'"
End Sub
You create a SP that moves data from view to table.
Then modify the Job that it executes that SP by schedule.
Then in Excel Macro you can just use that SP to update the data.
Or see example how to run the Job from VBScript
You can use SQLDMO.SQLServer to execute your job.

SQL Server 2005 stored procedure fast in SSMS slow from VBA

I have a stored procedure which when run from SQL Server Management Studio consistently takes 5 seconds to run when called like this.
exec dbo.MyStoredProc '2009-04-30 00:00:00', '2009-04-30 20:00:00'
When called from an excel spreadsheet via VBA it takes 6 minutes plus (not including the time taken to copy the recordset to a sheet. The VBA is nothing fancy simply using an ADO connection to return a recordset. Unfortunately the Excel approach is a client requirement that I can't get rid of yet.
Public Function GenerateSQL(strQueryName As String) As Recordset
Dim rs As Recordset, cm As Command, dbsConn As Connection
Set dbsConn = New ADODB.Connection
dbsConn.Open Configuration.Range("ConnectionString")
Set cm = New ADODB.Command
With cm
.CommandText = strQueryName
.CommandType = adCmdStoredProc
.CommandTimeout = 300
.ActiveConnection = dbsConn
Set rs = .Execute()
End With
Set GenerateSQL = rs
End Function
Does anyone have any idea why this would happen or how I could begin to trace what is happening?
Thanks,
Steve
Everything you need to know about this topic: Slow in the Application, Fast in SSMS? Understanding Performance Mysteries
I believe I have the same problem as Steve Homer.
In addition to this SO question I also found this thread on eggheadcafe.com Very slow SP execution when using .net - very fast in Management Studio - totico
The answers say it's about parameter sniffing and how that affects which execution plan is used. The answers there specifically mentions the arithabort set option and how that affects the selection of plan.
Now I just need to find out how to change the set options from VBA...
Finally thanks to this forum entry on social.msdn.com i managed to get it right. First, set multiple connections to false:
connectionObject.Properties("Multiple Connections") = False
and then use the following function on your connection to set arithabort on ...
Private Sub OptionSet(ByRef cnn As adodb.Connection)
Dim cmd As adodb.Command
Set cmd = New adodb.Command
With cmd
Set .ActiveConnection = cnn
.CommandType = adodb.CommandTypeEnum.adCmdText
.CommandText = "set arithabort on"
Call .Execute
End With
Set cmd = Nothing
End Sub
Use SQL Server Profiler
Set up a trace on your database.
Limit the trace only to the stored procedure object in question
Limit to the username used by the VBA code
An introduction to SQL Server Profiler
In particular, check the SET options used by the connection and compare these with the defaults used when running the stored procedure in SSMS.
I have come across scenarios before where the SET options were different between calling code and within SSMS and the difference in performance was HUGE.
Thanks I'll take a look at the trace tools.
In reply to the comments on the original question
Are you using the exact same parameter values?
Yes exactly the same.
How much data is being returned (roughly) - number of rows and columns (and are any of them particularly big)?
Under 200 rows, perhaps 15 fields mostly ints with a couple of 20 character varchars.
Can you run SQL profiler and confirm if the sql is the issue or the remains of the macro in excel ?
The SQL is pretty ugly, as is the underlying database schema, and unfortunately is under NDA so I can't post it. If the query were the issue then wouldn't it be slow in management studio too though?

Resources