Create a temp table with pre-filled columns - sql

Im trying to create a temp table #TempTable with columns. There are many columns and I do not want to type them all out by hand. Is there a way to pre-fill, if that makes sense?
Instead of
CREATE #TempTable (col1, col2 ... col1000) -- Im not saying we have 1000
But doing:
CREATE #TempTable (SELECT column_name
from information_schema.columns where table_name = 'OriginalTable')
Is this possible? Im using MS SQL.

You can do SELECT . . . INTO :
SELECT ot.* INTO #TempTable
FROM OriginalTable ot
WHERE 1 = 0;
Note : When using the SELECT . . . INTO statement, the #TempTable must not already exist.

When creating a temp table, it's good to clean up before creating it. repeating this step will cause an error if the table already exists
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
select *
into #tmp
from OriginalTable

One way of doing -
select top 0 * into #TempTable from OriginalTable
The above creates an empty copy of temp table
If you don't want to specify *(wildcard) and want specific columns from OriginalTable to be created in your temporary table -
select top 0 col1,col2,col3 into #TempTable from OriginalTable

Related

Table "already exists" after dropping with if exists

I got a pretty complex SQL that finally forced me to use a temp table to work around.
Essentially it looks like this:
;IF EXISTS(SELECT * FROM sys.tables WHERE SCHEMA_NAME(schema_id) LIKE 'dbo' AND name like '#MYTEMPTABLE')
DROP TABLE #MYTEMPTEBLE;
WITH cte AS ...
SELECT * INTO #MYTEMPTABLE FROM cte
SELECT * FROM #MYTEMPTABLE WHERE [conditions]
DROP TABLE #MYTEMPTABLE;
However, I get an error message saying an object with the name #MYTEMPTABLE already exists in the database after a call with an error (which is rather likely if the customer/tester screws up some data).
It might DROP TABLE fail on your check condition, it might check from TempDB.INFORMATION_SCHEMA.COLUMNS table instead of sys.tables table
SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME IN (
SELECT NAME
FROM TempDB.SYS.TABLES
WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#MYTEMPTEBLE')
);
sqlfiddle
If your SQL server version was higher than 2016, you can try to use DROP TABLE IF EXISTS
DROP TABLE IF EXISTS #MYTEMPTEBLE;
WITH cte AS ...
SELECT * INTO #MYTEMPTABLE FROM cte
SELECT * FROM #MYTEMPTABLE WHERE [conditions]
if your SQL server version didn't support that, you can check OBJECT_ID IS NOT NULL which represnt temp table exists in your system
IF OBJECT_ID('TempDB..#MYTEMPTEBLE') IS NOT NULL
DROP TABLE #MYTEMPTEBLE;

Loop with DB names inserting

I have a number of databases with tables Table1 with the same structures. All table names are listed in the main1 database in the table testbases. It is necessary in a loop to go through all the rows from the Table1 and insert them into query.
SELECT * FROM [DBNAME].[DBO].Table1.Client
UNION
To end up with a big query like this:
SELECT * FROM [DBNAME1].[DBO].Table1.Client
UNION
SELECT * FROM [DBNAME2].[DBO].Table1.Client
UNION
SELECT * FROM [DBNAME3].[DBO].Table1.Client
UNION
SELECT * FROM [DBNAME4].[DBO].Table1.Client
UNION
etc...
How can I do this efficiently and automatically, so I don't need to manually change the query every time we add a client?
If all of the tables are identical, you could use sp_MSforeachdb along with an IF EXISTS to go through all of your databases, then insert the table if found into a temp table. You would just need to change the column names from col1, col2, ... to whatever your actual table schema is. Although you'd need to exclude any databases that contain a Table1 table that you don't want included in your data set.
DROP TABLE IF EXISTS #insertTable (col1 varchar(100), col2 varchar(100),...)
DECLARE #command varchar(1000)
SELECT #command = 'USE ?
EXEC(''IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''''Table1'''')
SELECT col1, col2, ... FROM Table1'')'
INSERT INTO #insertTable (col1, col2, ...)
EXEC sp_MSforeachdb #command

Update a column in a table repeatedly

