Welcome to MSDN Blogs Sign in | Join | Help

The reference projects needed to resolve objects that reside inside an MSDB database have been posted on the MSDN Code Gallery site.

You can find them on: http://code.msdn.microsoft.com/dbpromsdbsamples

We did not post .dbmeta files but stub projects, because .dbmeta files require the collation to match with your environment. This would result in a multitude of files do download. So instead we provided projects, you do need to make sure you set the project collation to match with your own environment. After you have done this you can create your own .dbmeta file if you do not want to reference a project.

NOTE: Since the projects are a stub projects, in other words the content of objects like procedure have been removed, you cannot and should not use these project to deploy to your msdb database!

-GertD

Visual Studio 2005 Team System Database Professional post Service Release 1 (SR1) roll-up package 1, is now available.

For a list of issues that are fixed, please see knowledge base article KB941278.

You can download the roll-up from the Microsoft Connect site at:
http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=11229

-GertD

We have had a lot of requests from users asking us to make T-SQL Static Code Analysis available at build time and from the command line. The latest Visual Studio Team System 2008 Database Edition Power Tool release, adds this ability to the product through a new MSBuild task. In this blog post I will go through the step that you need to follow to enable and use T-SQL Static Code Analysis from the command line.

Step 0: Install the Power Tools

You first need to install the latest Power Tools for Visual Studio Team System 2008 Database Edition.

Step 1: Create a new database project or open an existing one

We need a database project, either use an existing one, or simple create a test project, from example using the pubs database. That is what I will use for this example.

Step 2: Unload the project

We will need to add a entry to the project file to import the MSBuild .targets file for Power Tools. In order to do this you have to unload the project so that you can edit project file using the XML editor. Right click on the project node inside the Solution Explorer and choose "Unload Project".

image 

Step 3: Import the Microsoft.VisualStudio.TeamSystem.Data.PowerTools.Tasks.targets file

The next step is to modify the project file to add an import statement to include the Microsoft.VisualStudio.TeamSystem.Data.PowerTools.Tasks.targets file which contains the MSBuild task for T-SQL Static Code Analysis. Right click on the unloaded project in Solution Explorer and choose "Edit <project name.dbproj>".

image

This will open the .dbproj file inside the Visual Studio XML editor. Now we need to add an import statement to load the .target file. If you search for "<Import" inside the project file you will find the regular import which loads the normal MSBuild tasks for the database project like the SqlBuildTask and the SqlDeployTask.

   1: <!--Import the settings-->
   2: <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\TeamData\Microsoft.VisualStudio.TeamSystem.Data.Tasks.targets" />

We need to add a reference to the Power Tools targets file.

   1: <!--Import the settings-->
   2: <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\TeamData\Microsoft.VisualStudio.TeamSystem.Data.Tasks.targets" />
   3: <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\TeamData\Microsoft.VisualStudio.TeamSystem.Data.PowerTools.Tasks.targets" />

 

Step 4: Reload the project

After you made the project change, including the new targets file, it is time to reload the project. Right click on the unloaded project node inside Solution Explorer and choose "Reload Project". This will reload the project.

image

NOTE: Make sure you have no errors when loading the project, because this will be an indication that your edits were not correct.

Step 5: Start a "Visual Studio 2008 Command Prompt"

The next step is to run T-SQL Static Code Analysis from the command line, in order to do so we need a command prompt that has the PATH set correctly so we can call MSBuild.exe. Visual Studio creates a shortcut in the menu structure that will launch a command prompt with the correct settings.

When you started the command prompt navigate to the directory where you project file is located that you changed in the previous step.

Step 6: Run T-SQL Static Code Analysis from the command-line

From the command prompt run: msbuild pubs.dbproj /t:SqlAnalysis

image

NOTE: The results file is created in the output directory, which by default is the SQL directory

Step 7: Look at the results

When executing the project using the SqlAnalysis target, an XML file is created that contains the results, named StaticCodeAnalysis.Results.xml. This file contains the information that is normally displayed in the Visual Studio "Error List".

