Insert result of select into temp table in the procedure - sql-server

In procedure, I need to make two or more queries resulting the same columns and unite that resulting rows in one returning table. Example
CREATE PROC tmpProc
AS
BEGIN
-- Making first query
SELECT * INTO #resultTable FROM tableOne;
-- Making second query, resulting columns are totally the same
SELECT * INTO #resultTable FROM tableTwo;
-- Return rowset from temporary table
SELECT * From #resultTable;
END
But this type of proc failed, because There is already an object named #resultTable in the database

Here are two sample to do that:
IF OBJECT_ID('tempdb..#resultTable') IS NOT NULL DROP TABLE #resultTable
------ 1 use insert into select---------------------
SELECT * INTO #resultTable FROM tableOne;
INSERT INTO #resultTable SELECT * FROM tableTwo
------ 1 use union ---------------------
SELECT * INTO #resultTable FROM (
SELECT * FROM tableOne
UNION ALL
SELECT * FROM tableTwo
) AS t

This will work if columns are same in two tables.
CREATE PROC tmpProc
AS
BEGIN
-- Making first query
SELECT * FROM tableOne;
UNION ALL
SELECT * FROM tableTwo;
END

CREATE PROC tmpProc
AS
BEGIN
-- Making first query
SELECT * INTO #resultTable FROM tableOne;
-- Making second query, resulting columns are totally the same
INSERT INTO #resultTable SELECT * FROM tableTwo;
-- Return rowset from temporary table
SELECT * From #resultTable;
END

Try this
CREATE PROC tmpProc
AS
BEGIN
select * into #resultTable from (
SELECT col1,col2,col3...coln FROM tableOne;
union all
SELECT col1,col2,col3...coln FROM tableTwo;
) as a
SELECT * From #resultTable;
END

Related

Capturing all the columns in a select statement except one from a table

Is there any way to select all the columns except one in Snowflake like we have in bigquery:
select * except(columnname) from table
2022 update: Snowflake now supports EXCLUDE():
Test with:
with data as (
select 1 col_a, 2 col_b, 3 col_c, 4 col_d
)
select *, col_a as id
exclude (col_c, col_b, col_a)
from data
https://twitter.com/felipehoffa/status/1593311749100294144
Previous answer:
In lieu of the EXCEPT syntax, I wrote a stored procedure that can give you the list of columns to SELECT for:
create or replace procedure cols_except(table_name varchar, except varchar)
returns varchar
language sql as
begin
describe table identifier(:table_name);
return (
select listagg("name", ', ') cols_except
from table(result_scan(last_query_id()))
where not array_contains("name"::variant, (split(:except, ',')))
);
end;
You can use it to get the columns to select for, after eliminating the values that match the except clause:
call cols_except('snowflake_sample_data.tpch_sf1.nation', 'N_NAME,N_REGIONKEY');
Snowflake supports natively SELECT * EXCLUDE(<col_list>) syntax:
SELECT * EXCLUDE id FROM tab1;
SELECT * EXCLUDE (id, col1) FROM tab1;
For sample data:
CREATE OR REPLACE TABLE tab1(id INT, col1 TEXT, col2 TEXT)
AS
SELECT 1, 'a', 'b';
Output:

How to set variables in While Loop in Sql Server

