Describe Temp table columns in SQL Server - sql-server

I have this script:
CREATE TABLE #TempTable (Id int)
ALTER TABLE #TempTable ADD [IdKey] INT
ALTER TABLE #TempTable ADD [ProviderName] NVARCHAR(100)
SELECT *
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..#TempTable');
I need to read the columns of this temp table and create another temp table based on the previous one.
Why when I do the select of tempdb.sys.columns, the ProviderName length is 200 instead of 100?

With this simple query it's possible to copy the temp table structure:
SELECT *
INTO #NewTempTable
FROM #TempTable
WHERE 1 = 0

Using this will solve the issue:
SELECT * FROM [tempdb].[sys].[dm_exec_describe_first_result_set] (N'SELECT Id, [IdKey], [ProviderName] FROM #temptable', null, 0);

Clone Temporary Table Structure to New Physical Table in SQL Server
we will see how to Clone Temporary Table Structure to New Physical Table in SQL Server.This is applicable for both Azure SQL db and on-premises.
Demo SQL Script
IF OBJECT_ID('TempDB..#TempTable') IS NOT NULL
DROP TABLE #TempTable;
SELECT 1 AS ID,'Arul' AS Names
INTO
#TempTable;
SELECT * FROM #TempTable;
METHOD 1
SELECT * INTO TempTable1 FROM #TempTable WHERE 1=0;
EXEC SP_HELP TempTable1;
METHOD 2
SELECT TOP 0 * INTO TempTable1 FROM #TempTable;
EXEC SP_HELP TempTable1;

Related

How to create a table in sql server like other table?

I want to create a table like another table in SQL Server.
In Postgres I used to create it with this request:
CREATE TABLE IF NOT EXISTS table2 (LIKE table1 INCLUDING ALL) INHERITS (table1)
Something like this should work:
IF OBJECT_ID('table1', 'U') IS NULL BEGIN
SELECT TOP 0 * INTO table1 FROM table2
END
This will clone the column definition of table2 in table1 without inserting any data (because of the top 0).
Then you have to create the PK, UK, FK for the table1. For this purpose you can check: https://www.mssqltips.com/sqlservertip/3443/script-all-primary-keys-unique-constraints-and-foreign-keys-in-a-sql-server-database-using-tsql/
With this resource you can generate an ALTER TABLE script to add all PK, UK, FK in a variable and run it like:
DECLARE #sqlCommand nvarchar(1000)
EXECUTE sp_executesql #sqlCommand
SELECT *
INTO table2
FROM table1 where 1=2
SELECT * = select all columns
INTO= place of set
FROM = place to lookup,
WHERE 1=2 = filter criteria
select top 0 * into x from y
will give you an empty shell of a table with no data exactly defined as the original table minus all the indexes , constraints etc

Truncate existing table within a stored procedure then insert fresh data

I have a stored procedure that returns a result set. After that I insert this result set into created real table. And then I am using that real table create SSRS reports.
So, something like this:
CREATE PROCEDURE Test
AS
DECLARE #TempTable TABLE(..)
INSERT INTO #TempTable
SELECT...
FROM ...
WHERE ...
SELECT * FROM #TempTable
--============================
INSERT INTO RealTable EXEC [dbo].[Test]
How can I modify this stored procedure so every time it executed it will truncate table with existing data and then insert a fresh one?
So I need something like that:
create procedure Test
as
TRUNCATE RealTable
DECLARE #TempTable TABLE(..)
INSERT INTO #TempTable
SELECT...
FROM...
WHERE...
SELECT * FROM #TempTable INTO RealTable
Or should I just create agent job that would run command something like:
Truncate Table RealTable
INSERT INTO RealTable EXEC [dbo].[Test]
Am I on a right way in terms of logic?
Dont TRUNCATE. Use a MERGE Statement.
CREATE PROCEDURE Test
AS
MERGE RealTable TRGT
USING SourceTable SRCE
ON SRCE.[Column] = TRGT.Column --use columns that can be joined together
WHEN MATCHED THEN UPDATE
SET TRGT.Column1 = SRCE.Column1,
TRGT.Column2 = SRCE.Column2
....................
WHEN NOT MATCHED BY TARGET THEN INSERT
VALUES
(
SRCE.Column1,
SRCE.Column2,
.....................
)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
What's the purpose of the truncate if you are inserting the same data?
What should happen if you have more then 1 concurrent user?
another thing you can do:
1.
insert into TargetTable
select * from SourceTable
2.
rebuild indexes on TargetTable
3.
exec sp_rename SourceTable, SourceTable_Old
exec sp_rename TargetTable, SourceTable
drop table SourceTable_Old
this is an old way of entire table data refresh without much impact, when table variable was not an option.
this is what you probably need as you are directly inserting from #TempTable to RealTable.
create procedure Test
as
BEGIN
TRUNCATE TABLE RealTable
INSERT INTO RealTable
SELECT...
FROM someothertable
WHERE...
END

