Ok so this is the query I have...I just added the ACCOUNTID and the #accountID portion which is obviosly not working
INSERT INTO Leads (
LEADID,
CREATEUSER,
CREATEDATE,
FIRSTNAME,
MODIFYDATE,
ACCOUNTID
)
SELECT
'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20))
,'U6UJ9000S'
,CURRENT_TIMESTAMP
,'U6UJ9000S'
,name
,#accountID
FROM Temp
What I am trying to do is do an insert into the account table first and get that id and add the insert id to this insert into the leads table. Is that even possible
SO basically for each record in the Temp table i need to insert a record in the account table with no values just need the account_id so when i insert in the leads table i have the account id to make that insert
Setup:
USE TempDB;
GO
CREATE TABLE dbo.Leads
(
LeadID VARCHAR(64),
CreateUser VARCHAR(32),
CreateDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FirstName VARCHAR(32),
AccountID INT
);
CREATE TABLE dbo.Accounts
(
AccountID INT IDENTITY(1,1),
name VARCHAR(32) /* , ... other columns ... */
);
CREATE TABLE dbo.Temp(name VARCHAR(32));
INSERT dbo.Temp SELECT 'foo'
UNION SELECT 'bar';
Query:
INSERT dbo.Accounts
(
name
)
OUTPUT
'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)),
'U6UJ9000S',
CURRENT_TIMESTAMP,
inserted.name,
inserted.AccountID
INTO dbo.Leads
SELECT name
FROM dbo.Temp;
Check:
SELECT * FROM dbo.Accounts;
SELECT * FROM dbo.Leads;
Cleanup:
USE tempdb;
GO
DROP TABLE dbo.Temp, dbo.Accounts, dbo.Leads;
The problem you will probably end up hitting in practice with Aaron's use of composable DML is that chances are in reality you will have an FK defined to constrain Leads(AccountId) to a valid value in which case you will hit the error.
The target table 'dbo.Leads' of the OUTPUT INTO clause cannot be on
either side of a (primary key, foreign key) relationship. Found
reference constraint 'FK_foo'.
To avoid this issue you can use
INSERT INTO dbo.Leads
EXEC('
INSERT INTO dbo.Accounts
OUTPUT
''Q'' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)),
''U6UJ9000S'',
CURRENT_TIMESTAMP,
inserted.name,
inserted.AccountID
SELECT name
FROM dbo.Temp;
')
It is not working because you are inserting 6 values but you are specifying only 5 columns:
These are 5 columns:
LEADID,
CREATEUSER,
CREATEDATE,
FIRSTNAME,
ACCOUNTID
Ant these are 6 values:
'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20))
,'U6UJ9000S'
,CURRENT_TIMESTAMP
,'U6UJ9000S'
,name
,#accountID
I don't know where you get the #accountID from, but I imagine you define it somewhere else above.
You can get #accountID as follows, after you do the insert to the Account table:
select #accountID=scope_identity()
And then execute the insert into the Leads table.
UPDATE: EXAMPLE:
declare #accountID int
INSERT INTO Account (col1,col2,col...)
values ('foo','bar','baz')
select #accountID=SCOPE_IDENTITY()
INSERT INTO Leads (
LEADID,
CREATEUSER,
CREATEDATE,
FIRSTNAME,
ACCOUNTID
)
values
(
'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)) --leadid
,'U6UJ9000S' --createuser
,CURRENT_TIMESTAMP --createdate
,t.name --firstname
,#accountID --accountID
)
set a variable to Scope_identity() (which returns the last id that was created) and use that
With SQL Server 2005 or higher you can use the OUTPUT clause.
CREATE TABLE #Inserted (AccountID, AccountName)
INSERT Account (AccountName)
OUTPUT Inserted.AccountID, Inserted.AccountName
INTO #Inserted
SELECT AccountName
FROM Temp
INSERT Leads (
LEADID,
CREATEUSER,
CREATEDATE,
FIRSTNAME,
ACCOUNTID
)
SELECT
'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20))
,'U6UJ9000S'
,CURRENT_TIMESTAMP
,t.name
,i.AccountID
FROM Temp AS t
JOIN #Inserted AS i ON t.AccountName= i.AccountName
You can declare an variable, set it to the desired id and the use the variable in the insert.
Related
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
I am trying to write a query that will insert a group of people into a table if that person does not exist. For example, I have table full of people and I need to add more people into the database and I don't know if they are already there. I do know that the social security number (ssn) will never be the same for two people. Could a query be used to check if the ssn is in the table and if not insert the person into the table? If the ssn is in the table then go to the next person and check?
I was thinking about using a stored procedure, but I do not have any rights to create a store procedure.
You can insert your data into a table variable or temp table and then INSERT INTO table from temp table where it does not exists in your table.
DECLARE #Inserted AS TABLE
(
NAME VARCHAR(50)
,SSN DECIMAL(10, 0)
)
INSERT INTO #Inserted
( NAME, SSN )
VALUES ( 'Bob', 123456789 )
, ( 'John', 123546789 )
, ( 'James', 123456798 )
INSERT INTO MyTable
SELECT *
FROM #Inserted AS i
LEFT OUTER JOIN MyTable AS m
ON i.SSN = m.SSN
WHERE m.SSN IS NULL
Here are a couple ideas to get you started. I use MERGE a lot because it offers so much control. You could also look into the IN clause as part of a WHERE predicate in the INSERT SELECT statement.
MERGE
DECLARE #PERSONTABLE TABLE (ID INT PRIMARY KEY IDENTITY(1,1), FirstName VARCHAR(max))
INSERT INTO #PERSONTABLE (FirstName) VALUES ('Bill'),('Sally'),('Bob')
DECLARE #NEWPEOPLE TABLE (FirstName VARCHAR(max))
INSERT INTO #NEWPEOPLE (FirstName) VALUES ('Jim'), ('Sally')
--MERGE
MERGE INTO #PERSONTABLE AS T
USING #NEWPEOPLE AS S
ON (T.FirstName = S.FirstName)
WHEN NOT MATCHED BY TARGET THEN
INSERT (FirstName) VALUES (S.FirstName);
SELECT * FROM #PERSONTABLE
EXCEPT
DECLARE #PERSONTABLE TABLE (ID INT PRIMARY KEY IDENTITY(1,1), FirstName VARCHAR(max))
INSERT INTO #PERSONTABLE (FirstName) VALUES ('Bill'),('Sally'),('Bob')
DECLARE #NEWPEOPLE TABLE (FirstName VARCHAR(max))
INSERT INTO #NEWPEOPLE (FirstName) VALUES ('Jim'), ('Sally')
--EXCEPT
INSERT INTO #PERSONTABLE (FirstName)
SELECT FirstName FROM #NEWPEOPLE
EXCEPT
SELECT FirstName FROM #PERSONTABLE
SELECT * FROM #PERSONTABLE
You could do it like this if the new people are in another table. If not, then use Vladimir's solution.
INSERT INTO People(ssn, firstname, lastname)
SELECT ssn, firstname, lastname
FROM newpeople
WHERE ssn not in (select ssn from people )
INSERT INTO People(ssn, firstname, lastname)
SELECT np.ssn, np.firstname, np.lastname
FROM newpeople np
LEFT JOIN People p on np.ssn = p.ssn
WHERE p.ssn IS NULL
Here's another option I use a lot. Normally joins are better than sub-selects... if the joined table value is null you know you don't have a hit in the joined table.
I'm trying to get the ID of each row inserted from a mass insert and create a mapping table with an ID from my temp table #InsertedClients. I'm using the same temp table for the initial insert but the PDATClientID is not part of the insert. I can't seem to figure out how to do this correctly. When I inserting into the Client_Mapping table using SCOPE_IDENTITY it only grabs the ID from the first insert and puts it along with all of my PDATClientIDs. After doing a lot of Googling I believe I should be using OUTPUT, but can't seem to figure how to put the INSERTED.CLID for each record together with each PDATClientID. I should also say that I can't use a cursor there are too rows. Any help is greatly appreciated!
IF NOT EXISTS (
SELECT ID
FROM sysobjects
WHERE id = object_id(N'[Client_Mapping]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1
)
CREATE TABLE [Client_Mapping] (
ClientMappingID INT Identity(1, 1) NOT NULL
,PDATClientID INT NOT NULL
,CLID INT NOT NULL
,AUDITDATE DATETIME NOT NULL
,CONSTRAINT [PK_Client_Mapping] PRIMARY KEY (ClientMappingID)
)
-- Begin Inserts
SELECT
First_Name
,Middle_Name
,Last_Name
,CONVERT(DATETIME, Date_Of_Birth) AS DOB
,a.Address_Line as Address1
,a.Address_Line_2 as Address2
,a.Zip_Code as ZipCode -- ??? Do I need to account for zipcode + 4
,REPLACE(REPLACE(REPLACE(cphp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS HomePhone
,REPLACE(REPLACE(REPLACE(cpcp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS CellPhone
,cpem.Number_Or_Address AS EMAIL
,c.Client_ID as PDATClientID
,c.Action AS [ClientAction]
,ca.Action as [ClientAddressAction]
,a.Action AS [AddressAction]
,cphp.Action AS [HomePhoneAction]
,cpcp.Action AS [CellPhoneAction]
,cpem.Action AS [EmailAction]
INTO #InsertClients
FROM Client c
LEFT JOIN Client_Address ca ON ca.Client_ID = c.Client_ID
LEFT JOIN Address a ON a.Address_ID = ca.Address_ID
LEFT JOIN Client_Phone cphp ON cphp.Client_ID = c.Client_ID
AND cphp.Phone_Email_Type = 'HP'
AND cphp.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
LEFT JOIN Client_Phone cpcp ON cpcp.Client_ID = c.Client_ID
AND cpcp.Phone_Email_Type = 'CP'
AND cpcp.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
LEFT JOIN Client_Phone cpem ON cpem.Client_ID = c.Client_ID
AND cpem.Phone_Email_Type = 'EM'
AND cpem.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
where c.action ='I'
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[Clients] (
[FName]
,[MiddleInitial]
,[LName]
,[DOB]
,[Address1]
,[Address2]
,[ZipCode]
,[HomePhone]
,[CellPhone]
,[Email]
,[AuditStaffID]
,[AuditDate]
,[DateCreated]
)
Select
First_Name
,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END
,Last_Name
,DOB
,Address1
,Address2
,ZipCode
,HomePhone
,CellPhone
,EMail
,496 AS [AuditStaffID]
,CURRENT_TIMESTAMP AS [AuditDate]
,CURRENT_TIMESTAMP AS [DateCreated]
FROM
#InsertClients
Where
[ClientAction] = 'I'
INSERT INTO [Client_Mapping]
(
PDATClientID
,CLID
,AUDITDATE
)
SELECT
PDATClientID
,SCOPE_IDENTITY()
,CURRENT_TIMESTAMP
FROM #InsertClients
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage
END CATCH
you have a hell of a code in your question I can explain you in few line how you can retrieve all the inserted ids.
Yes SCOPE_IDENTITY() gives you the last IDENTITY value generated by the identity column. In you case you will need to use a table variable to get all the generated Identity values during your insert
/* Declare a table Vairable */
DECLARE #NewValues TABLE (IDs INT);
/* In Your Insert Statement use OUTPUT clause */
INSERT INTO Table_Name (Column1,Column2,Column3,....)
OUTPUT inserted.Identity_Column INTO #NewValues (IDs)
SELECT Column1,Column2,Column3,....
FROM Table_Name2
/* Finally Select values from your table variable */
SELECT * FROM #NewValues
Your Query
In your case your insert statement should look something like ...
INSERT INTO [dbo].[Clients] (
[FName]
,[MiddleInitial]
,[LName]
,[DOB]
,[Address1]
,[Address2]
,[ZipCode]
,[HomePhone]
,[CellPhone]
,[Email]
,[AuditStaffID]
,[AuditDate]
,[DateCreated]
)
OUTPUT inserted.[FName], inserted.[MiddleInitial] ,.... INTO #TableVarible(First_Name,[MiddleInitial].....)
Select
First_Name
,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END
,Last_Name
,DOB
,Address1
,Address2
,ZipCode
,HomePhone
,CellPhone
,EMail
,496 AS [AuditStaffID]
,CURRENT_TIMESTAMP AS [AuditDate]
,CURRENT_TIMESTAMP AS [DateCreated]
FROM
#InsertClients
Where
[ClientAction] = 'I'
Solved the problem by using this example found here: http://sqlserverplanet.com/tsql/match-identity-columns-after-insert. The example from that site is below.
-- Drop temp tables if they already exist
IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source;
IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target;
IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref;
GO
-- Create the temp tables
CREATE TABLE #source (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT);
CREATE TABLE #target (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT);
CREATE TABLE #xref (ROW INT PRIMARY KEY IDENTITY(1, 1), source_id INT, target_id INT);
GO
-- If xref table is being reused, make sure to clear data and reseed by truncating.
TRUNCATE TABLE #xref;
-- Fill source table with dummy data (even numbers)
INSERT INTO #source (DATA)
SELECT 2 UNION SELECT 4 UNION SELECT 6 UNION SELECT 8;
GO
-- Fill target table with dummy data (odd numbers) to simulate existing records
INSERT INTO #target (DATA)
SELECT 1 UNION SELECT 3 UNION SELECT 5;
GO
-- Insert source table data into target table. IMPORTANT: Inserted data must be sorted by the source table's primary key.
INSERT INTO #target (DATA)
OUTPUT INSERTED.id INTO #xref (target_id)
SELECT DATA
FROM #source
ORDER BY id ASC;
GO
-- Update the xref table with the PK of the source table. This technique is used for data not captured during the insert.
;WITH src AS (SELECT id, ROW = ROW_NUMBER() OVER (ORDER BY id ASC) FROM #source)
UPDATE x
SET x.source_id = src.id
FROM #xref AS x
JOIN src ON src.ROW = x.ROW;
GO
-- Verify data
SELECT * FROM #source;
SELECT * FROM #target;
SELECT * FROM #xref;
GO
-- Clean-up
IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source;
IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target;
IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref;
GO
I just wondering how to select values from table B according to table A col values; The idea is quite simple but I have confused a little
code like a
DECLARE #A TABLE
(
id INT NOT NULL,
name VARCHAR(50)
);
INSERT #A SELECT id,name FROM table1 WHERE id>10
DECLARE #B TABLE
(
address VARCHAR(255),
city VARCHAR(128)
);
INSERT #b SELECT address,city FROM table2
WHERE id=(SELECT id FROM #A)
Change "id =" to "id IN"
WHERE id=(SELECT id FROM #A)
to
WHERE id IN (SELECT id FROM #A)
i want to delete duplicate rows from my table on the basis of category ID, but don't want to delete all, i want to left one rows if there are more than one row with the same category ID.
this is my query i am making i need to change it.
delete from twinhead_tblcategory where categoryid in (select categoryid from twinhead_tblcategory group by categoryid having count(categoryid) > 1 )
For SQL Server you can do it:
WITH MyTableCTE (CategoryId, RowNumber)
AS
(
SELECT CategoryId, ROW_NUMBER() OVER (ORDER BY CategoryId) AS 'RowNumber'
FROM MyTable
)
Delete From MyTableCTE Where RowNumber > 1
Do a select distinct into a new table, delete the old one and rename the new one into old table name.
If your rows have a distinct id column, then this should work:
DELETE t1 FROM your_table t1, your_table t2
WHERE t1.column1 = t2.column1 AND t1.column2 = t2.column2
AND ... /* check equality of all relevant columns */
AND t1.id < t2.id
Check here for sql server - http://support.microsoft.com/kb/139444 - that should get you started.
This is probably heavy-handed but perhaps you could select distinct * into a temp table, then truncate the table, then insert into the table the contents of the temp table. Foreign key constraints may prevent this, though.
For SqlServer, you could use a cursor to loop through all items, ordered by that categoryID.
Is the current ID the same as the previous one? Then delete it, see example C of this article.
Else remember the ID for the next round.
You have several way for delete duplicate rows.
for my solutions , first consider this table for example
CREATE TABLE #Employee
(
ID INT,
FIRST_NAME NVARCHAR(100),
LAST_NAME NVARCHAR(300)
)
INSERT INTO #Employee VALUES ( 1, 'Vahid', 'Nasiri' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 4, 'name3', 'lname3' );
First solution : Use another table for duplicate rows.
SELECT DISTINCT *
FROM #Employee
SELECT * INTO #DuplicateEmployee
FROM #Employee
INSERT #DuplicateEmployee
SELECT DISTINCT *
FROM #Employee
BEGIN TRAN
DELETE #Employee
INSERT #Employee
SELECT *
FROM #DuplicateEmployee
COMMIT TRAN
DROP TABLE #DuplicateEmployee
SELECT DISTINCT *
FROM #Employee
Second solution :
SELECT DISTINCT * FROM #Employee
SELECT * INTO #DuplicateEmployee FROM #Employee
INSERT #DuplicateEmployee
SELECT ID,
FIRST_NAME,
LAST_NAME
FROM #Employee
GROUP BY
ID,FIRST_NAME,LAST_NAME
HAVING COUNT(*) > 1
BEGIN TRAN
DELETE #Employee
FROM #DuplicateEmployee
WHERE #Employee.ID = #DuplicateEmployee.ID
AND #Employee.FIRST_NAME = #DuplicateEmployee.FIRST_NAME
AND #Employee.LAST_NAME = #DuplicateEmployee.LAST_NAME
INSERT #Employee
SELECT *
FROM #DuplicateEmployee
COMMIT TRAN
DROP TABLE #DuplicateEmployee
SELECT DISTINCT * FROM #Employee
teared solution : use rowcount
SELECT DISTINCT *
FROM #Employee
SET ROWCOUNT 1
SELECT 1
WHILE ##rowcount > 0
DELETE #Employee
WHERE 1 < (
SELECT COUNT(*)
FROM #Employee a2
WHERE #Employee.ID = a2.ID
AND #Employee.FIRST_NAME = a2.FIRST_NAME
AND #Employee.LAST_NAME = a2.LAST_NAME
)
SET ROWCOUNT 0
SELECT DISTINCT *
FROM #Employee
Fourth solution : use Analytical Functions
SELECT DISTINCT *
FROM #Employee;
WITH #DeleteEmployee AS (
SELECT ROW_NUMBER()
OVER(PARTITION BY ID, First_Name, Last_Name ORDER BY ID) AS
RNUM
FROM #Employee
)
DELETE
FROM #DeleteEmployee
WHERE RNUM > 1
SELECT DISTINCT *
FROM #Employee
Fifth solution : Use identity field
SELECT DISTINCT *
FROM #Employee;
ALTER TABLE #Employee ADD UNIQ_ID INT IDENTITY(1, 1)
DELETE
FROM #Employee
WHERE UNIQ_ID < (
SELECT MAX(UNIQ_ID)
FROM #Employee a2
WHERE #Employee.ID = a2.ID
AND #Employee.FIRST_NAME = a2.FIRST_NAME
AND #Employee.LAST_NAME = a2.LAST_NAME
)
ALTER TABLE #Employee DROP COLUMN UNIQ_ID
SELECT DISTINCT *
FROM #Employee
and end of all solution use this command
DROP TABLE #Employee
Source of my answer is this site