sql query to insert values to auto increament column - sql

Hi I want to populate value for Auto increament column when insert value for a table from another table. below is query im using and it throws error
create table test12
(
Id int,
name varchar(255),
dept varchar(255)
)
insert into test12 values(1,'f','cs'),(2,'b','cse'),(3,'c','cs'),(4,'d','cse'),(5,'e','cs'),(6,'f',null)
select * from test12
create table test34
(
seq int identity(1,1) not null,
name varchar(255) not null,
dept varchar(255) default('cs')
)
insert into test34(seq,name,dept) values
(1,(select name from test12),
(select case when dept='cse' then 'Y' else 'N' end as dept from test12))
Please let me what is the mistake

you need not to give values for Identity column, it is auto added, just exclude identity column form insert as:
INSERT INTO test34 (name, dept)
SELECT
name,
CASE WHEN dept = 'cse' THEN 'Y' ELSE 'N' END AS dept
FROM test12
If you really want to add Identity values manually try below SET statements.
SET IDENTITY_INSERT test34 ON;
INSERT INTO test34 (seq, name, dept)
SELECT
ID
name,
CASE WHEN dept = 'cse' THEN 'Y' ELSE 'N' END AS dept
FROM test12
SET IDENTITY_INSERT test34 OFF;

You can turn ON or OFF the IDENTITY_INSERT
SET IDENTITY_INSERT test34 ON
insert into test34(seq,name,dept) values
(1,(select name from test12),
(select case when dept='cse' then 'Y' else 'N' end as dept from test12))
SET IDENTITY_INSERT test34 OFF

There is no need to insert value for auto increment column automatically it will generate values.
insert into test34(name,dept)
select name, Case when dept='cse' then 'Y' else 'N' end as dept from test12

Related

Update temp table with identity after insert

