Create permanent table based on temporary table in SQL Server - sql-server

I have a temp table which aggregates columns from multiple tables.
I would like to convert this temp table into a permanent table without explicit specifying the column names and their types.
Don't know if i have explained this well enough

You can use SELECT ... INTO:
SELECT *
INTO dbo.normal_table
FROM #temp_table
-- WHERE 1 = 2; --add if you only want table structure and not actual data
Things to check after table creation:
IDENTITY column and current value (may need reseeding)
DEFAULT values of column(if temp table has defaults, normal table needs to be ALTERed)
COLLATION tempdb may have different collation than your database
size of columns, precision and scale (VARCHAR,NVARCHAR,CHAR, DECIMAL..) if SELECT contains expressions
If temp table does not contain IDENTITY column you can add one using:
SELECT ID = IDENTITY(INT,1,1)
,col1 = NULL -- NULL by default are treated as INT so you may need casting
,col2 = CAST(NULL AS DECIMAL(38,10))
,t.*
INTO dbo.table_name
FROM #temp t

Related

T-SQL OUTPUT clause to update a temp table

I have a utility script that is used to insert data into tables in my database. The script has a number of temp table in it that stores the new data to be inserted and a lot of it is related.
So, for example I have tables like so
DECLARE #Table1 TABLE
(
Table1ID INT
Table1Description VARCHAR(50)
Table1Code VARCHAR(5)
)
DECLARE #Table2 TABLE
(
Table2ID INT
Table2Description VARCHAR(50)
Table2Code VARCHAR(5)
)
DECLARE #Relationships TABLE
(
Table1Code VARCHAR(5)
Table2Code VARCHAR(5)
)
So the script populates the data in #Table1 and #Table2, but doesn't populate the ID fields. Once the data has been MERGEd into the database tables, I update the Table1ID and Table2ID fields in a separate statement as they are auto incrementing fields. Then when I use the #Relationships table to populate the database table, I can join to #Table1 and #Table2 to get the actual ID values.
I'm updating the script and I'm wondering if I can MERGE the data from #Table1/#Table2 into the database and update the ID fields in the temp table as part of the MERGE statement using the OUTPUT clause all in one statement?
I think the answer is no as I can't find anything mentioning updating an existing table with the OUTPUT clause, only inserting into a table.
I am still able to do what I need to do, so I'm not after alternatives. I just wondering if it is possible using the OUTPUT Clause
Thanks in advance

Insert from temp table to a table with identity column

