Is it possible to automatically force SQLCMD mode in script? - sql

We're using Visual Studio Database Professional and it makes heavy use of SQLCMD variables to differentiate between environments while deploying.
I know there's several directives available for setting context (like :connect for server name). Is there a way within the script itself to force SQLCMD mode for execution? Part of our deployment process is to have DBA's examine and execute the scripts and it would be a nice safety net (so I don't have to remind them to set their execution mode to SQLCMD).

Not a solution, but as a work-around, you could embed your script in some warning. This post inspired me to this code:
SET NOEXEC OFF; -- previous execution may have toggled it
:setvar IsSqlCmdEnabled "True"
GO
IF ('$(IsSqlCmdEnabled)' = '$' + '(IsSqlCmdEnabled)')
BEGIN
PRINT('Use SqlCmd-mode!!');
SET NOEXEC ON;
-- RAISERROR ('This script must be run in SQLCMD mode.', 20, 1) WITH LOG
END
ELSE
BEGIN
PRINT('Using SqlCmd-mode')
-- insert the code you really want to execute:
-- ...
END
SET NOEXEC OFF; -- do not disable next execution in this session

This does not seem to be possible. I even checked the SSMS project mode.
However, if you create a database project in BIDS, the pre-deploy & post-deploy scripts run in SQLCMD mode by default.
I know that is not the answer you want, but it is the best I can give you w/o resorting creating a custom SSMS plugin that would do it for you based on some text in the script file.

Related

Is there a SQL equivalent of return?

Consider the following bit of SQL
SET DATEFORMAT ymd
SET ARITHABORT, ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER, ANSI_NULLS, NOCOUNT ON
SET NUMERIC_ROUNDABORT, IMPLICIT_TRANSACTIONS, XACT_ABORT OFF
GO
USE master
GO
IF DB_NAME() <> N'master' SET NOEXEC ON
--
-- Create database [myDatabaseName]
--
PRINT (N'Create database [myDatabaseName]')
GO
CREATE DATABASE myDatabaseName
There is then a very long script setting up tables, views, stored procedures etc etc.
I would like to know if SQL would allow something along the likes of the following pseudo code;
If (myDatabaseName Exists)
Return // in other word abort the script here but don't throw an error
Else
//Carry on and install the database
I am aware of the Exists function in SQL but I can't seem to find anything that would simply abort the remains of the script straightaway.
This script will end up in an installation routine. In theory it should never be in an installer where the database is already present, however I would prefer not to take chances and prepare properly for a potential mistake. It is also crucial that the script does not throw any error as that will just cause the installer to roll back and install nothing.
I'm hoping that something exists in SQL that will just exit a script cleanly if particular conditions are met. By exit I really do mean exit as opposed to simply breaking out of the condition being currently evaluated.
The problem is, your client tool (SSMS, SQLCMd, etc) splits your script into batches based on the location of the GO keyword (it's a client tool thing, not SQL Server at all).
It then sends the first batch. After the first batch is complete (no matter what the outcome), it sends the second batch, then the third after the second, etc.
If you're running with sufficient permissions, a high-valued RAISERROR (severity 20-25) should stop the client tool in its tracks (because it forces the connection closed). It's not that clean though.
Another option is to try to set NOEXEC ON which still does some work with each subsequent batch (compilation) but won't run any of the code1. This allows you a slightly better recovery option if you want some batches at the end to always run, by turning it OFF again.
1Which means you still will see error messages for compilation errors for later batches which rely upon database structures that would have been created in earlier batches, if they weren't being skipped.
You can use GOTO as follows :
If (myDatabaseName Exists)
GOTO QUIT; // in other word abort the script here but don't throw an error
Else
//Carry on and install the database
QUIT:
SELECT 0;
There are several methods for that kind of request :
raiserror('Oh no a fatal error', 20, -1) with log
OR
print 'Fatal error, script will not continue!'
set noexec on
They should work and close the connection.
See here : Answer

Prevent SQL File From Running As a Script

I have tens of SQL files that contain individual queries and update commands. These commands are intended to be used as a starting point for manual updates to the database, they are not structured to be ran as scripts.
Is there an SQL command I can place at the start of these files to stop an inadvertent click of the 'Run Script' button? Return, halt, stop?
I'm opening these in Oracle's SQL Developer, and the 'Run Command' and 'Run Script' buttons are right next to each other...
You can use the exit command at the top of your script.
If someone accidentally runs it as a script, it will immediately disconnect and will not run the rest of the statements.
Example:
exit
update t set a = 'abc';
drop table t;
...

Opening a batch file using SQL Server procedure

Opening a batch file using SQL Server procedure....
For this, I took the example of opening a notepad. And able to open it with the following code :
start "c:\windows\system32" notepad.exe
--- saved as : note.bat
I tried to open it with following procedure :
ALTER procedure [dbo].[executebat]
as
begin
EXEC master.dbo.xp_CMDShell 'D:\ducont\note.bat'
end
also I enabled the xp_cmdshell option with following code ::
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
But when I try to execute the procedure, it showing continuously
" Query Executing..."
and no output !!
Guide me if I went wrong anywhere .
Simple answer. When you run xp_cmdshell it is creating a shell to do any work you ask it to. Your bat file is running inside that shell, and will open notepad, again inside the shell. You just won't be able to see it. Since it's expecting input (and can't get any) you are stuck with the " Query Executing..."
There really isn't a good way to do what you are asking for other than possibly using CLR. Unfortunately I don't know enough about it to say for certain one way or another. There may be an easier way in SQL 2012 or 2014 but I haven't seen it yet.

SQL Server ':setvar' Error

I am trying to create some script variables in T-SQL as follows:
/*
Deployment script for MesProduction_Preloaded_KLM_MesSap
*/
GO
SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON;
SET NUMERIC_ROUNDABORT OFF;
GO
:setvar DatabaseName "MesProduction_Preloaded_KLM_MesSap"
However, when I run this, I get an error stating 'Incorrect syntax near ':'. What am I doing wrong?
The :setvar only works in SQL command mode, so you are possibly within normal SQL execution in the management studio and have not swapped to command mode.
This can be done through the user interface in SQL Server Management Studio by going to the "Query" menu, and selecting "SQLCMD mode."
Just enable sqlcmd mode in SQL Server Management Studio as described in following image.
FOR SQL2012:
go to :
tools/options/Query Execution and check the by default, open new queries in SQLCMD mode.
Hit the New Query button and make sure the variable definitions are highlighted, your script should run correctly now.
Previous versions:
http://blog.sqlauthority.com/2013/06/28/sql-server-how-to-set-variable-and-use-variable-in-sqlcmd-mode/
try replacing :setvar DatabaseName "MesProduction_Preloaded_KLM_MesSap"
with:
USE [MesProduction_Preloaded_KLM_MesSap]
GO

SQL Server Stored Procedure Fails due to use of XML/ ANSI_NULLS, QUOTED_IDENTIFIER options

I have a stored procedure which takes an XML parameter and inserts the data into multiple tables. If I run the stored procedure into a database using a SSMS query window, everything works fine. However, we have a custom installation program that is used to deploy stored procedures to databases, and when this is used, execution of the sp fails with this error:
INSERT failed because the following SET options have incorrect settings:
'ANSI_NULLS, QUOTED_IDENTIFIER'. Verify that SET options are correct for use with
indexed views and/or indexes on computed columns and/or query notifications
and/or xml data type methods.
The custom installation program does not use the correct settings when scripting in the stored procedures.
Setting these ( SET ARITHABORT ON; SET QUOTED_IDENTIFIER ON; SET ANSI_NULLS ON;) within the sp has no effect:
I have also tried setting these options for the open connection just before calling the sp in the code. This again does not have the desired effect.
It appears that the settings on the connection to the database while the sp is being run in to the database are what matters, not the settings when the sp is used.
I have experimented by playing with these settings in SSMS options, and this does appear to be the case. I would just like someone to confirm that this is definitely the case (if there is a way around I would love to hear it, but I'm not hopeful)
Unfortunately altering the installer program is not an option for me at the present time, so I'm looking at having to roll back a couple of weeks work; so if I do have to do this I want to be really sure (and have some evidence to back me up) that this is the only option
The settings applied with those at CREATE or ALTER time and are ignored at runtime.
SSMS has correct settings by default (so does sqlcmd, osql etc).
From BOL, CREATE PROC, "Using SET Options"
The Database Engine saves the settings
of both SET QUOTED_IDENTIFIER and SET
ANSI_NULLS when a Transact-SQL stored
procedure is created or modified.
These original settings are used when
the stored procedure is executed.
Therefore, any client session settings
for SET QUOTED_IDENTIFIER and SET
ANSI_NULLS are ignored when the stored
procedure is running. Other SET
options, such as SET ARITHABORT, SET
ANSI_WARNINGS, or SET ANSI_PADDINGS
are not saved when a stored procedure
is created or modified.