I have a temp table that looks like this:
FirstName
LastName
DOB
Sex
Age
ExternalID
In my stored procedure I'm inserting these values into a regular table that has the following structure:
ID identity(1,1)
FirstName
LastName
So, I do this:
Insert into myTable
select FirstName, LastName from TempTable
During the insert I need to insert primary key from main table back into temp table "ExternalID" column. How can this be achieved?
I tried using OUTPUT statement but it only allows to insert to a separate table and then I have no way to map back to temp table
I need to insert generated IDs to column ExternalID in temp table right after the insert. FirstName and LastName are not unique.
One possible solution would be to use loop and insert one row at a time. This way, I can update temp table row with scope_identity(). But I want to avoid using loops.
Try using MERGE instead of INSERT.
MERGE allows you to output a column you didn't insert, such as an identifier on your temp table. Using this method, you can build another temporary table that maps your temp table to the inserted rows (named #TempIdTable in the sample below).
First, give #TempTable its own primary key. I'll call it TempId. I'll also assume you have a column on #TempTable to store the returned primary key from MyTable, ID.
--Make a place to store the associated ID's
DECLARE #TempIdTable TABLE
([TempId] INT NOT NULL
,[ID] INT NOT NULL)
--Will only insert, as 1 never equals 0.
MERGE INTO myTable
USING #TempTable AS tt
ON 1 = 0
WHEN NOT MATCHED
THEN
INSERT ([FirstName]
,[LastName])
VALUE (t.[FirstName]
,t.[LastName])
OUTPUT tt.[TempId], inserted.[ID] --Here's the magic
INTO #TempIdTable
--Associate the new primary keys with the temp table
UPDATE #TempTable
SET [ID] = t.[ID]
FROM #TempIdTable t
WHERE #TempTable.[TempId] = t.[TempId]
I was working on a similar issue and found this trick over here: Is it possible to for SQL Output clause to return a column not being inserted?
Here's the full code I used in my own testing.
CREATE TABLE [MQ]
([MESSAGEID] INT IDENTITY PRIMARY KEY
,[SUBJECT] NVARCHAR(255) NULL);
CREATE TABLE [MR]
([MESSAGESEQUENCE] INT IDENTITY PRIMARY KEY
,[TO] NVARCHAR(255) NOT NULL
,[CC] NVARCHAR(255) NOT NULL
,[BCC] NVARCHAR(255) NOT NULL);
CREATE TABLE #Messages (
[subject] nvarchar(255) NOT NULL
,[to] nvarchar(255) NOT NULL
,[cc] nvarchar(255) NULL
,[bcc] nvarchar(255) NULL
,[MESSAGEID] INT NULL
,[sortKey] INT IDENTITY PRIMARY KEY
);
INSERT INTO #Messages
VALUES ('Subject1','to1','cc1','bcc1', NULL)
,('Subject2','to2', NULL, NULL, NULL);
SELECT * FROM #Messages;
DECLARE #outputSort TABLE (
[sortKey] INT NOT NULL
,[MESSAGEID] INT NOT NULL
,[subject] NVARCHAR(255)
);
MERGE INTO [MQ]
USING #Messages M
ON 1 = 0
WHEN NOT MATCHED
THEN
INSERT ([SUBJECT])
VALUES (M.[subject])
OUTPUT M.[SORTKEY]
,inserted.[MESSAGEID]
,inserted.[SUBJECT]
INTO #outputSort;
SELECT * FROM #outputSort;
SELECT * FROM [MQ];
UPDATE #Messages
SET MESSAGEID = O.[MESSAGEID]
FROM #outputSort O
WHERE #Messages.[sortKey] = O.[sortKey];
SELECT * FROM #Messages;
DROP TABLE #Messages;
As you said, FirstName and LastName are not unique. This means you cannot use a trigger because there can be the same FirstName + LastName so you cannot join on them.
But you can do the inverse thing: first update your temp table ExternalID (I suggest you to use sequence object and just do update #t set ExternalID = next value for dbo.seq1;) and then just insert your rows including ExternalID into myTable. To be able to insert into identity field you can use set identity_insert myTable on or you can re-design your destination table to contain no identity at all as now you use sequence for the same purpose.
We need a unique column for able to make the comparison at the update operation after the insert. That's why we are using ExternalID column temporarily. ExternalID updated by row_nubmber.
;WITH CTE AS
(
SELECT *, RN = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM #TempTable
)
UPDATE CTE SET ExternalID = RN
We are keeping the output of the insert operation in a temp table. The trick is order by with ExternalID, it will help us for making the unique row number for same first and last name
DECLARE #output TABLE (
ID INT,
FirstName VARCHAR(10),
LastName VARCHAR(10))
Insert into #myTable
OUTPUT inserted.ID, inserted.FirstName, inserted.LastName INTO #output(ID, FirstName, LastName)
select FirstName, LastName from #TempTable T
order by ExternalID
For replacing the ExternalID column with inserted id value, we are making comparing with first name, last name and row number.
;WITH TMP_T AS(
SELECT *, RN = ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ExternalID) FROM #TempTable )
,OUT_T AS(
SELECT *, RN = ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ID) FROM #output )
UPDATE TMP_T SET ExternalID = OUT_T.ID
FROM
TMP_T INNER JOIN OUT_T ON
TMP_T.FirstName = OUT_T.FirstName
AND TMP_T.LastName = OUT_T.LastName
AND TMP_T.RN = OUT_T.RN
Sample Data:
DECLARE #TempTable TABLE (
FirstName VARCHAR(10),
LastName VARCHAR(10),
DOB VARCHAR(10),
Sex VARCHAR (10),
Age VARCHAR(10),
ExternalID INT)
INSERT INTO #TempTable VALUES
('Serkan1', 'Arslan1', 'A','M','1',NULL),
('Serkan2', 'Arslan2', 'B','M','1',NULL),
('Serkan3', 'Arslan', 'C','M','1',NULL),
('Serkan3', 'Arslan', 'D','M','1',NULL)
DECLARE #myTable TABLE (
ID INT identity(100,1), -- started from 100 for see the difference
FirstName VARCHAR(10),
LastName VARCHAR(10))
Result:
MyTable
ID FirstName LastName
----------- ---------- ----------
100 Serkan1 Arslan1
101 Serkan2 Arslan2
102 Serkan3 Arslan
103 Serkan3 Arslan
TempTable
FirstName LastName DOB Sex Age ExternalID
---------- ---------- ---------- ---------- ---------- -----------
Serkan1 Arslan1 A M 1 100
Serkan2 Arslan2 B M 1 101
Serkan3 Arslan C M 1 102
Serkan3 Arslan D M 1 103
One way to do this is by duplicating the data into a second temp table like so:
SELECT *
INTO #TEMPTABLE
FROM (VALUES (1, 'Adam'), (2, 'Kate'), (3, 'Jess')) AS X (Id, Name)
SELECT TOP 0 CAST(NULL AS INT) AS IdentityValue, *
INTO #NEWTEMPTABLE
FROM #TEMPTABLE
CREATE TABLE #TABLEFORINSERT (
IdentityColumn INT IDENTITY(1,1),
Id INT,
Name VARCHAR(255)
)
INSERT INTO #TABLEFORINSERT (Id, Name)
OUTPUT INSERTED.IdentityColumn, INSERTED.Id, Inserted.Name INTO #NEWTEMPTABLE
SELECT Id, Name FROM #TEMPTABLE
--New temp table with identity values
SELECT * FROM #NEWTEMPTABLE