Table used in proc defaults to the calling schema instead of dbo if the table exists in that schema too

I created mytable in both dbo and schema1 schemas.
Then a proc using mytable. Notice schema name is not present.
Executing the proc used schema1.mytable. Shouldn't it have been dbo.mytable when schemaname is not present? What is the concept involved here?
create proc schema1.myproc
as
begin
select id into #tbl
from mytable
select * from #tbl
end
select * from dbo.mytable
++++++++
id name
1 a
++++++++
select * from schema1.mytable
++++++++
id name
2 b
++++++++
exec schema1.myproc
++++++++
id
2
++++++++
Since your stored procedure schema is schema1 if you don't mention the schema name it will be used
change your sp to this it will return the dbo data
create proc dbo.myproc
as
begin
select id into #tbl
from mytable
select * from #tbl
end

How to drop a table if it exists?

The table name is Scores.
Is it correct to do the following?
IF EXISTS(SELECT *
FROM dbo.Scores)
DROP TABLE dbo.Scores
Is it correct to do the following?
IF EXISTS(SELECT *
FROM dbo.Scores)
DROP TABLE dbo.Scores
No. That will drop the table only if it contains any rows (and will raise an error if the table does not exist).
Instead, for a permanent table you can use
IF OBJECT_ID('dbo.Scores', 'U') IS NOT NULL
DROP TABLE dbo.Scores;
Or, for a temporary table you can use
IF OBJECT_ID('tempdb.dbo.#TempTableName', 'U') IS NOT NULL
DROP TABLE #TempTableName;
SQL Server 2016+ has a better way, using DROP TABLE IF EXISTS …. See the answer by #Jovan.
From SQL Server 2016 you can use
DROP TABLE IF EXISTS dbo.Scores
Reference: DROP IF EXISTS - new thing in SQL Server 2016
It will be in SQL Azure Database soon.
The ANSI SQL/cross-platform way is to use the INFORMATION_SCHEMA, which was specifically designed to query meta data about objects within SQL databases.
if exists (select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'Scores' AND TABLE_SCHEMA = 'dbo')
drop table dbo.Scores;
Most modern RDBMS servers provide, at least, basic INFORMATION_SCHEMA support, including: MySQL, Postgres, Oracle, IBM DB2, and Microsoft SQL Server 7.0 (and greater).
Have seen so many that don't really work.
when a temp table is created it must be deleted from the tempdb!
The only code that works is:
IF OBJECT_ID('tempdb..#tempdbname') IS NOT NULL --Remove dbo here
DROP TABLE #tempdbname -- Remoeve "tempdb.dbo"
In SQL Server 2016 (13.x) and above
DROP TABLE IF EXISTS dbo.Scores
In earlier versions
IF OBJECT_ID('dbo.Scores', 'U') IS NOT NULL
DROP TABLE dbo.Scores;
U is your table type
Or:
if exists (select * from sys.objects where name = 'Scores' and type = 'u')
drop table Scores
I hope this helps:
begin try drop table #tempTable end try
begin catch end catch
I wrote a little UDF that returns 1 if its argument is the name of an extant table, 0 otherwise:
CREATE FUNCTION [dbo].[Table_exists]
(
#TableName VARCHAR(200)
)
RETURNS BIT
AS
BEGIN
If Exists(select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME = #TableName)
RETURN 1;
RETURN 0;
END
GO
To delete table User if it exists, call it like so:
IF [dbo].[Table_exists]('User') = 1 Drop table [User]
Simple is that:
IF OBJECT_ID(dbo.TableName, 'U') IS NOT NULL
DROP TABLE dbo.TableName
where dbo.TableName is your desired table and 'U' is type of your table.
IF EXISTS (SELECT NAME FROM SYS.OBJECTS WHERE object_id = OBJECT_ID(N'Scores') AND TYPE in (N'U'))
DROP TABLE Scores
GO
SQL Server 2016 and above the best and simple one is
DROP TABLE IF EXISTS [TABLE NAME]
Ex:
DROP TABLE IF EXISTS dbo.Scores
if suppose the above one is not working then you can use the below one
IF OBJECT_ID('dbo.Scores', 'u') IS NOT NULL
DROP TABLE dbo.Scores;
I use:
if exists (select *
from sys.tables
where name = 'tableName'
and schema_id = schema_id('dbo'))
begin
drop table dbo.tableName
end
Make sure to use cascade constraint at the end to automatically drop all objects that depend on the table (such as views and projections).
drop table if exists tableName cascade;
If you use long codes and want to write less for temporary table create this procedure:
CREATE PROCEDURE MF_DROP (#TEMP AS VARCHAR(100)) AS
EXEC('IF OBJECT_ID(''TEMPDB.DBO.' + #TEMP + ''', ''U'') IS NOT NULL DROP TABLE ' + #TEMP)
In execution:
EXEC MF_DROP #A
CREATE TABLE #A (I INT) ....
A better visual and easy way, if you are using Visual Studio, just open from menu bar,
View -> SQL Server Object Explorer
it should open like shown here
Select and Right Click the Table you wish to delete, then delete. Such a screen should be displayed. Click Update Database to confirm.
This method is very safe as it gives you the feedback and will warn of any relations of the deleted table with other tables.

Can I insert into temp table from SP without declaring table?

Here is my code:
alter procedure test1 as
select DeptID,DeptName from Department
go
alter procedure test2 as
--Create Table #tab (DeptID INT, DeptName VARCHAR(255))
INSERT INTO #tab
exec test1
select * from #tab
drop table #tab
go
exec test2
I am getting an error like "Invalid object name #tab"
If I add at the begining Create Table #tab (DeptID INT, DeptName VARCHAR(255)) then I do not get any error.
What is wrong in my code? Can I populate a temp table from the results of a stored procedure without declaring the temp table and its column definitions?
When loading a temp table from a stored procedure, then you have to CREATE the table first.
There is no straightforward equivalent of
SELECT * INTO #temptable FROM AnotherTable
The non-straightforward version (read all about the bad stuff on "How to Share Data Between Stored Procedures". And simpler) would be
SELECT * INTO #temptable FROM OPENQUERY(Loopback, 'exec test1')
It's because the Local Temporary table #tab which you are expecting does not existing in the session.
So the table creation should not be commented line.
Create Table #tab (DeptID INT, DeptName VARCHAR(255))
Moreover, if you want to do without creating the table then it should be like below
Alter procedure test2
As
Set NoCount ON
IF OBJECT_ID('tempdb..#tab') IS NOT NULL
Begin
Drop table #temp
End
SELECT DeptID, DeptName INTO #tab from Department
Select * from #tab
Drop table #tab
Go

Resources