3

I have a large repository of SQL scripts in SQLCMD syntax. Each script has 0 or more $(SomeParam) defined. We have a utility which executes the scripts and passes in the values for the $(params), essentially enable us to configure and automate builds for a wide range of data models.

Sometimes our build process fails because a script has a $(param) specified which is not configured in our utility. i.e. we have no value for this $(param) set

I would like to perform a test-run of these scripts prior to executing them. The test run should ensure that all required $(params) have been supplied to the script. The SQL itself should not be executed - I just want to know if it is compile-able. Is this possible to achieve using sqlcmd?

Alternatives Considered

I've considered one alternative of using a Powershell script to find matches for all $(param) in the file (using RegEx) and cross-checking that against our list of params in the utility. I'd prefer to retain all functionality either on the sqlcmd command-line or in the SQL scripts themselves if possible.

3
  • 1
    Could be a job for SET NOEXEC ON. Commented Oct 20, 2016 at 15:33
  • could you provide an additional defaulted parameter to indicate it's running in test mode. then use this flag to only execute the code contained when it's not in test mode? it's pretty dirty solution I've used before to validate a script without it running. Commented Oct 20, 2016 at 15:34
  • @JeroenMostert - I think this is probably the best approach. If you can expand a little with an answer then I will mark it as the correct answer. Commented Nov 20, 2016 at 14:05

2 Answers 2

4

SET NOEXEC ON makes SQL Server enter a mode where statements are parsed and compiled but not executed, with the exception of the command SET NOEXEC OFF, which reverts things back to their original state. So, if statements end up syntactically invalid because of missing parameters, SET NOEXEC ON will catch it.

There is an important limitation to SET NOEXEC ON. The documentation misleadingly states that "this setting is useful for having SQL Server validate the syntax and object names in Transact-SQL code when executing", but, in fact, under SET NOEXEC ON, SQL Server will not resolve names to most objects at all. The following script will parse without error:

SET NOEXEC ON;
GO
CREATE TABLE Foo(ID INT PRIMARY KEY);
GO
INSERT Fooo(ID) VALUES (5);  -- Oops, typo

That doesn't mean that no names are resolved at all. The following script will still fail:

SET NOEXEC OFF;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SET NOEXEC ON;
GO
SELECT dbo.Foo();  -- No error here, even though Foo can't be invoked this way
SELECT * FROM dbo.Foo(5);  -- Error here: too many arguments specified

Fair enough, you might say, but:

SET NOEXEC ON;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SELECT * FROM dbo.Foo(5);  -- No error, because Foo doesn't exist

So SET NOEXEC ON can serve neither as a way to guarantee a script is completely valid, nor as a way to determine a script is definitely invalid. As long as you're aware of its limitations it can still be useful.

There is another setting that does work consistently as far as object names go: SET PARSEONLY ON. This not only doesn't execute statements, it doesn't even compile them. The example above which gives an error with NOEXEC will give no error with PARSEONLY. As does the following:

CREATE TYPE MyInt FROM INT;
GO
CREATE TABLE A(ID MyInt);  
  -- Error under NOEXEC since MyInt does not exist, no error under PARSEONLY

So if all you want to check is syntactical validity, PARSEONLY is better than NOEXEC.

Sign up to request clarification or add additional context in comments.

Comments

0

You can create a copy of the script, encapsulate the execution of the script in to a Transaction automaticaly and introduce an error at the end of the script. It always print an error. If the error is YOUR introduced error, then the script ran perfect, or print a param error otherwise. Sorry for my english

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.