Select into #temp table got an error - sql

I have complicated store procedure and get the data into the #temp table that is worked fine. However when I filter the data from this temp table then I got the error, 'Invalid object name '#temp_2'. After the data in #temp_2 table, I also need to open into cursor. Would someone tell me how to solve it.
There is my script:
DECLARE #sql varchar(500)
IF #strLocations=''
SET #sql='SELECT * into #temp_2 from #temp_1'
ELSE
SET #sql='SELECT * into #temp_2 from #temp_1 t where t.Location_id in ( ' + #strLocations + ')'
EXEC (#sql)
select * from #temp_2

EXEC creates a new session to execute the statements. When the session ends, any local temporary tables created in it are destroyed (i.e. dropped). You will have to create the temporary table before your EXEC statement.

Related

inserting data into temp table based on whether it exists in db [duplicate]

This question already has an answer here:
Drop temp table within IF ELSE statement
(1 answer)
Closed 7 months ago.
I am inserting data from a table table1 into a temp table. I am unsure whether it will be in db1 or db2 (this script is reused a lot). I want to check of the existence of it in db1 if its there create the temp table in db1 and if not create it in db2
my script is as follows
drop table if exists ##temp
if object_id('[db1].[dbo].[table1]') is not null
begin
select *
into ##temp
from [db1].[dbo].[table1]
end
else
begin
drop table if exists ##temp
select *
into ##temp
from [db2].[dbo].[table1]
end
however, while both the select into queries work individually I get this error when I run the whole block
There is already an object named '##temp' in the database.
It seems to trigger the else statement even when it is not required
I think they need to be executed in separate batches.
Try it like this:
IF OBJECT_ID('[db1].[dbo].[table1]') IS NOT NULL
BEGIN
EXEC sp_executesql #stmt = N'DROP TABLE IF EXISTS ##temp;';
EXEC sp_executesql #stmt = N'SELECT *
INTO ##temp
FROM [db1].[dbo].[table1]; ';
END;
ELSE
BEGIN
EXEC sp_executesql #stmt = N'DROP TABLE IF EXISTS ##temp;';
EXEC sp_executesql #stmt = N'
SELECT *
INTO ##temp
FROM [db2].[dbo].[table1]; ';
END;
As the instance of global temp table exists for all sessions, most likely scenario is another user creating temp table with same name while you are executing only portion of the above query before other session ends.
FYI: it is not triggering else statement based on your error, if statement is being executed multiple times without checking if ##temp table exists. try executing drop table if exists ##temp inside if statement
IF OBJECT_ID('[db1].[dbo].[table1]') IS NOT NULL
BEGIN
DROP TABLE IF exists ##temp
SELECT *
INTO ##temp
FROM [db1].[dbo].[table1]
END
ELSE
BEGIN
DROP TABLE IF EXISTS ##temp
SELECT *
INTO ##temp
FROM [db2].[dbo].[table1]
END

How to use a variable in "Select [some calculations] insert into #NameOfTheTableInThisVariable"?

I have a procedure in which there are calculations being done and the final result is inserted into a permanent table. I want to remove the permanent table and I cannot use Temp table as well. So i want to use a dynamic table name, which is stored in a variable:
Current scenario:
Insert into xyz_table
Select col1,col2,sum(col3)
from BaseTable
(In reality, there are lot of columns and a lot of calculations)
What I want:
Select col1,col2,sum(col3) into #DynamicTableName
from BaseTable
where the name of the table would be dynamic in nature i.e.,
#DynamicTableName = 'xyz ' + cast(convert(date,getdate()) as nvarchar)+' '+convert(nvarchar(5),getdate(),108)
It will have date and time in its name every time the procedure is run.
I want to use this name in the "Select * into statement"
How can I achieve this?
i tried it with the some short code. But since my procedure has a lot of calculations and UNIONS , I cannot use that code for this. Any help would be appreciated.
declare #tablename nvarchar(30)= 'xyz ' + cast(convert(date,getdate()) as nvarchar)+' '+convert(nvarchar(5),getdate(),108)
declare #SQL_Statement nvarchar(100)
declare #SQL_Statement2 nvarchar(100)
declare #dropstatement nvarchar(100)
SET #SQL_Statement = N'SELECT * Into ' +'['+#tablename +'] '+'FROM '+ 'dimBranch'
print #SQL_Statement
EXECUTE sp_executesql #SQL_Statement
SET #SQL_Statement= N'select * from ' + '['+#tablename + '] '
print #SQL_Statement
EXECUTE sp_executesql #SQL_Statement
set #dropstatement = 'DROP TABLE' + '['+#tablename + '] '
PRINT #dropstatement
exec sp_executesql #dropstatement
Reason why I want this is because I use this procedure in ETL job as well as in SSRS report. And if someone runs the package and the SSRS report at the same time, the incorrect or weird data gets stored in the table. Therefore I need a dynamic name of the table with date and time.
You can't parameterize an identifier in SQL, only a value
--yes
select * from table where column = #value
--no
select * from #tablename where #columnname = #value
The only thin you can do to make these things dynamic is to build an sql string and execute it dynamically, but your code is already doing this with sp_executesql
More telling is your complaint at the bottom of your question, that if the procedure is invoked simultaneously it gives problems. Perhaps you should consider using local table variables for temporary data storage that the report is using rather than pushing data back into the db
DECLARE #temp TABLE(id INT, name varchar100);
INSERT INTO #temp SELECT personid, firstname FROM person;
-- work with temp data
select count(*) from #temp;
--when #temp goes out of scope it is lost,
--no other procedure invoked simultaneously can access this procedure'a #temp
Consider a local temp table, which is automatically session scoped without the need for dynamic SQL. For example:
SELECT *
INTO #YourTempTable
FROM dimBranch;
The local temp table will automatically be dropped when the proc completes so there is no need for an explict drop in the proc code.

Select from temp table fails

I'm inserting data into a temp table and querying the temp table fails
DECLARE #SQLQuery AS NVARCHAR(500)
SET #SQLQuery = 'SELECT Top 100 *
INTO #tempTable
FROM ' + #origDB + '.dbo.' + #origTable + ' o WITH (NOLOCK) '
EXECUTE sp_executesql #SQLQuery
and when I try to query the temp table , like so
select * from #tempTable
I get the following error :
Invalid object name '#tempTable'.
Courtesy of MSDN
The problem that you have is with the scope. The TEMP table is creatd at the scope of the EXEC() method and hence it is not available after the function returns. To fix this, create your temp table before calling EXEC() and use an INSERT INTO instead of SELECT INTO.
As others have said, the scope of a temporary table is limited to the session context in which it is created - a stored procedure runs in its own context.
You could use a global temporary table ##tempTable, but it's generally a bad idea as it would be available to other sessions than the one creating it.

SQL Server 2008: Insert variable into DML statements using Stored Procedure

I have the following procedure:
CREATE PROCEDURE [dbo].[Test1]
AS
BEGIN
INSERT INTO [My_Database].[My_Schema].[My_Table]
(...lists columns...)
SELECT ... lots of columns from joined query...
END
Instead of hardcoding "[My_Database].[My_Schema]", I now want to select it as a variable from a predefined table like this:
CREATE PROCEDURE [dbo].[Test1]
AS
BEGIN
SELECT #myDB = [My_DB] FROM [my_custom_table]
--INSERT INTO [My_Database].[My_Schema].[My_Table]
INSERT INTO #myDB.[My_Table]
(...lists columns...)
SELECT ... lots of columns from joined query...
END
It does not work if I use it like above. I need to use:
EXEC sp_executesql (entire_sql_statement_in_quotes)
My problem is that I have a lot of these procedures to change to using a variable instead of being hardcoded. It will take forever to convert each statement to a long string.
Is there some other way to do it? What am I missing?
Regards
One idea, you could drop and recreate a synonym using dynamic SQL at the beginning of each procedure, then you can leave each Insert statement as Insert Into MySynonym
DROP SYNONYM MySynonym -- Must create it first before running this bit!
DECLARE #sql nvarchar(max)
SET #SQL = 'CREATE SYNONYM MySynonym
FOR ' + #myDB + '.test1'
EXEC sp_Executesql #sql
INSERT INTO MySynonym
SELECT ...
This would give you a peice of code you could copy paste into each SP. If the table you are inserting into is different for each SP, you could declare that too and build it into your CREATE SYNONYM statement
SET #SQL = 'CREATE SYNONYM MySynonym
FOR ' + #myDB + '.' + #MyTable
to Truncate each table first you would need to use DynamicSQL also, as you cannot delete on a synonym
SET #SQL = 'Truncate Table ' + #MyTable
EXEC sp_Executesql #sql

How to BULK INSERT a file into a *temporary* table where the filename is a variable?

I have some code like this that I use to do a BULK INSERT of a data file into a table, where the data file and table name are variables:
DECLARE #sql AS NVARCHAR(1000)
SET #sql = 'BULK INSERT ' + #tableName + ' FROM ''' + #filename + ''' WITH (CODEPAGE=''ACP'', FIELDTERMINATOR=''|'')'
EXEC (#sql)
The works fine for standard tables, but now I need to do the same sort of thing to load data into a temporary table (for example, #MyTable). But when I try this, I get the error:
Invalid Object Name: #MyTable
I think the problem is due to the fact that the BULK INSERT statement is constructed on the fly and then executed using EXEC, and that #MyTable is not accessible in the context of the EXEC call.
The reason that I need to construct the BULK INSERT statement like this is that I need to insert the filename into the statement, and this seems to be the only way to do that. So, it seems that I can either have a variable filename, or use a temporary table, but not both.
Is there another way of achieving this - perhaps by using OPENROWSET(BULK...)?
UPDATE:
OK, so what I'm hearing is that BULK INSERT & temporary tables are not going to work for me. Thanks for the suggestions, but moving more of my code into the dynamic SQL part is not practical in my case.
Having tried OPENROWSET(BULK...), it seems that that suffers from the same problem, i.e. it cannot deal with a variable filename, and I'd need to construct the SQL statement dynamically as before (and thus not be able to access the temp table).
So, that leaves me with only one option which is to use a non-temp table and achieve process isolation in a different way (by ensuring that only one process can be using the tables at any one time - I can think of several ways to do that).
It's annoying. It would have been much more convenient to do it the way I originally intended. Just one of those things that should be trivial, but ends up eating a whole day of your time...
You could always construct the #temp table in dynamic SQL. For example, right now I guess you have been trying:
CREATE TABLE #tmp(a INT, b INT, c INT);
DECLARE #sql NVARCHAR(1000);
SET #sql = N'BULK INSERT #tmp ...' + #variables;
EXEC master.sys.sp_executesql #sql;
SELECT * FROM #tmp;
This makes it tougher to maintain (readability) but gets by the scoping issue:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'CREATE TABLE #tmp(a INT, b INT, c INT);
BULK INSERT #tmp ...' + #variables + ';
SELECT * FROM #tmp;';
EXEC master.sys.sp_executesql #sql;
EDIT 2011-01-12
In light of how my almost 2-year old answer was suddenly deemed incomplete and unacceptable, by someone whose answer was also incomplete, how about:
CREATE TABLE #outer(a INT, b INT, c INT);
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SET NOCOUNT ON;
CREATE TABLE #inner(a INT, b INT, c INT);
BULK INSERT #inner ...' + #variables + ';
SELECT * FROM #inner;';
INSERT #outer EXEC master.sys.sp_executesql #sql;
It is possible to do everything you want. Aaron's answer was not quite complete.
His approach is correct, up to creating the temporary table in the inner query. Then, you need to insert the results into a table in the outer query.
The following code snippet grabs the first line of a file and inserts it into the table #Lines:
declare #fieldsep char(1) = ',';
declare #recordsep char(1) = char(10);
declare #Lines table (
line varchar(8000)
);
declare #sql varchar(8000) = '
create table #tmp (
line varchar(8000)
);
bulk insert #tmp
from '''+#filename+'''
with (FirstRow = 1, FieldTerminator = '''+#fieldsep+''', RowTerminator = '''+#recordsep+''');
select * from #tmp';
insert into #Lines
exec(#sql);
select * from #lines
Sorry to dig up an old question but in case someone stumbles onto this thread and wants a quicker solution.
Bulk inserting a unknown width file with \n row terminators into a temp table that is created outside of the EXEC statement.
DECLARE #SQL VARCHAR(8000)
IF OBJECT_ID('TempDB..#BulkInsert') IS NOT NULL
BEGIN
DROP TABLE #BulkInsert
END
CREATE TABLE #BulkInsert
(
Line VARCHAR(MAX)
)
SET #SQL = 'BULK INSERT #BulkInser FROM ''##FILEPATH##'' WITH (ROWTERMINATOR = ''\n'')'
EXEC (#SQL)
SELECT * FROM #BulkInsert
Further support that dynamic SQL within an EXEC statement has access to temp tables outside of the EXEC statement. http://sqlfiddle.com/#!3/d41d8/19343
DECLARE #SQL VARCHAR(8000)
IF OBJECT_ID('TempDB..#BulkInsert') IS NOT NULL
BEGIN
DROP TABLE #BulkInsert
END
CREATE TABLE #BulkInsert
(
Line VARCHAR(MAX)
)
INSERT INTO #BulkInsert
(
Line
)
SELECT 1
UNION SELECT 2
UNION SELECT 3
SET #SQL = 'SELECT * FROM #BulkInsert'
EXEC (#SQL)
Further support, written for MSSQL2000 http://technet.microsoft.com/en-us/library/aa175921(v=sql.80).aspx
Example at the bottom of the link
DECLARE #cmd VARCHAR(1000), #ExecError INT
CREATE TABLE #ErrFile (ExecError INT)
SET #cmd = 'EXEC GetTableCount ' +
'''pubs.dbo.authors''' +
'INSERT #ErrFile VALUES(##ERROR)'
EXEC(#cmd)
SET #ExecError = (SELECT * FROM #ErrFile)
SELECT #ExecError AS '##ERROR'
http://msdn.microsoft.com/en-us/library/ms191503.aspx
i would advice to create table with unique name before bulk inserting.