When you open the file in VS it will look like this:

   1: <?xml version="1.0" encoding="utf-16" standalone="no"?>
   2: <Problems>
   3:   <Problem>
   4:     <Rule>Microsoft.Design#SR0010</Rule>
   5:     <ProblemDescription>You should avoid using the following join syntaxes, which have been deprecated: Table1.Id = Table2.Id, Table1.Id *= Table2.Id, Table1.Id =* Table2.Id. You should use the newer syntax, which uses the JOIN keyword.</ProblemDescription>
   6:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.reptq2.proc.sql</SourceFile>
   7:     <Line>4</Line>
   8:     <Column>14</Column>
   9:     <Severity>Warning</Severity>
  10:   </Problem>
  11:   <Problem>
  12:     <Rule>Microsoft.Design#SR0010</Rule>
  13:     <ProblemDescription>You should avoid using the following join syntaxes, which have been deprecated: Table1.Id = Table2.Id, Table1.Id *= Table2.Id, Table1.Id =* Table2.Id. You should use the newer syntax, which uses the JOIN keyword.</ProblemDescription>
  14:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.reptq2.proc.sql</SourceFile>
  15:     <Line>4</Line>
  16:     <Column>23</Column>
  17:     <Severity>Warning</Severity>
  18:   </Problem>
  19:   <Problem>
  20:     <Rule>Microsoft.Design#SR0010</Rule>
  21:     <ProblemDescription>You should avoid using the following join syntaxes, which have been deprecated: Table1.Id = Table2.Id, Table1.Id *= Table2.Id, Table1.Id =* Table2.Id. You should use the newer syntax, which uses the JOIN keyword.</ProblemDescription>
  22:     <SourceFile>c:\work\pubs\Schema Objects\Views\dbo.titleview.view.sql</SourceFile>
  23:     <Line>4</Line>
  24:     <Column>15</Column>
  25:     <Severity>Warning</Severity>
  26:   </Problem>
  27:   <Problem>
  28:     <Rule>Microsoft.Design#SR0010</Rule>
  29:     <ProblemDescription>You should avoid using the following join syntaxes, which have been deprecated: Table1.Id = Table2.Id, Table1.Id *= Table2.Id, Table1.Id =* Table2.Id. You should use the newer syntax, which uses the JOIN keyword.</ProblemDescription>
  30:     <SourceFile>c:\work\pubs\Schema Objects\Views\dbo.titleview.view.sql</SourceFile>
  31:     <Line>4</Line>
  32:     <Column>23</Column>
  33:     <Severity>Warning</Severity>
  34:   </Problem>
  35:   <Problem>
  36:     <Rule>Microsoft.Performance#SR0005</Rule>
  37:     <ProblemDescription>You might cause a table scan when you use an expression that starts with "%" in the LIKE predicate. </ProblemDescription>
  38:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.reptq3.proc.sql</SourceFile>
  39:     <Line>6</Line>
  40:     <Column>73</Column>
  41:     <Severity>Warning</Severity>
  42:   </Problem>
  43:   <Problem>
  44:     <Rule>Microsoft.Performance#SR0007</Rule>
  45:     <ProblemDescription>You have specified a nullable column that is not wrapped with the ISNULL function. This practice can cause the final result to be evaluted as NULL for the predicate.</ProblemDescription>
  46:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.byroyalty.proc.sql</SourceFile>
  47:     <Line>4</Line>
  48:     <Column>7</Column>
  49:     <Severity>Warning</Severity>
  50:   </Problem>
  51:   <Problem>
  52:     <Rule>Microsoft.Performance#SR0007</Rule>
  53:     <ProblemDescription>You have specified a nullable column that is not wrapped with the ISNULL function. This practice can cause the final result to be evaluted as NULL for the predicate.</ProblemDescription>
  54:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.reptq3.proc.sql</SourceFile>
  55:     <Line>6</Line>
  56:     <Column>7</Column>
  57:     <Severity>Warning</Severity>
  58:   </Problem>
  59:   <Problem>
  60:     <Rule>Microsoft.Performance#SR0007</Rule>
  61:     <ProblemDescription>You have specified a nullable column that is not wrapped with the ISNULL function. This practice can cause the final result to be evaluted as NULL for the predicate.</ProblemDescription>
  62:     <SourceFile>c:\work\pubs\Schema Objects\Stored Procedures\dbo.reptq3.proc.sql</SourceFile>
  63:     <Line>6</Line>
  64:     <Column>27</Column>
  65:     <Severity>Warning</Severity>
  66:   </Problem>
  67: </Problems>

 

