SQL: Insert Query Result into Temp Table inside While Loop - sql

I am trying to insert select query result into a temporary table inside the while loop. But below query gives me this error:
There is already an object named '#TT' in the database.
DECLARE #V_START INT = 1;
DROP TABLE #TT
WHILE(#V_START < 4)
BEGIN
SELECT * INTO #TT
FROM Table
WHERE Column = #V_START;
SET #V_START = #V_START + 10;
END
SELECT * FROM #TT

every time your loop is executed a temporary table will create, but first-time execution the temp table does not exist command run successfully and you give the error in the second round of loop execution.
You can try it like below :
DECLARE #V_START INT = 1;
DROP TABLE IF EXISTS #TT;
CREATE TABLE #TT
(
--your columns
)
WHILE(#V_START < 40)
BEGIN
INSERT INTO #TT
(
--your columns
)
SELECT --your columns
FROM Table
WHERE Column = #V_START;
SET #V_START = #V_START + 10;
END
SELECT * FROM #TT
but better solution is using select into with condition for inserting data to temp table:
DROP TABLE IF EXISTS #TT
SELECT * INTO #TT
FROM Table
WHERE Column % 10 = 0 AND Id < 10
SELECT * FROM #TT

Related

Insert into #temp_table from stored procedure with dynamic columns

I have a stored procedure which can return a variety of field names in its output. Something like this:
create or alter procedure dbo.my_prc (#return_format as int ) as
create table #all_data (id int ,chr varchar(10))
insert into #all_data
values (1,'a')
,(2,'b')
,(3,'c')
--return id -> id_2 only
if #return_format = 1
select id * 2 as 'id_2' from #all_data
--return chr -> chrq only
if #return_format = 2
select chr + '?' as 'chrq' from #all_data
--return everything
if #return_format = 3
select * from #all_data
Here are possible outputs:
exec my_prc #return_format = 1 --id_2
exec my_prc #return_format = 2 --chrq
exec my_prc #return_format = 3 --everything
How can I dynamically create a #temp_table (or a set of temp tables for 1-3) which will capture my field names and data?
This obviously doesn't work but something like this is what I'm thinking:
/*
exec my_prc #return_format = 1 into #temp_table
--or maybe
select top 0 from (exec my_prc #return_format = 1) into #temp_table --create a #temp_table with the field names
insert into #temp_table exec my_prc #return_format = 1
*/
For more context, I am trying to avoid simply declaring a static #temp_table and inserting into as such. I don't want to get into the weeds, but that is likely not a good option for me.
create table #temp_table (id int ,chr varchar(10))
insert into #temp_table
exec my_prc #return_format = 3
Here is a solution which writes to the database then creates a #temp_table from that newly created table
The stored procedure can look like this
create or alter procedure dbo.my_prc (#return_format as int ) as
create table #all_data (id int ,chr varchar(10))
insert into #all_data
values (1,'a')
,(2,'b')
,(3,'c')
drop table if exists dbo.output_table --drop so that you can reset the field names
--return id -> id_2 only
if #return_format = 1
select id * 2 as 'id_2' into dbo.output_table from #all_data
--return chr -> chrq only
if #return_format = 2
select chr + '?' as 'chrq' into dbo.output_table from #all_data
--return everything
if #return_format = 3
select * into dbo.output_table from #all_data
select * from dbo.output_table --if you still need to see the output in the SP
And then you can create your #temp_table off dbo.output_table
select * into #temp_table from dbo.output_table
Regardless of which value you choose for #return_format, dbo.output_table will have those fields
Have you tried to use Dynamic SQL?
It is a way to write your SQL in a string and then execute it.
e.g.
v_sql = "create table " + v_table_name + for loop with columns... ";
execute immediate v_sql;

There is already an object named '#BaseData' in the database

Below is a snippet of my code.
I am wanting to filter my data based upon a variable.
When I try to run the code, it returns an error of "There is already an object named '#BaseData' in the database.". I am not sure as to why this is the case; I have put extra checks within the IF statements to drop the temp table if it already exists but to no avail.
Are you able to help or provide an alternative solution please?
DECLARE #Variable AS VARCHAR(20) = 'Example1'
IF OBJECT_ID(N'TEMPDB..#BaseData') IS NOT NULL
DROP TABLE #BaseData
IF #Variable = 'Example1'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
END
IF #Variable = 'Example2'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
WHERE
[column] = 1
END
IF #Variable = 'Example3'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
WHERE
[column] = 0
END
While code is compiled by SQL, creation of same #table is found in each condition so it doesn't work.
One possible solution would be to create table and than insert data conditionally.
-- DROP TEMP TABLE IF EXISTS
IF OBJECT_ID(N'TEMPDB..#BaseData') IS NOT NULL
DROP TABLE #BaseData
GO
-- CRATE TEMP TABLE WITH TempId, AND SAME STRUCTURE AS YOUR TABLE
SELECT TOP 0 CONVERT(INT, 0)TempId, * INTO #BaseData FROM TestTable
-- DECLARE VARIABLE
DECLARE #Variable AS VARCHAR(20)= 'Example1'
-- INSERT DATA IN TABLE DEPENDING FROM CONDITION
IF (#Variable = 'Example1')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable
END
IF (#Variable = 'Example2')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable WHERE Id = 1
END
IF (#Variable = 'Example3')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable WHERE Id = 2
END

If Else Statement to Skip Value if populated

I am trying to create an if else script to skip a record if there is a specific value in a column of the table and continue to insert records into a different table.
How do I create the script to perform this action?
IF EXISTS (Select * From Table A where X =1)
BEGIN
Do nothing
END
ELSE
BEGIN
INSERT INTO TABLE Y
SELECT * FROM TABLE Z
END
Instead, write a single statement:
INSERT INTO TABLE Y
SELECT *
FROM TABLE Z
WHERE NOT EXISTS (Select 1 From Table A where X = 1);
The conditional is not needed at all.
If you want it in a proc to execute, use it this way
create procedure usp_insert
as
BEGIN
declare #rowcount int = (Select count(*) From TableA where X <>'1')
Begin
if #rowcount>=1
INSERT INTO TABLE Y
SELECT * FROM TABLE Z
end
END

T-SQL If Else condition on the same Temp Table

Here is what I am trying to do:
IF len(Variable) > 1
BEGIN
SELECT * INTO #TEMPTAB FROM multiple joins
END
ELSE
BEGIN
SELECT * INTO #TEMPTAB FROM different multiple joins
END
SELECT * FROM #TEMPTAB more large number of multiple joins & where & groupby
ERROR: There is already an object #TEMPTAB defined
-- Because of select * into in IF and ELSE both
I don't want to create a temp table prior cause it has a lot of columns to be defined.
Is there a way around it?
This was a fun problem for me that is... Well I figured out four ways to do it. One is with a view, one with a temp Table, one with a physical table, and one with a stored procedure and global temp table. Let me know if you have any questions.
View
DECLARE #Variable VARCHAR(10) = 'aa';
IF LEN(#Variable) > 1
BEGIN
EXEC('CREATE VIEW yourView AS SELECT ''Greater than 1'' col')
END
ELSE
BEGIN
EXEC('CREATE VIEW yourView AS SELECT ''Less than 1'' col')
END
SELECT *
FROM yourView;
DROP VIEW yourView;
Temp Table
DECLARE #Variable VARCHAR(100) = 'aa',
--Default value is 0
#percent INT = 0;
--If the length > 1, then change percent to 100 as to return the whole table
IF LEN(#Variable) > 1
SET #percent = 100;
--If the length <=1, then #percent stays 0 and you return 0 percent of the table
SELECT TOP(#percent) PERCENT 'Greater than 1' col INTO #TEMPTAB
--If you didn't populate the table with rows, then use this query to populate it
IF(#percent = 0)
BEGIN
INSERT INTO #TEMPTAB
SELECT 'Less than 1' col
END
/*your 1k lines of code here*/
SELECT *
FROM #TEMPTAB
--Cleanup
DROP TABLE #tempTab
Physical Table
DECLARE #Variable VARCHAR(10) = 'A';
IF len(#Variable) > 1
BEGIN
SELECT 'Greater than 1' col INTO TEMPTAB
END
ELSE
BEGIN
SELECT 'Less than 1' col INTO TEMPTAB2
END
IF OBJECT_ID('TEMPTAB2') IS NOT NULL
--SP_Rename doesn't work on temp tables so that's why it's an actual table
EXEC SP_RENAME 'TEMPTAB2','TEMPTAB','Object'
SELECT *
FROM TEMPTAB
DROP TABLE TEMPTAB;
Stored Procedure with Global Temp Table
IF OBJECT_ID('yourProcedure') IS NOT NULL
DROP PROCEDURE yourProcedure;
GO
CREATE PROCEDURE yourProcedure
AS
IF OBJECT_ID('tempdb..##TEMPTAB') IS NOT NULL
DROP TABLE ##tempTab;
SELECT 'Greater than 1' col INTO ##TEMPTAB
GO
DECLARE #Variable VARCHAR(10) = 'aaa';
IF LEN(#Variable) > 1
BEGIN
EXEC yourProcedure;
END
ELSE
BEGIN
SELECT 'Less than 1' col INTO ##TEMPTAB
END
SELECT *
FROM ##TEMPTAB
IF OBJECT_ID('tempdb..##TEMPTAB') IS NOT NULL
DROP TABLE ##TEMPTab;
Didn't you consider dynamic query with global temporary tables? This works for me:
DECLARE #sql NVARCHAR(MAX) = CASE WHEN 1 = 2
THEN 'SELECT * INTO ##TEMPTAB FROM dbo.SomeTable1'
ELSE 'SELECT * INTO ##TEMPTAB FROM dbo.SomeTable2'
END
EXEC (#sql)
SELECT * FROM ##TEMPTAB
DROP TABLE ##TEMPTAB
The first time you ran this code it created the table #TEMPTAB. The next time you ran SQL Server is telling you the table already exists. You should precede your code with the following:
if object_ID('tempdb..#TEMPTAB','U') is not null
drop table #TEMPTAB
This will drop (delete the table if it already exists) and the code that follows will always be able to recreate(or create) the table.

Using IF / ELSE to determine a SELECT INTO statement

I'm having some strange issues using IF / ELSE to determine which one or two SELECT statements to execute. The error message I'm getting when running the full statement is that my temporary table already exists, but that does not occur if I run two separate executions of two separate IF statements.
Here is the code in SQL Server:
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
SELECT * into #temp1
FROM PreviousMonthTbl
END
ELSE
BEGIN
SELECT * into #temp1
FROM CurrentMonthTbl
END
It's a "feature" of the syntax checking in SQL Server. You simply cannot "create" a #temporary table twice within the same batch.
This is the pattern you need.
SELECT * into #temp1
FROM PreviousMonthTbl
WHERE 1=0;
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
INSERT into #temp1 SELECT *
FROM PreviousMonthTbl
END
ELSE
BEGIN
INSERT into #temp1 SELECT *
FROM CurrentMonthTbl
END
If you prefer, you can also express the branch (in this case) as a WHERE clause:
SELECT * into #temp1
FROM PreviousMonthTbl
WHERE (select BusinessDayCount from Calendartbl) <= 1
UNION ALL
SELECT *
FROM CurrentMonthTbl
WHERE isnull((select BusinessDayCount from Calendartbl),2) > 1
You can't use SELECT INTO for a tables with same name in the same batch. Use a different name for a temporary table
IF EXISTS(
SELECT 1
FROM Calendartbl
WHERE BusinessDayCount <= 1
)
BEGIN
IF OBJECT_ID('tempdb.dbo.#PreviousMonthTbl') IS NULL DROP TABLE dbo.#PreviousMonthTbl
SELECT *
INTO #PreviousMonthTbl
FROM PreviousMonthTbl
END
ELSE
BEGIN
IF OBJECT_ID('tempdb.dbo.#CurrentMonthTbl') IS NULL DROP TABLE dbo.#CurrentMonthTbl
SELECT *
INTO #CurrentMonthTbl
FROM CurrentMonthTbl
END
From what I understand the problem is this:
When you run the below statement,
SELECT * into #temp1 FROM CurrentMonthTbl
you are creating a temp table on the fly.
If before that line you had a create table statement, then this Select into statement will fail because the table already exists.
If in your case you already have a temp table created, then try replacing:
SELECT * into #temp1 FROM CurrentMonthTbl
with:
Insert into #temp1
Select * from CurrentMonthTbl
Also look at There is already an object named '##Temp' in the database
You can use actual table in place of #temp1 table in if else statement. After that you can insert the data from actual to temp table and drop the actual table.
IF OBJECT_ID('tempdb..#temp1') is not null
drop table #temp1
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
SELECT * into dbo.TempTable
FROM PreviousMonthTbl
END
ELSE
BEGIN
SELECT * into dbo.TempTable
FROM CurrentMonthTbl
END
select * into #temp1
from dbo.TempTable
IF OBJECT_ID('dbo.TempTable', 'U') is not null
drop table dbo.TempTable