Tuesday, July 11, 2006

When writing complex sproc’s in T-SQL you can sometimes run into the problem that IDEs and other tools, while trying to parse the query, are unable to realise that the query actually works.  This is because they try and interpret the query to get the metadata (the format of the result, rather than the result itself), rather than execute it – not such a bad thing since you don’t want an IDE to execute a sproc willy-nilly, which could result in all sorts of side effects.

 

The main place where developers will encounter this is when trying to configure a TableAdapter (or something) that uses temp tables.

 

Consider the following sproc:

 

CREATE PROCEDURE [dbo].[DoSomething]

AS

CREATE TABLE #MyTable (Id int, Name nvarchar(50))

INSERT INTO #MyTable

VALUES(1,'Name1')

SELECT * FROM #MyTable

 

Executing this procedure via SQL renders the expected result as follows:

 

(1 row(s) affected)

Id          Name

----------- --------------------------------------------------

1           Name1

 

(1 row(s) affected)

 

However if you try and create a TableAdapter in Visual Studio using the same sproc, you get an error that looks something like this:

 

Step1.png

 

The short solution is not to use temp tables, but rather table variables – which for lots of other reasons is arguably better.  The altered sproc would then look like this:

 

ALTER PROCEDURE [dbo].[DoSomething]

AS

DECLARE @MyTable table (Id int, Name nvarchar(50))

INSERT INTO @MyTable

VALUES(1,'Name1')

 

SELECT * FROM @MyTable

 

That is fine, but occasionally you may need to use temp tables and developers land up creating ‘permanent’ temp tables or some other approach.  The question remains, how can we force Visual Studio to ignore the metadata and actually execute the sproc?  In some cases temp tables may be unavoidable – particularly if you are using someone else’s sproc.  The quick solution is to use the SET FMTONLY statement which when turned off would seem to return data as well as metadata to the client.  The SQL Books say the SET FMTONLY Returns only metadata to the client.’  I am making the assumption therefore that setting it to ‘OFF’ returns something else as well – I suspect it is the data.

 

So, to use a sproc that uses temp tables in Visual Studio, the sproc could be changed to:

 

ALTER PROCEDURE [dbo].[DoSomething]

AS

SET FMTONLY OFF

CREATE TABLE #MyTable (Id int, Name nvarchar(50))

INSERT INTO #MyTable

VALUES(1,'Name1')

SELECT * FROM #MyTable

 

… making Visual studio happy.

 

Interestingly, SSIS (SQL Server Integration Services) has an additional quirk.  Firstly, if you use a temp table without turning FMTONLY to OFF, and write a source query of ‘EXEC DoSomething’ you receive an error message ‘This SQL statement is not a query’ – SSIS doesn’t even parse your carefully constructed SQL.  You know that

  1. It works in the query analyser
  2. It is a query
  3. You are more intelligent than your PC, so if you know it is a query then it must be a query.

The best way to convince SSIS that the query is actually a query is to insert the SET FMTONLY OFF line into the sproc (without changing the source query that SSIS uses – see it was a query!).  You may think that the solution is the same as with Visual Studio (use table variables), but SSIS was written by some other development team and has a different attitude and personality.

 

If you execute a sproc with table variables or temp tables with FMTONLY OFF you get something like the following:

 

Step2.png 

If you look carefully, the ‘Executing’ successful (is a valid query) but the ‘Pre-Execute’ fails.  I tried to turn off the pre-execute as an option in the designer with no success.  The quick answer is to add SET NOCOUNT ON to the sproc, which for some reason lets the pre-execute run successfully.  I am not sure why, the SQL Books say that NOCOUNT Stops the message that shows the number of rows affected by a Transact-SQL statement from being returned as part of the results, which doesn’t seem relevant to pre-execute – but it does work.  The query would then be changed to:

 

ALTER PROCEDURE [dbo].[DoSomething]

AS

SET FMTONLY OFF

SET NOCOUNT ON

CREATE TABLE #MyTable (Id int, Name nvarchar(50))

INSERT INTO #MyTable

VALUES(1,'Name1')

SELECT * FROM #MyTable

 

Or, if using table variables:

 

CREATE PROCEDURE [dbo].[DoSomething1]

AS

SET NOCOUNT ON

DECLARE @MyTable table (Id int, Name nvarchar(50))

INSERT INTO @MyTable

VALUES(1,'Name1')

 

SELECT * FROM @MyTable

 

In summary:

  1. Rather use table variables than temp tables
  2. When using temp tables use SET FMTONLY OFF
  3. When using SSIS, use SET NOCOUNT ON
  4. If SSIS says your query is not a query it may be trying to fool you.

Simon Munro

kick it on DotNetKicks.com
7/11/2006 3:24:34 PM (South Africa Standard Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  | 
Related Posts:
My favourite SQL 2005 new feature
Do I put Business Logic in the database?

Tracked by:
"Handling Metadata from SQL Stored procedures in Visual Studio and SSIS" (DotNet... [Trackback]
"phentermine diet pill" (phentermine diet pill) [Trackback]
"Funny Quotes" (Funny Quotes) [Trackback]
"pc memory upgrade" (pc memory upgrade) [Trackback]
"popcorn recipe ebook" (popcorn recipe ebook) [Trackback]
"generic cialis next day" (generic cialis next day) [Trackback]
"ital" (ital) [Trackback]
"foto scolaretta sex sex" (foto scolaretta sex sex) [Trackback]
"child custody" (child custody) [Trackback]
"crochet pillow edgings" (crochet pillow edgings) [Trackback]
"prom dresses" (prom dresses) [Trackback]
"invisibile ragazze inculate" (invisibile ragazze inculate) [Trackback]
"piu caldo fuoriclasse papa" (piu caldo fuoriclasse papa) [Trackback]
"museo santa giulia brescia" (museo santa giulia brescia) [Trackback]
"rubber stamping sites" (rubber stamping sites) [Trackback]
"dirty disney toons" (dirty disney toons) [Trackback]
"nokia 1110" (nokia 1110) [Trackback]
"Antivirus Software Reviews" (Antivirus Software Reviews) [Trackback]
"construction project checklist" (construction project checklist) [Trackback]
"chicago gay dating" (chicago gay dating) [Trackback]
"car seat covers dog" (car seat covers dog) [Trackback]
"cinema roma" (cinema roma) [Trackback]
"what is my computer hz" (what is my computer hz) [Trackback]
"babel" (babel) [Trackback]
"owner builder homes" (owner builder homes) [Trackback]
"SEIKO KINETIC SKH640" (SEIKO KINETIC SKH640) [Trackback]
"babysitter wanted fairbanks alaska" (babysitter wanted fairbanks alaska) [Trackback]
"foto spogliatoio" (foto spogliatoio) [Trackback]
"lilith" (lilith) [Trackback]
"si te vas mp3" (si te vas mp3) [Trackback]
"girls ugly" (girls ugly) [Trackback]