Step 8: Clean up the results

If you want to clean up the resulting file produced by the static code analysis run, simply run:

msbuild pubs.dbproj /t:ScaClean

This will remove the results file.

 

Conclusion:

Following the steps outlined before enable you to run T-SQL Static Code Analysis from the command line, you can use the same step to integrate this in to your Team Build environment, but you have to make sure that you install the Power Tools on the build server before you can use this.

-GertD
"DataDude" Group Engineering Manager

VSTS-DB, both the 2005 and 2008 version, makes an assumption with regards to database compatibility levels, which can cause problems in certain use cases.

The assumption is that the DesignDB instance used for validation of the schema inside the project is set to a 80 compatibility level when using a SQL Server 2000 project and to 90 when you are using a SQL Server 2005 project. If you have a database schema that was migrated from SQL Server 2000 to 2005 and is relying on the fact that the database compatibility level must be set to 80 to keep your code running, this will cause TSD4001 errors when you import/open that schema in to a SQL Server 2005 project and ultimately prevent you from building and deploying your project, since TSD4xxxx are always errors, which come from the DesignDB instance.

Lets look at two common cases that some of you have reported that cause problems:

Problem description SQL Server 2000
sp_dbcmptlevel = 80
SQL Server 2005
sp_dbcmptlevel = 80
SQL Server 2005
sp_dbcmptlevel = 90
Using hints without  a WITH clause, for example:

CREATE VIEW [dbo].[v_test]
AS
    SELECT    T1.column_1
    FROM       dbo.T1 (NOLOCK, FASTFIRSTROW)
    WHERE    T1.column_1 = 1

Works Works Errors

TSD4001: Invalid column name 'NOLOCK'. (SQL error = 207)   

TSD4001: Invalid column name 'FASTFIRSTROW'. (SQL error = 207)   

TSD4001: Parameters supplied for object 'dbo.T1' which is not a function. If the parameters are intended as a table hint, a WITH keyword is required. (SQL error = 215)
Using old join ANSI syntax, for example:

CREATE PROCEDURE [dbo].[p_test]
AS 
BEGIN
    SELECT    T1.column_1
    FROM       dbo.T1,
                    dbo.T2
    WHERE    T1.column_1 *= T2.column_1
    RETURN 0;
END

Works Works Error TSD4027:
The query uses non-ANSI outer join operators ("*=" or "=*"). To run this query without modification, please set the compatibility level for current database to 80 or lower, using stored procedure sp_dbcmptlevel. It is strongly recommended to rewrite the query using ANSI outer join operators (LEFT OUTER JOIN, RIGHT OUTER JOIN). In the future versions of SQL Server, non-ANSI join operators will not be supported even in backward-compatibility modes. (SQL error = 4147)

The above list examples are not exhaustive and do not represent the complete list of difference in database compatibility levels. Please see the SQL Server Books Online topic on sp_dbcmptlevel, it contains a list of differences. (Look for the label "Differences Between Lower Compatibility Levels and Level 90".)

      

Resolution:

So what do you need to do when you are running in to this problem? First you need to determine which version of Visual Studio Team System Database Edition you have and if you need to install the latest QFE or not.

Visual Studio 2005

If you are using the Visual Studio 2005 based version, you need to make sure that you install the latest QFE roll-up, which is documented in the following KB article:

KB 941278:  Visual Studio 2005 Team System Database Professional Post Service Release 1 (SR1) Rollup Package #1

Visual Studio 2008

If you are using a Visual Studio 2008 RTM based version, you are OK and do not need to install an update; however if you are using a Visual Studio 2008 pre-release version (CTP, beta or RC) you do need to update to the RTM version, since the fix went in at the last moment.

Workaround

Now that you have identified which version you need, how do you work around the problem? We have added a way to set the database compatibility level inside the project, however there is no UI support to set this option. You need to follow the following steps.

