8

I am using a Temporary table in Stored Procedure in SQL Server. I am trying to use that SP in OLE DB Source Editor.

I can see the data output returned in the Query Builder that comes with Build Query button. But when I Click the Columns tab, I am getting the below error.

- TITLE: Microsoft Visual Studio

Error at Data Flow Task [OLE DB Source [1]]: SSIS Error Code DTS_E_OLEDBERROR. An OLE DB error has occurred. Error code: 0x80004005. An OLE DB record is available. Source: "Microsoft SQL Server Native Client 10.0" Hresult: 0x80004005 Description: "Invalid object name '##Payment'.".

Error at Data Flow Task [OLE DB Source [1]]: Unable to retrieve column information from the data source. Make sure your target table in the database is available.

Does that mean I cant use temp tables in SP, if I want it to be consumed by SSIS

aaroncatlin
  • 3,203
  • 1
  • 16
  • 27
Jason M
  • 1,040
  • 4
  • 12
  • 21
  • @sriram thinks you can also check the below link for more details, its a trick i dont know why microsoft guys make it more simple... - http://www.sqllike.com/using-temporary-tables-with-ssis-40.html – hakre Aug 28 '12 at 10:06

7 Answers7

18

UPDATE November 2020.
This post has been superceeded by How to EXEC a stored procedure from SSIS to get its output to text file that describes how to run a stored procedure from SSIS

exec mySproc WITH RESULT SETS ((i int))

look at the solution provided by Troy Witthoeft

Old answer
There is another solution mentioned at https://web.archive.org/web/20120915093807/http://sqlserverpedia.com/blog/sql-server-bloggers/ssis-stored-procedure-metadata. Look at option 3. (November 2020; updated link)

Quote: Add some meta-data and the "set nocount on" to the stored procedure with a "short circuited if clause" (if 1=0), and a bogus select statement at the top. I've tested with trying to leave the "set nocount on" out and it did not work.

CREATE PROCEDURE [dbo] . [GenMetadata] AS 
SET NOCOUNT ON 
IF 1 = 0 
    BEGIN
         -- Publish metadata 
        SELECT   CAST (NULL AS INT ) AS id , 
                CAST (NULL AS NCHAR ( 10 )) AS [Name] , 
                CAST (NULL AS NCHAR ( 10 )) AS SirName 
    END 

 -- Do real work starting here 
CREATE TABLE #test 
    ( 
      [id] [int] NULL, 
      [Name] [nchar] ( 10 ) NULL, 
      [SirName] [nchar] ( 10 ) NULL 
    ) 
Henrik Staun Poulsen
  • 13,154
  • 4
  • 23
  • 26
  • This is the standard solution and by far the easiest to implement. There's no need to create other database objects or avoid using stored procedures. – Eric Ness Dec 02 '11 at 17:38
  • From what I have seen, this is the best solution. `SET FMTONLY OFF` kills performance, table variables are not always appropriate, no messing with `DelayValidation`, and it works with SQL 2000 (as I unfortunately had to find out). I found that you can put the dummy query outside the stored proc and into the Source component, so keeping your proc untouched and cleaner. e.g. `IF 1 = 0 BEGIN SELECT CAST(null as int) AS Foo END; EXEC udpMyProc` I didn't require `SET NOCOUNT` at the top of the statement (although my proc does set it) – Rhumborl Feb 17 '15 at 14:52
8

I used

SET FMTONLY OFF at the start of procedure, which will tell not to process rows to the client when it is not being executed as there is no temp table while parsing the SP, hence no column available while parsing.

It got me working finally :)

Jason M
  • 1,040
  • 4
  • 12
  • 21
  • 1
    I tried this, but when I go to run the package in SSIS it freezes up and takes forever before it starts processing. If I remove SET FMTONLY OFF and switch back to a table variable instead of a temp table the package starts fine. – Matt Palmerlee May 23 '12 at 00:39
  • You want to avoid using this at all costs, unless performance is never an issue. This can cause your stored procedure to run up to 5 times instead of once. – Jens Jan 04 '19 at 16:01
6

If the error was raised while you are in BIDS, then ajdams solution will not work as it only applies to errors raised while running the package from the SQL Server Agent.

The primary problem is that SSIS is struggling to resolve the meta data. From its stand-point, the ## tables don't exist since it can't return the meta data for the object during the pre-execution phase. So you have to find a way to satisfy its requirement that the table already exists. There are a few solutions:

  1. Don't use temporary tables. Instead, create a working database and put all your objects in it. Obviously, this probably won't work if you are trying to get the data on a server where you aren't a dbo like a production server, so you can't rely on this solution.

  2. Use CTE's instead of temporary tables. This works if your source server is 2005/2008. This won't help if the source server is 2000.

  3. Create the ## table in a separate Execute SQL command. Set the connection's RetainSameConnection property to True. Set DelayValidation to true for the data flow. When you setup the data flow, fake it out by temporarily adding a SELECT TOP 0 field = CAST(NULL AS INT) to the top of the stored procedure that has identical meta data to your final output. Remember to remove this from the stored procedure before you run the package. This is also a handy trick for sharing temporary table data between data flows. If you want the rest of the package to use separate connections so that they can run in parallel, then you have to create an additional non-shared connection. This evades the problem since the temporary table already exists at the time the data flow tasks runs.

Option 3 achieves your goal, but it is complicated and has the limitation that you have to separate the create ## command into another stored procedure call. If you have the ability to create stored procedures on the source server, then you probably also have the ability to create other objects like staging tables and this is usually a better solution. It also side-steps possible TempDB contention issues which is a desirable benefit as well.

Good luck and let me know if you need further guidance on how to implement step 3.

Registered User
  • 8,357
  • 8
  • 49
  • 65
3

Nope, it's a permissions issue. This should help you:

http://support.microsoft.com/kb/933835

ajdams
  • 2,276
  • 14
  • 20
1

For all the hassle involved, I think it is probably just not worth it. Create a real table in the db and truncate it before / after your load. If it's for a datawarehouse it isn't going to matter if you have an extra table or two. This gives you the design-time SSIS tools and means you don't have to worry about the intracacies of temp tables.

If you want to keep things separate, then just create your SSIS temp tables in a separate schema. You can use permissions to make this schmema invisible to all other users.

CREATE SCHEMA [ssis_temp]

CREATE TABLE [ssis_temp].[tempTableName]
AndyM
  • 3,574
  • 6
  • 39
  • 45
1

These steps helped me:

  1. Write the final result set into a table.
  2. Script that table as CREATE into a new New Query Editor Window.
  3. Remove everything except the open and close brackets that define the columns.
  4. Wrap that into another pair of brackets.
  5. Recompose the calling of your SP from

    exec p_MySPWithTempTables ?, ?

into

exec p_MySPWithTempTables ?, ? with result sets
(
    (
        ColumnA int,
        ColumnB varchar(10),
        ColumnC datetime
    )
)
Irawan Soetomo
  • 1,315
  • 14
  • 35
0

You can use table variables instead of temporary tables . it will work

paranjai
  • 531
  • 2
  • 5
  • 26