I have a table like this
CREATE TABLE #tmp(ColSelect NVARCHAR(400),ColParValues XML)
that ColSelect contains SQL Select Statement and ColParValues contains some xml data for parameter value in ColSelect
for example ColSelectcontains:
"SELECT [$12]+19/[$16]-[$54]"
and col 2 contains name value pair that refer to ColSelect parameters
How can I update my table that replace each parameter with relevant value from ColParValues. I use this statement:
update #tmp
SET
ColSelect=REPLACE(ColSelect,c.value('#Value','nvarchar(10)'),c.value('#Res','DECIMAL(24,12)'))
FROM #tmp t1
CROSS APPLY t1.ColParValues.nodes('/root/r') AS n(c)
but this statement replace just one parameter value in each row.
And this is sample data link
This is one solution :
create table #tmp (colselect varchar(200),colparvalues xml)
insert into #tmp (colselect,colparvalues)
values ('select case when [$71]+[$29]+10<25 then 1 else 0 end'
,'<root><r Value="[$71]" Res="1"/><r Value="[$29]" Res="5"/></root>'),
('select case when [$95]*[$29]+10<25 then 1 else 0 end'
,'<root><r Value="[$95]" Res="3"/><r Value="[$29]" Res="5"/></root>')
WHILE ##ROWCOUNT >0
update #tmp
SET
ColSelect=REPLACE(ColSelect,c.value('#Value','nvarchar(10)'),c.value('#Res','DECIMAL(24,12)'))
FROM #tmp t1
CROSS APPLY t1.ColParValues.nodes('/root/r') AS n(c)
WHERE t1.colselect LIKE'%'+replace(c.value('#Value','nvarchar(10)'),'[','')+'%'
select * from #tmp
drop table #tmp
However, very much similar to cursor in performance. Check the performance. Use if ok.

How to SELECT * INTO [tmp table] without declare table?

i want use select statement on the a table and inserting result into a temp table variable, but i don't declare temp table with columns and i want use like this:
Declare #tmp table;
SELECT * INTO #tmp FROM myTable
this want declare columns and data types for #tmp
please help me
You can do this simply without the DECLARE command - which is not valid for #temp tables anyway, only #table variables. Did you try just the following without trying to define #tmp first:
SELECT * INTO #tmp FROM myTable;
With data:
select *
into #tmp
from myTable
No data:
select *
into #tmp
from myTable
where 0=1
BTW, you can not do this with table variables.
select *
into #tmp
from myTable
Table variables need to be declared with the columns.

create temp table of trigger data

I am trying to create an audit trigger without having to specifiy the column list more than once.
To this end, I want to product a temporary table of the content of the INSERTED or DELETED data in the trigger, then process that into an audit table.
If I use this:
IF #ChangeType = 'D'
SELECT * INTO #tmp FROM DELETED
ELSE
SELECT * INTO #tmp FROM INSERTED
Then I get a compilation error at the 2nd SELECT * INTO that the table #tmp already exists.
If I try and work around this using dynamic SQL:
SET #Sql = 'SELECT * INTO #tmp FROM '
IF #ChangeType = 'D'
SET #Sql = #Sq + 'DELETED'
ELSE
SET #Sql = #Sql + 'INSERTED'
EXEC (#Sql)
Then I get an error that the DELETED and INSERTED tables do not exist.
How can I get the INSERTED and DELETED tables in a trigger into a temporary or other in-memory table?
Try to create the temporary table outside the if, like:
SELECT TOP 0 * INTO #tmp FROM DELETED
IF #ChangeType = 'D'
INSERT INTO #tmp SELECT * FROM DELETED
ELSE
INSERT INTO #tmp SELECT * FROM INSERTED
This is a known problem due to the resolve-on-parse of the temp table object. With two SELECT - INTO statements in the same scope, SQL Server throws the towel.
SELECT * INTO #tmp FROM DELETED WHERE 1=0
IF #ChangeType = 'D'
INSERT #tmp SELECT * FROM DELETED
ELSE
INSERT #tmp SELECT * FROM INSERTED
I'd be interested as to why you need to copy the data into another table in the first place. But, that's off-topic...
Temporary table (#temp) are notionally stored on disc, and Table Variables (#temp) are notionally only in memory and may be more optimal for small tasks. (Assumes writes to the table will normally only affect small numbers of rows.)
Temporary tables, however, can be created using the SELECT INTO trick, avoiding the need to know the table definition in advance.
If you do know the table definition in advance, however, can't you simply use something such as the following?
DECLARE #temp TABLE (id AS INT, val as INT)
IF #ChangeType = 'D'
INSERT INTO #temp SELECT * FROM DELETED
ELSE
INSERT INTO #temp SELECT * FROM INSERTED
Personally, I'd even avoid using * if possible. Your subsequent queries will only use specific fields, so I'd only copy the fields I was using. This has the added benefit that if fields are added to the table, the code doesn't break...
DECLARE #temp TABLE (id AS INT, val as INT)
IF #ChangeType = 'D'
INSERT INTO #temp SELECT id, val FROM DELETED
ELSE
INSERT INTO #temp SELECT id, val FROM INSERTED
In my mind, the advantage of specifying the fields (which is what you wish to avoid), is that you can ensure that you always only copy what you need.