MSSQL to create temporary identity column when selecting from table - sql-server

I have a temporary table that I am selecting all the records from. Say it looks like this:
select * from #mytable
I need to add a temporary identity field to that selection. I've looked around and suggestions include using the IDENTITY(1,1) keyword in some fashion or just creating an auto-incrementing field like this:
row_Number() over (order by col1, col2) as myid
But that doesn't make the column an identity, it just creates a uniquely incremented field.
I know there should be a simple solution to this but I just can't find it.

I just want to know if it's possible to create a key identity field
while doing a select
Only by SELECT INTO:
SELECT IDENTITY(INT,1,1) AS IdentityColumn
,*
INTO #Temp
FROM sys.databases
But not via a plain SELECT, since IDENTITY is nothing more than just a column property that involves proprietary sequence generator and it works only on INSERT

You can use SELECT INTO
SELECT
IDENTITY (INT, 1, 1) AS NEW_ID, *
INTO #tempTable
FROM #mytable
SELECT * FROM #tempTable

Related

Can I grab the inserted IDs when doing multiple inserts?

In my head this sounds improbable, but I'd like to know if I can do it:
INSERT INTO MyTable (Name)
VALUES ('First'),
('Second'),
('Third'),
('Fourth'),
('Fifth');
SELECT INSERTED Name, ID FROM TheAboveQuery
Where ID is an auto-indexed column?
Just to clarify, I want to select ONLY the newly inserted rows.
Starting with SQL Server 2008 you can use OUTPUT clause with INSERT statement
DECLARE #T TABLE (ID INT, Name NVARCHAR(100))
INSERT INTO MyTable (Name)
OUTPUT INSERTED.ID, INSERTED.Name INTO #T
VALUES
('First'),
('Second'),
('Third'),
('Fourth'),
('Fifth');
SELECT Name, ID FROM #T;
UPDATE: if table have no triggers
INSERT INTO MyTable (Name)
OUTPUT INSERTED.ID, INSERTED.Name
VALUES
('First'),
('Second'),
('Third'),
('Fourth'),
('Fifth');
Sure, you can use an IDENTITY property on your ID field, and create the CLUSTERED INDEX on it
ONLINE DEMO
create table MyTable ( ID int identity(1,1),
[Name] varchar(64),
constraint [PK_MyTable] primary key clustered (ID asc) on [Primary]
)
--suppose this data already existed...
INSERT INTO MyTable (Name)
VALUES
('First'),
('Second'),
('Third'),
('Fourth'),
('Fifth');
--now we insert some more... and then only return these rows
INSERT INTO MyTable (Name)
VALUES
('Sixth'),
('Seventh')
select top (##ROWCOUNT)
ID,
Name
from MyTable
order by ID desc
##ROWCOUNT returns the number of rows affected by the last statement executed. You can always see this in the messages tab of SQL Server Management Studio. Thus, we are getting the number of rows inserted and combining it with TOP which limits the rows returned in a query to the specified number of rows (or percentage if you use [PERCENT]). It is important that you use ORDER BY when using TOP otherwise your results aren't guaranteed to be the same
From my previous edited answer...
If you are trying to see what values were inserted, then I assume you are inserting them a different way and this is usually handled with an OUTPUT clause, TRIGGER if you are trying to do something with these records after the insert, etc... more information would be needed.

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.

T-SQL - Validate BLOB / varbinary(max) data

Data is being migrated from Table A to Table B.
Table A has 2 columns - an identity column and a column Content defined as varbinary(max).
How can I validate that Table B has been loaded with correct data for Content column? Is T_SQL's EXCEPT operator good enough? Are there alternate methods?
Thanks
EXCEPT is the tool for this job. Note that unlike other SQL Server set operators, the order makes a difference. Here's one way to validate using EXCEPT:
-- sample data
DECLARE #table1 TABLE (id int identity, content varbinary(max));
DECLARE #table2 TABLE (id int identity, content varbinary(max));
INSERT #table1(content) VALUES (12), (15), (20);
INSERT #table2(content)
SELECT content
FROM #table1;
--solution
(
SELECT id, content FROM #table1
EXCEPT
SELECT id, content FROM #table2
)
UNION ALL
(
SELECT id, content FROM #table2
EXCEPT
SELECT id, content FROM #table1
);

Retrieve original and new identities mapping from SELECT INSERT statement using OUTPUT clause

I have a table with two columns:
CREATE TABLE MyTable(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(100) NOT NULL);
I want to duplicate the data using SELECT INSERT statement:
INSERT INTO MyTable (Name)
SELECT Name FROM MyTable
and here is the trickey part - I want to retrieve a mapping table between the original identity and the new identity:
DECLARE #idsMap TABLE (OriginalId int, NewId int)
I know I suppose to use the OUTPUT clause, but for some reason it doesn't work:
INSERT INTO MyTable (Name)
OUTPUT t.Id, INSERTED.Id INTO #idsMap (OriginalId, NewId)
SELECT Name FROM MyTable t
-- Returns error The multi-part identifier "t.Id" could not be bound.
Related questions:
can SQL insert using select return multiple identities?
Possible to insert with a Table Parameter, and also retrieve identity values?
It can be achieved using MERGE INTO and OUTPUT:
MERGE INTO MyTable AS tgt
USING MyTable AS src ON 1=0 --Never match
WHEN NOT MATCHED THEN
INSERT (Name)
VALUES (src.Name)
OUTPUT
src.Id,
inserted.Id
INTO #idsMap;
How about just adding a new column to MyTable? You can keep it around as long as you need to analysis or whatever. I have to say it seems a bit off to me to create a copy of the table but that is up to you to decide.
Something like this might work for you.
alter table MyTable
add OldID int null;
INSERT INTO MyTable (Name, OldID)
SELECT Name , Id
FROM MyTable t
select * from MyTable

Create new table from Existing table With out identity property to be copied

I am using select * into to create a table from another table and used SET IDENTITY_INSERT ON for newly created table to accept data including identity column.
Now my question is that Is there any way to create a table (say TABLE A) from another existing table (say TABLE B) with out copying identity property of TABLE B to TABLE A.
Of course, let's say TABLEA looks like this:
CREATE TABLE TABLEA (
ID INT PRIMARY KEY IDENTITY(1, 1),
Column1 VARCHAR(50)
)
and let's assume that TABLEB looks the same. If we wanted to move data from TABLEB into TABLEA without moving the identity column we would write this statement:
INSERT INTO TABLEA (Column1)
SELECT Column1 FROM TABLEB
and this will cause every new row in TABLEA to get its own identity value.
But note, you can't issue a SELECT * FROM TABLEB because that would also select the ID column. You have to list out all of the fields you want individually. However, generally speaking, I think a lot of very experienced DBA's and programmers would say that SELECT * FROM Table is really dangerous because if the schema changes everything breaks. You really want to always be specific.
SELECT STUFF((SELECT ', ' + c.name FROM sys.columns c where c.object_id = OBJECT_ID('dbo.TABLE_NAME') and c.is_identity <> 1 FOR XML PATH('')),1, 2, '') AS CSVColumn
This will give you a comma separated list of columns of each table. Copy these statements into notepad to create a script that you can run.

Resources