Step 1: Unload the project

We will need to add a property to the project file, in order to do this you have to unload the project so that you can edit project file using the XML editor. Right click on the project node inside the Solution Explorer and choose "Unload Project".

image_thumb1

Step 2: Add the CompatLevel property to the project file

The next step is to modify the project file to add the CompatLevel property.

Right click on the unloaded project in Solution Explorer and choose "Edit <project name.dbproj>".

image_thumb2

This will open the project file inside the XML editor. You need to make sure you are adding the property to the right configuration block. By default there is only one configuration named 'Default'. Which is declared at the top of the project file, below you see the first 18 lines.

 
   1: <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
   2:   <PropertyGroup>
   3:     <Configuration Condition=" '$(Configuration)' == '' ">Default</Configuration>
   4:     <Name>"DatabaseProject"</Name>
   5:     <SchemaVersion>2.0</SchemaVersion>
   6:     <ProjectGuid>{86c9eefc-ee75-4a7f-a518-b398f5922055}</ProjectGuid>
   7:     <ShowWizard>False</ShowWizard>
   8:     <OutputType>Database</OutputType>
   9:     <DBProduct>SQL Server 2005</DBProduct>
  10:     <RootPath>
  11:     </RootPath>
  12:     <ArithAbort>True</ArithAbort>
  13:     <NumericRoundAbort>False</NumericRoundAbort>
  14:     <AnsiNulls>True</AnsiNulls>
  15:     <ConcatNullYieldsNull>True</ConcatNullYieldsNull>
  16:     <AnsiPadding>True</AnsiPadding>
  17:     <AnsiWarnings>True</AnsiWarnings>
  18:     <QuotedIdentifier>True</QuotedIdentifier>
  19:     <...>
  20:   </PropertyGroup>
 

What you need to do is at the CompatLevel property by adding the following XML element: <CompatLevel>80</CompatLevel>. I suggest to place it under the DBProduct property, since this information is related.

 
   1: <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
   2:   <PropertyGroup>
   3:     <Configuration Condition=" '$(Configuration)' == '' ">Default</Configuration>
   4:     <Name>"DatabaseProject"</Name>
   5:     <SchemaVersion>2.0</SchemaVersion>
   6:     <ProjectGuid>{86c9eefc-ee75-4a7f-a518-b398f5922055}</ProjectGuid>
   7:     <ShowWizard>False</ShowWizard>
   8:     <OutputType>Database</OutputType>
   9:     <DBProduct>SQL Server 2005</DBProduct>
  10:     <CompatLevel>80</CompatLevel>
  11:     <RootPath>
  12:     </RootPath>
  13:     <ArithAbort>True</ArithAbort>
  14:     <NumericRoundAbort>False</NumericRoundAbort>
  15:     <AnsiNulls>True</AnsiNulls>
  16:     <ConcatNullYieldsNull>True</ConcatNullYieldsNull>
  17:     <AnsiPadding>True</AnsiPadding>
  18:     <AnsiWarnings>True</AnsiWarnings>
  19:     <QuotedIdentifier>True</QuotedIdentifier>
  20:     <...>
  21:   </PropertyGroup>
 
Line 10 shows the required change.

Step 3: Reload the project

After you made the project change, adding the property to the project file, it is time to reload the project. Right click on the unloaded project node inside Solution Explorer and choose "Reload Project". This will reload the project.

image_thumb3

NOTE: Make sure you have no errors when loading the project, because this will be an indication that your edits were not correct.

After you reload the project, the errors related to the database compatibility mode differences should have disappeared.

 

Restrictions

  1. You can add the CompatLevel property to both SQL Server 2000 and SQL Server 2005 projects, however the values allowed for the database compatibility mode are restricted to: 80 and 90, other values are not supported.

Side effects