I am trying to use while loop instead of CURSOR in SQL SERVER. I am trying to select TOP 1 in while and set them to the variables like below. It doesnt let me set the variables in while loop. What am I doing wrong?
WHILE (
SELECT TOP 1 #WAOR_CODE = WAOR_.WAOR_CODE
, #WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder
)
BEGIN
SELECT #WAOR_CODE
, #WAOD_INVENTORYITEMID
DELETE TOP (1) #wmsorder
END
Another option:
WHILE EXISTS(select 1 FROM #wmsorder)
BEGIN
DELETE TOP (1)
FROM #wmsorder
END
However, deleting all records from a table one by one might be a performance hell. You might want to consider using TRUNCATE TABLE instead:
TRUNCATE TABLE #wmsorder
Also, note that each delete is written to the database log, while truncate table doesn't get written to the log at all.
Testing with a temporary table containing 100,000 rows, deleting the rows one by one took me 9 seconds, while truncate table completed immediately:
-- create and populate sample table
SELECT TOP 100000 IDENTITY(int,1,1) AS Number
INTO #wmsorder
FROM sys.objects s1
CROSS JOIN sys.objects s2
-- delete rows one by one
WHILE EXISTS(select 1 FROM #wmsorder)
BEGIN
DELETE TOP (1)
FROM #wmsorder
END
-- clean up
DROP TABLE #wmsorder
-- create and populate sample table
SELECT TOP 100000 IDENTITY(int,1,1) AS Number
INTO #wmsorder
FROM sys.objects s1
CROSS JOIN sys.objects s2
-- truncate the table
TRUNCATE TABLE #wmsorder
-- clean up
DROP TABLE #wmsorder
DECLARE #t TABLE (a INT PRIMARY KEY)
INSERT INTO #t
VALUES (1), (2), (3)
Variant #1:
label:
DELETE TOP(1)
FROM #t
OUTPUT DELETED.a
IF ##ROWCOUNT > 0
GOTO label
Variant #2:
WHILE ##ROWCOUNT != 0
DELETE TOP(1)
FROM #t
OUTPUT DELETED.a
Variant #3:
DECLARE #a TABLE(a INT)
WHILE ##ROWCOUNT != 0 BEGIN
DELETE FROM #a
DELETE TOP(1)
FROM #t
OUTPUT DELETED.a INTO #a
SELECT * FROM #a
END
See the below code. I just corrected the SQL statements shared by you
WHILE 1=1
BEGIN
IF NOT EXISTS (SELECT 1 FROM #wmsorder)
BREAK
SELECT TOP 1 #WAOR_CODE = WAOR_.WAOR_CODE
,#WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder WAOR_
SELECT #WAOR_CODE
,#WAOD_INVENTORYITEMID
DELETE #wmsorder WHERE WAOR_CODE = #WAOR_CODE AND WAOD_INVENTORYITEMID = #WAOD_INVENTORYITEMID
END
But as Zohar Peled mentioned, it will be a pain to the engine if you are deleting the records one by one from a table. So below I have shared another query, through this even you can track the records before deleting from the table
DECLARE #TableVar AS TABLE (WAOR_CODE VARCHAR(100), WAOD_INVENTORYITEMID VARCHAR(100))
WHILE 1=1
BEGIN
SELECT TOP 1 #WAOR_CODE = WAOR_.WAOR_CODE
,#WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder WAOR_
WHERE NOT EXISTS (SELECT 1 FROM #TableVar t WHERE t.WAOR_CODE = WAOR_.WAOR_CODE AND t.WAOD_INVENTORYITEMID = WAOR_.WAOD_INVENTORYITEMID)
IF #WAOR_CODE IS NULL AND #WAOD_INVENTORYITEMID IS NULL
BREAK
INSERT INTO #TableVar
(WAOR_CODE, WAOD_INVENTORYITEMID)
SELECT #WAOR_CODE
,#WAOD_INVENTORYITEMID
END
DELETE #wmsorder WHERE EXISTS (SELECT 1 FROM #TableVar t WHERE t.WAOR_CODE = #wmsorder.WAOR_CODE AND t.WAOD_INVENTORYITEMID = #wmsorder.WAOD_INVENTORYITEMID)
Sorry I did not test the second code. Please forgive me if it breaks something. But I am pretty sure it may require a small repair to make this query functional. All the best.

Count # of Rows in Stored Procedure Result, then Insert result into table

I have an SSIS package which will first run my sp_doSomething. This stored procedure will select data from several different tables and join them for possible storage into dbo.someTable. But I only want that IF the select is > 1 row of selected data.
I want to then have a precedence restraint that looks at the amount of rows my stored procedure returned.
If my row count > 1, then I want to take the results of the stored procedure and insert them into one of my tables.
Otherwise, I will record an error/send an email, or whatever.
I really don't want to run this stored procedure more then once, but that is the only way I could think to do it (Run it, count the rows. Then, run it again and insert the result).
I'm a complete TSQL/SSIS newb. So I'm sorry if this question is trivial.
I can't find a good answer anywhere.
Create a variable with Package Scope of type Int32 and name rowcount.
Data Flow
Control Flow
you can try this
declare #tableVar table(col1 varchar(100))
declare #Counter int
insert into #tableVar(col1) exec CompanyNames
set #Counter = (select count(*) from #tableVar)
insert into Anytable(col) Values (#counter)
Within the Stored Proc, write the results to a #Temp. Then Select Count(*) from the #Temp, into a variable.
Select #intRows = Count(*) from myTempResults
Then evaluate the value of #intRows.
If #intRows > 1 BEGIN
Insert Into dbo.SomeTable
Select * from #Temp
End
Will a #temp table work for you?
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
CREATE TABLE #Holder
(ID INT )
declare #MyRowCount int
declare #MyTotalCount int = 0
/* simulate your insert, you would read from your real table(s) here */
INSERT INTO #HOLDER (ID)
select 1 union all select 2 union all select 3 union all select 4
Select #MyRowCount = ##ROWCOUNT, #MyTotalCount = #MyTotalCount + #MyRowCount
Select 'TheMagicValue1' = #MyRowCount, 'TheMagicTotal' = #MyTotalCount
INSERT INTO #HOLDER (ID)
select 5 union all select 6 union all select 7 union all select 8
/* you will note that I am NOT doing a count(*) here... which is another strain on the procedure */
Select #MyRowCount = ##ROWCOUNT, #MyTotalCount = #MyTotalCount + #MyRowCount
Select 'TheMagicValue1' = #MyRowCount, 'TheMagicTotal' = #MyTotalCount
/* Optional index if needed */
CREATE INDEX IDX_TempHolder_ID ON #Holder (ID)
/* CREATE CLUSTERED INDEX IDX_TempHolder_ID ON #Holder (ID) */
if #MyTotalCount > 0
BEGIN
Select 'Put your INSERT statement here'
END
/* this will return the data to the report */
Select ID from #HOLDER
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end

T-SQL Insert into temp table from another temp table

I am trying to acheive like this at the end of the procedure i need all the rows in
one temp table
How can I accomplish this
if #i > 1
begin
select * from into #tempTbl1 from payments
where method = 'test1'
end
else
begin
select * from into #tempTbl2 from payments
where method = 'test1'
end
insert into #tempTbl1 select * from #tempTbl2
select * from #tempTbl1
despite the previous logic issue, to simplely get all rows from both temp tables , use UNION:
select * from #tempTbl1
UNION ALL
SELECT * from #tempTbl2
The problem you have here is that based on your IF/ELSE you will never had both tables. Your final INSERT INTO requires that both tables exist. You may need to create the objects before hand in the stored proc before you try to populate, then insert into the tables.
This also begs the question, if you're going to later insert everything in #tempTbl1 anyways, which is created in the SELECT INTO statement, why have the #tempTbl2 in the first place?
create procedure dbo.testing
(#i int)
AS
if #i > 1
begin
print 'In condition 1'
select *
into #tempTbl1
from payments
where method = 'test1'
end
else
begin
print 'In condition 2'
select *
into #tempTbl2
from payments
where method = 'test1'
end
print 'Made it out of the if else'
insert into #tempTbl1
select *
from #tempTbl2
-- Never gets this far...
print 'In the final select'
select *
from #tempTbl1
If you're committed to this method, then you may need to check to see if the table exists:
IF EXISTS (SELECT * FROM tempdb.sys.objects WHERE object_id = OBJECT_ID(N'tempdb.dbo.#tempTbl1') AND type in (N'U'))
print 'Table is there'
Update based on comments
Based on your comments, this will work. The SELECT...INTO statement you originally posted lets you create a table based on the data types of the columns your selecting from, but the destination table can't already exist. If you define the structure you're going to insert into beforehand, you can have the two conditions evaluate and end up with a single table as the result.
(Note - my "payments" table only had two columns, "method" and "col2". You would want to specify the columns you need in the CREATE TABLE and the SELECT)
create procedure dbo.testing
(#i int)
AS
create table #tempTbl1
(method varchar(10)
, col2 int)
if #i > 1
begin
insert into dbo.#tempTbl1
select method, col2
from payments
where method = 'test1'
end
else
begin
insert into dbo.#tempTbl1
select method, col2
from payments
where method = 'test1'
end
select *
from #tempTbl1

How to use two temporary tables with the same name but different structures

Following is what my logic is supposed to do
IF #id = 1
BEGIN
SELECT * INTO #abc from table1
END
IF #id = 2
BEGIN
SELECT * INTO #abc frm table2
END
However, when I execute my statements I get the error saying
there is already an object named #abc..
Any suggestions to overcome this error please?
You can't. The parser doesn't understand your IF logic and it treats both SELECT INTO statements as things that will happen.
What you should do is:
IF #id = 1
BEGIN
SELECT * INTO #abc1 from table1
END
IF #id = 2
BEGIN
SELECT * INTO #abc2 frm table2
END
IF #id = 1
SELECT * FROM #abc1;
ELSE
SELECT * FROM #abc2;
After all, you need to know the different columns that are in the #temp table in order to do anything meaningful with it, right?
(Or avoid temp tables altogether.)
Another possible solution:
CREATE TABLE #abc (
--put schema here
)
IF #id = 1
BEGIN
insert into #abc
select * from table1
END
IF #id = 2
BEGIN
insert into #abc
select * from table2
END
select * from #abc
drop table #abc;
You should always use the column names instead of * because it's better in terms of performance.
And also, select * finds all the columns currently in a table, changes in the structure of a table such as adding, removing, or renaming columns automatically modify the results of select *. Listing columns individually gives you more precise control over the results.

Resources