I'm grabbing some rows from a table, manipulating them in a temp table, and then looking to insert them as new rows into my original table.
However, I'm running into an issue with the identity column, even when I don't have the identity column on my temp table. The identity column is an auto-incrementing int.
This seems like a simple thing I'm way overthinking.
select top 0 *
into #TestTable
from OriginalTable;
...
--insert and manipulate records
...
ALTER TABLE #TestTable
DROP COLUMN MyIdentityColumn;
DECLARE #InsertedRows TABLE (NewSeqNum INT);
INSERT INTO OriginalTable
OUTPUT MyIdentityColumn INTO #InsertedRows(NewSeqNum)
SELECT * FROM #TestTable
but I get this error:
An explicit value for the identity column in table 'OriginalTable' can only be specified when a column list is used and IDENTITY_INSERT is ON.
I absolutely do not want to set an explicit value, I want it to insert and give me the new identity (via #InsertedRows)
If you don't want to keep the id of inserted records, then you need to specify all your columns but the id column in the select. As general good practice, dont select *, always specify the columns you want to retrieve-insert.
INSERT INTO OriginalTable (col1, col2, col3...)
OUTPUT MyIdentityColumn INTO #InsertedRows(NewSeqNum)
SELECT (col1, col2, col3...) FROM #TestTable
If I'm understanding you, I think your problem is that you're trying to insert '*' into the original table - which means all of your columns from the temp table. Including your ID column (which you don't want to insert, because you're wanting it to auto-generate.)
Instead, I'd suggest doing something like this:
Select [ColumnB],[ColumnC],[ColumnD],[Etc] into your temp table
Select [ColumnB],[ColumnC],[ColumnD],[Etc] into your original table.
... aka, spell out the columns explicitly, and omit the Identity column.

Inserting concatenate Identity column with other column

I have a identity column and i have other column while inserting a new row in
table i need to insert into third column with concatenate of two columns result
For reference please see below table
------------------------------------------------
A | B | c
----------------------------------------------
1 | 33 | 133(1 [identity result] + 33)
2 | 112 | 2112
Please help me to solve this issue.
There is already an answer to this question but i think is not the best way to achieve it.
Here's an example on how to achieve it with a computed column.
CREATE TABLE dbo.calculatedTEST (
A INT IDENTITY(1,1) NOT NULL,
B INT NOT NULL,
c AS CONVERT(INT,CONVERT(VARCHAR(max),A)+CONVERT(VARCHAR(max),B))
)
insert into dbo.calculatedTEST
(B)
values
(1),
(1),
(2),
(2)
select * from dbo.calculatedTEST
A computed column is computed from an expression that can use other
columns in the same table. The expression can be a noncomputed column
name, constant, function, and any combination of these connected by
one or more operators. The expression cannot be a subquery.
Unless otherwise specified, computed columns are virtual columns that
are not physically stored in the table. Their values are recalculated
every time they are referenced in a query. The Database Engine uses
the PERSISTED keyword in the CREATE TABLE and ALTER TABLE statements
to physically store computed columns in the table. Their values are
updated when any columns that are part of their calculation change. By
marking a computed column as PERSISTED, you can create an index on a
computed column that is deterministic but not precise. Additionally,
if a computed column references a CLR function, the Database Engine
cannot verify whether the function is truly deterministic. In this
case, the computed column must be PERSISTED so that indexes can be
created on it. For more information, see Creating Indexes on Computed
Columns.
Don't need to insert Column C, You can easily get Column C using Select Statement.
like this.
select A,B,cast(Cast(A as varchar(max))+cast(B as varchar(max)) as
varchar(max)) as C from Your_Table_Name
If you really need to insert column C, then you have to run insert and Update query at the same time to inset value in the C column of the table.
Like:
insert into Table_Name(B) values('33');Select IDENT_CURRENT();
--you'll get the inserted Identity.
--now run the Update query for Identity you get from the insert query.
Sample.
create table #tab1
(
Id bigint identity(1,1) primary key,
a int,
b varchar(50)
)
insert into #tab1(a) values(88);
declare #id1 as bigint set #id1=(select SCOPE_IDENTITY());
update #tab1 set b=cast(id as varchar(max))+cast(a as varchar(max)) where Id=#id1

Alter Column: option to specify conversion function?

I have a column of type float that contains phone numbers - I'm aware that this is bad, so I want to convert the column from float to nvarchar(max), converting the data appropriately so as not to lose data.
The conversion can apparently be handled correctly using the STR function (suggested here), but I'm not sure how to go about changing the column type and performing the conversion without creating a temporary column. I don't want to use a temporary column because we are doing this automatically a bunch of times in future and don't want to encounter performance impact from page splits (suggested here)
In Postgres you can add a "USING" option to your ALTER COLUMN statement that specifies how to convert the existing data. I can't find anything like this for TSQL. Is there a way I can do this in place?
Postgres example:
...ALTER COLUMN <column> TYPE <type> USING <func>(<column>);
Rather than use a temporary column in your table, use a (temporary) column in a temporary table. In short:
Create temp table with PK of your table + column you want to change (in the correct data type, of course)
select data into temp table using your conversion method
Change data type in actual table
Update actual table from temp table values
If the table is large, I'd suggest doing this in batches. Of course, if the table isn't large, worrying about page splits is premature optimization since doing a complete rebuild of the table and its indexes after the conversion would be cheap. Another question is: why nvarchar(max)? The data is phone numbers. Last time I checked, phone numbers were fairly short (certainly less than the 2 Gb that nvarchar(max) can hold) and non-unicode. Do some domain modeling to figure out the appropriate data size and you'll thank me later. Lastly, why would you do this "automatically a bunch of times in future"? Why not have the correct data type and insert the right values?
In sqlSever:
CREATE TABLE dbo.Employee
(
EmployeeID INT IDENTITY (1,1) NOT NULL
,FirstName VARCHAR(50) NULL
,MiddleName VARCHAR(50) NULL
,LastName VARCHAR(50) NULL
,DateHired datetime NOT NULL
)
-- Change the datatype to support 100 characters and make NOT NULL
ALTER TABLE dbo.Employee
ALTER COLUMN FirstName VARCHAR(100) NOT NULL
-- Change datatype and allow NULLs for DateHired
ALTER TABLE dbo.Employee
ALTER COLUMN DateHired SMALLDATETIME NULL
-- Set SPARSE columns for Middle Name (sql server 2008 only)
ALTER TABLE dbo.Employee
ALTER COLUMN MiddleName VARCHAR(100) SPARSE NULL
http://sqlserverplanet.com/ddl/alter-table-alter-column

Create Table Variable (or Temp Table) from an existing Table but with an Extra Column

I want to create a table variable or temporary table, using data from another table but with an extra column.
I know I could use SELECT INTO as follows
SELECT *
INTO #TempTable
FROM Existing_Table
WHERE Section = 2
and then use
ALTER TABLE #TempTable ADD New_Column
And finally
DROP #TempTable
I will then be looping through each row with a dynamically called stored procedure to place values in the new column. Its not a big table.
Is that the best way? My understanding is that I cannot use the above with a table variable.
Thanks
Chris.
Its simpler
SELECT *, cast('hbkkj' as nvarchar(100)) as New_Column
INTO #TempTable
FROM Existing_Table
WHERE Section = 2

Resources