What are the side effects of adding and setting the value of the CompatLevel property?

  • The DesignDB instance will be set to the database compatibility level set in the project. When the property is not set explicitly the values are implicitly derived from the DBProject property value.
    • <DBProduct>SQL Server 2000</DBProduct> implies database compatibility level 80
    • <DBProduct>SQL Server 2005</DBProduct> implies database compatibility level 90
  • The database compatibility level will get propagated to the build script. For example when using a SQL Server 2005 project with the CompatLevel set to 80, a new build script you will contain:
       1:  CREATE DATABASE [$(DatabaseName)] ON ( NAME = N'PrimaryFileName', FILENAME = N'$(PrimaryFilePhysicalName)') LOG ON ( NAME = N'PrimaryLogFileName', FILENAME = N'$(PrimaryLogFilePhysicalName)') COLLATE SQL_Latin1_General_CP1_CS_AS 
       2:  GO
       3:   
       4:  :on error resume
       5:       
       6:  EXEC sp_dbcmptlevel N'$(DatabaseName)', 80
       7:  GO
  • Where an incremental build will contain:
       1:  DECLARE @dbcompatlvl as int;
       2:  SELECT  @dbcompatlvl = cmptlevel
       3:  FROM    [master].[dbo].[sysdatabases]
       4:  WHERE   [name] = N'$(DatabaseName)';
       5:  IF (ISNULL(@dbcompatlvl, 0) != 80)
       6:  BEGIN
       7:      RAISERROR(N'The database compatibility level of the build script %i does not match the compatibility level of the target database %i. Verify whether your database project settings are correct and whether your build script is up to date.', 16, 127, 80, @dbcompatlvl) WITH NOWAIT;
       8:      RETURN;
       9:  END
      10:  GO

 

Summary

   

If you are relying on the SQL Server database compatibility level, to keep your code running, you need to set the CompatLevel property inside your project. If you want you can update your project templates to include the CompatLevel property so you do not forget to set it.

-GertD

An other new addition to the Visual Studio Team System 2008 Database Edition - Power Tools release is the File Bound Generator. This data generator grovels through files inside a directory or optionally through its subdirectories, based on some search filter you provide and loads the content of the file in to a column value. The file content is either represented as text or as binary data. The generator is shared-instancing enabled, which means that the same file can be bound to multiple columns inside the same row while having to load it only once.

Let walk through an example which leverages the file bound generator to load data in to a table.

 

Step 0: Install the Power Tools

You first need to install the latest Power Tools for Visual Studio Team System 2008 Database Edition.

 

Step 1: Create a new project and add a table

The first step is to create a new database project, in this example I am using a SQL Server 2005 project named "testdb", since I want to leverage the NVARCHAR(MAX) and VARBINARY(MAX) data types, otherwise use NTEXT and IMAGE instead.

After having created the project add a new table which we will name [dbo].[files] with the following shape:

   1: CREATE TABLE [dbo].[files]
   2: (
   3:     [file_id]    int identity not null, 
   4:     [file_name]  nvarchar(256) not null,
   5:     [file_text]  nvarchar(max) null,
   6:     [file_bin]   varbinary(max) null,
   7: );

After you created the project and the table, make sure that you build and deploy project.

 

Step 2: Create a new Data Generation Plan

Next add a new Data Generation Plan, by right clicking on the Data Generation Plan folder in Solution Explorer and choose: "Add... New Item... Data Generation Plan"

image image image

This will add a new Data Generation Plan to your project and automatically bind the columns of the tables inside your project to the default data generator.

 

Step 3: Create some test input

In order to create some test files we can load and also demonstrate how shared-instancing works I am using the following batch file:

   1: @rem CreateFiles.cmd
   2: @echo off
   3:  
   4: for /L %%I in (1, 1, 1000) do call :CREATE %%I
   5: goto END
   6:  
   7: :CREATE
   8: @echo filename%1.txt > filename%1.txt
   9:  
  10: :END

Create a folder, for example C:\TEST, create or copy the CreateFiles.cmd file in to the directory you just created and run the batch file. This will create a 1000 files with sequential names and the content of the file being the file name so we can use it for correlation purposes.

 

Step 4: Configure the File Bound Generator

The default configuration of the plan will look like this:
image

The next step is to assign file bound generator to the file_name, file_text and file_bin columns.
image

After you assigned the generator you need to set the Generator Output, by default the generator binds to the coercion type, so the file_name and file_text will bind to String Result since they are NVARCHAR columns, the file_bin column will by default bind to the Binary Result since its type is of V