Copy data from one table to another in sql server

Consider the below tables.
Table 1:
ID Name Address DateOfBirth DateOfJoin CurrentProject
Table 2:
ID Name DateOfJoin CurrentProject
How do i write a sql server db script to copy data from Table 2 to Table 1 such that, values of Table 2 should overwrite values of Table 1 while merging except for when Table 2 value is null.
In case, the value of table 2 is null, the value of table 1 will take precedence.
Example in the above tables, the values of DataofJoin and CurrentProject should become values in the table 1 for a specific ID. When DateOfJoin and CurrentProject values are null in table 2, then table 1 value will remain as it is. Also, all the IDs that are present in Table 2 but not in Table 1 should be copied to Table 1 after running the script.
BEGIN
CREATE TABLE #Table1(
ID INT,
Name VARCHAR(50),
Address VARCHAR(50),
DateOfBirth DATE,
DateOfJoin DATE,
CurrentProject VARCHAR(50)
)
CREATE TABLE #Table2(
ID INT,
Name VARCHAR(50),
DateOfBirth DATE,
DateOfJoin DATE,
CurrentProject VARCHAR(50)
);
INSERT INTO #Table1 VALUES
(1,'NAME 1','ADDRESS 1','01/01/1990','01/01/2017','PROJECT 1'),
(2,'NAME 1','ADDRESS 2','01/01/1991','01/01/2017','PROJECT 2'),
(3,'NAME 1','ADDRESS 3','01/01/1992','01/01/2017','PROJECT 3'),
(4,'NAME 1','ADDRESS 4','01/01/1993','01/01/2017','PROJECT 4');
INSERT INTO #Table2 VALUES
(1,'NAME 1','01/01/1990','01/01/1988',NULL),
(3,'NAME 3','01/01/1991',NULL,'PROJECT 33'),
(5,'NAME 5','01/01/1986','01/01/2017','PROJECT 5'),
(6,'NAME 6','01/01/1985','01/01/2017','PROJECT 6');
SELECT * FROM #Table1;
SELECT * FROM #Table2;
-- Insert records which exists in Table but not in table 1
INSERT INTO #Table1(ID,Name,DateOfBirth,DateOfJoin,CurrentProject) SELECT * FROM #Table2 WHERE ID not in (SELECT ID FROM #table1)
-- Update matching id records from table 1 with table 2
UPDATE #Table1 SET
Name = CASE WHEN T2.Name='' or T2.Name IS NULL THEN #Table1.Name ELSE T2.Name END,
DateOfBirth = CASE WHEN T2.DateOfBirth='' or T2.DateOfBirth IS NULL THEN #Table1.DateOfBirth ELSE T2.DateOfBirth END,
DateOfJoin = CASE WHEN T2.DateOfJoin='' or T2.DateOfJoin IS NULL THEN #Table1.DateOfJoin ELSE T2.DateOfJoin END,
CurrentProject = CASE WHEN T2.CurrentProject='' or T2.CurrentProject IS NULL THEN #Table1.CurrentProject ELSE T2.CurrentProject END
FROM #Table2 T2 WHERE #Table1.ID= T2.ID
select * from #Table1
drop table #Table1;
drop table #Table2;
END

copy a column from one table to another where table1.col = table2.col

Suppose there are two tables which have the data mentioned in the insert query. There is no foreign key references between the two table.
create table uref.slave (
SLAVE_ID SMALLINT NOT NULL PRIMARY KEY,
DESC VARCHAR(20)
);
INSERT INTO uref.SLAVE values (1, null)
INSERT INTO uref.SLAVE values (2, null)
create table uref.master (
MASTER_ID SMALLINT NOT NULL PRIMARY KEY,
SLAVE_ID SMALLINT,
DESC VARCHAR(20)
);
INSERT INTO uref.MASTER values (1,1,'value1')
INSERT INTO uref.MASTER values (2,2,'value2')
Now I need a query which will copy uref.master.DESC into uref.slave.DESC based on uref.master.SLAVE_ID = uref.slave.SLAVE_ID.
The simplest solution may be to use MERGE.
MERGE INTO uref.SLAVE s
USING uref.MASTER m
ON (s.SLAVE_ID = m.SLAVE_ID)
WHEN MATCHED
THEN UPDATE SET Desc = m.Desc
It could be refined to update only when there is a change to be made
MERGE INTO uref.SLAVE s
USING uref.MASTER m
ON (s.SLAVE_ID = m.SLAVE_ID)
WHEN MATCHED
and ( s.Desc <> m.Desc
or (s.Desc is null and m.Desc is not null)
)
THEN UPDATE SET Desc = m.Desc
UPDATE uref.SLAVE t1
SET Desc =
(
SELECT t2.Desc
FROM uref.MASTER t2
WHERE t1.SLAVE_ID = t2.SLAVE_ID
)
WHERE EXISTS
(
SELECT *
FROM uref.MASTER t2
WHERE t1.SLAVE_ID = t2.SLAVE_ID
AND NOT t1.Desc=t2.Desc
)
AND t1.Desc IS NULL
if sql server, Try below sql: (recheck the table name and fields)
declare #urefSlave table (
SLAVE_ID SMALLINT ,
[DESC] VARCHAR(20)
);
INSERT INTO #urefSlave values (1, null)
INSERT INTO #urefSlave values (2, null)
Declare #urefMaster table (
MASTER_ID SMALLINT,
SLAVE_ID SMALLINT,
[DESC] VARCHAR(20)
);
INSERT INTO #urefMaster values (1,1,'value1')
INSERT INTO #urefMaster values (2,2,'value2')
select * from #urefMaster
select * from #urefSlave
update #urefSlave
set [DESC] = b.[DESC]
from #urefSlave a inner join #urefMaster b on a.SLAVE_ID = b.SLAVE_ID
select * from #urefSlave
REsult:
MASTER_ID SLAVE_ID DESC
--------- -------- --------------------
1 1 value1
2 2 value2
SLAVE_ID DESC
-------- --------------------
1 value1
2 value2
Updated
cannot help much in db2, because i don't have the tools to run the syntax
but from this link db2 update help
you can modify an example in there to meet your requirement:
UPDATE EMPLOYEE EU
SET (EU.SALARY, EU.COMM)
=
(SELECT AVG(ES.SALARY), AVG(ES.COMM)
FROM EMPLOYEE ES
WHERE ES.WORKDEPT = EU.WORKDEPT)
WHERE EU.EMPNO = '000120'
Hope this help.

How to update only one record of duplicates

I want to update status to inactive ( Status=ā€™Iā€™) for all duplicate record except one in sql, default status is active (Status=ā€™Aā€™ ) for all records in table. It should be done without using any inbuilt sql function ex: row_num(), rank(), set rowcount etc.
CREATE TABLE dup_test
(
Emp_ID INT,
Mgr_ID INT,
Status Varchar(5)
)
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (3,3,'A');
Expected Result:
Emp_ID, Mgr_ID, Status
1 1 A
1 1 I
1 1 I
2 2 A
2 2 I
3 3 A
Thanks in advance.
Alter the table and add an identity column (ID):
ALTER TABLE dup_test
ADD id INT NOT NULL IDENTITY (1, 1)
Then something like the following will work:
UPDATE dup_test SET
Status='I'
FROM dup_test dt LEFT OUTER JOIN
(SELECT Emp_ID, MAX(ID) AS maxid
FROM dup_test
GROUP BY Emp_ID) AS dt2 ON dt.Emp_ID=dt2.Emp_ID AND dt.ID=dt2.maxid
WHERE dt2.maxID IS NULL

Prevent insertion of duplicates

I have a table with columns CompanyID, EmployeeCode. EmployeeCode is unique and CompanyID can be repeated. So we can keep a list of employees in Google, Apple etc.
I want a way to ensure that the same employee cannot be added if he/she is already in the database. What would be a good way to do this ? I'd prefer not to create additional columns or tables for this.
Create a UNIQUE constraint on the column where you want to prevent duplicates:
CREATE UNIQUE INDEX [IX_YourTableName_EmployeeCode] ON [YourTableName] (EmployeeCode)
Try this..
Create table UniqueTable
(
CompanyID int,
EmployeeCode int
)
--Insert dummy data
INSERT INTO UniqueTable(EmployeeCode ,CompanyID ) Values(1,200)
--When are Going to insert duplicate Ecmployeecode '1' then it will not insert data into table
INSERT INTO UniqueTable(EmployeeCode ,CompanyID )
Select 1,200 From UniqueTable t1
Left join UniqueTable t2 on 1=t2.EmployeeCode
WHERE t2.EmployeeCode IS NULL
--We are Going to insert different Ecmployeecode '2' it will insert into table
INSERT INTO UniqueTable(EmployeeCode ,CompanyID )
Select 2,300 From UniqueTable t1
Left join UniqueTable t2 on 2=t2.EmployeeCode
WHERE t2.EmployeeCode IS NULL
Try this
Create PROCEDURE [dbo].[sp_Emp_Insert]
#EmployeeCode nvarchar(50)
As
Begin
if Not Exists (select EmployeeCode from YOUR_TABlE where EmployeeCode =#EmployeeCode )
Begin
Insert QUERY
End
else
Return 0
End
End