Custom value for Identity Column - sql-server

Suppose there is a table containing records of students from roll no 1 to 10. If we delete the record at roll number 4&5. Is it possible to enter new records at 4&5? Can anybody please help.

Yes, you can do that using SET IDENTITY_INSERT, given that for the StudentRollID column, IDENTITY(1, 1) is specified. This means that as each row is inserted into the table, SQL Server will automatically increment this value by 1 starting with the number 1.
-- 1 - Retrieve all of the data
-- from the dbo.Student table
SELECT *
FROM dbo.Student;
GO
-- 2 - Delete a single record
DELETE
FROM dbo.Student
WHERE StudentRollID = 4;
GO
-- 3 - Verify the record was deleted
SELECT *
FROM dbo.Student;
GO
-- 4 - Insert the deleted record
-- Insert fails
INSERT INTO [dbo].[Student]
([StudentRollID]
,[FirstName]
,[LastName]
,[CreateDate])
VALUES
(4
,'Bar'
,'Foo'
,'2014-12-04');
GO
-- 5 - Insert the deleted record
-- Insert succeeds
SET IDENTITY_INSERT [dbo].[Student] ON
INSERT INTO [dbo].[Student]
([StudentRollID]
,[FirstName]
,[LastName]
,[CreateDate])
VALUES
(4
,'Bar'
,'Foo'
,'2014-12-04');
SET IDENTITY_INSERT [dbo].[Student] OFF
GO
-- 6 - Verify the data
SELECT *
FROM dbo.Student;
GO

Related

Capture IDENTITY column value during insert and use as value for another column in same transaction

While performing an insert to a table which has an IDENTITY column, is it possible to use the IDENTITY value as the value for another column, in the same transaction?
For example:
DECLARE #TestTable TABLE
(
PrimaryId INT NOT NULL IDENTITY(1, 1),
SecondaryId INT NOT NULL
);
INSERT INTO #TestTable (SecondaryId)
SELECT
SCOPE_IDENTITY() + 1; -- set SecondaryId = PrimaryId + 1
SELECT * FROM #TestTable;
Expected:
| PrimaryId | SecondaryId |
+-----------+-------------+
| 1 | 2 |
I thought I might be able to achieve this with the SCOPE_IDENTITYor ##IDENTITY system functions, but unfortunately this does not work, as it is NULL at the time the transaction is executed.
Cannot insert the value NULL into column 'SecondaryId', table '#TestTable'; column does not allow nulls. INSERT fails.
I know I could use a computed column for this example, but I'm curious if what I'm trying to do is even possible.
Could you change your approach and use a SEQUENCE instead of an IDENTITY column?
CREATE SEQUENCE TestSequence
START WITH 1
INCREMENT BY 1 ;
GO
CREATE TABLE TestTable (PrimaryId INT NOT NULL DEFAULT NEXT VALUE FOR TestSequence, SecondaryId INT NOT NULL);
GO
INSERT INTO TestTable (
SecondaryId
)
SELECT NEXT VALUE FOR TestSequence + 1; -- set SecondaryId = PrimaryId + 1;
GO 3
SELECT * FROM TestTable;
GO
DROP TABLE TestTable;
DROP SEQUENCE TestSequence;
I would go with a trigger, this should also work for multi row inserts, You will need to remove the not null for SecondaryID, not sure if that's acceptable.
create trigger trg_TestTable
on dbo.TestTable
after insert
AS
BEGIN
update TestTable
set SecondaryId = i.PrimaryId
from inserted i
join TestTable a
on i.PrimaryId = a.PrimaryId;
END
GO
One thing you could do is use the OUTPUT INSERTED option of the INSERT COMMAND to capture the IDENTITY.
In this example the IDENTITY field is ScheduleID.
CREATE PROCEDURE dbo.spScheduleInsert
( #CustomerID int,
#ItemID int,
#StartDate Date,
#TimeIn DateTime,
#TimeOut DateTime,
#ReturnIdentityValue int OUTPUT )
AS
BEGIN
DECLARE #TempScheduleIdentity table ( TempScheduleID int )
INSERT INTO Schedule ( CustomerID,ItemID,StartDate,TimeIn,TimeOut )
OUTPUT INSERTED.ScheduleID into #TempScheduleIdentity
VALUES (#CustomerID,#ItemID,#StartDate,#TimeIn,#TimeOut)
SELECT #ReturnIdentityValue = (SELECT TempScheduleID FROM #TempScheduleIdentity)
END
Once you have the #ReturnIdentityValue...you could then update the records other field with the value.

check constraints multiple options

i have a table with a column i want to apply constraints too but it has two variables.
Table is called: MyOrderTable
Column is called : Orderref
example data would be:
OrderRef
80
75
110
110
80
110
What i want to do is create a constraint where if the value of OrderRef is below 100 it cannot be a duplicate number to any exisiting value in that column but if it is above 100 it can be a duplicate - can this be done - assume i will need a function to do this?
tried the following but it did not work:
ALTER TABLE MYORDERTABLE
ADD CONSTRAINT TAS_CK
CHECK (
MYORDERTABLE_CHECK(ORDERREF) = 1)
CREATE FUNCTION MYORDERTABLE_CHECK (
#ORDERREF INT
)
RETURNS TINYINT
AS
BEGIN
DECLARE #RESULT TINYINT
IF EXISTS(SELECT * FROM MYORDERTABLE WHERE ORDERREF < 100)
SET #RESULT= 1
ELSE
SET #RESULT= 0
RETURN #RESULT
END
i was still allowed to enter data under 100 for the orderref column
The CHECK fires up AFTER the row has been inserted into the table, not
before.
here in comments noticed about that
So you should use instead of insert trigger
use tempdb
go
create table t (
id int not null identity(1,1),
orderref int not null
)
go
create trigger tr_t on t instead of insert
as
begin
if exists(
select 1
from inserted i
join t on i.orderref < 100 and i.orderref = t.orderref
)
begin
raiserror('orderref < 100 already exists', 16, 1)
return
end
insert t(orderref)
select orderref from inserted
end
go
insert t (orderref) values (1)
insert t (orderref) values (2)
insert t (orderref) values (100)
insert t (orderref) values (100)
insert t (orderref) values (5)
insert t (orderref) values (5) -- error here
select * from t

Creating a temporary table within a TRIGGER with GROUP BY

I need to create and use a temporary table with GROUP BY clause within a trigger, but I'm having difficulties doing so.
My attempt:
Here I'm trying to use two temporary tables which are dropped after the trigger reach an end.
First I create a #Temptable and the trigger.
CREATE TABLE #TempTable (admID smallint, diagID smallint);
CREATE TRIGGER tr_newTest
ON Adm_Diag
FOR INSERT
AS
BEGIN
...
END
Since the table inserted only contains rows for a current INSERT and UPDATE statements I'm passing several INSERT and UPDATE statements to #TempTable.
DECLARE #admID smallint
SELECT #admID = Adm_ID
FROM inserted
DECLARE #diagID smallint
SELECT #diagID=Diag_ID
FROM inserted
INSERT INTO #TempTable VALUES (#admID, #diagID)
Now with this data I want to create a temporary table that groups the rows of #TempTable:
SELECT *
INTO #TempGroupTable
FROM
(
SELECT admID, COUNT(*) as Diag
FROM #TempTable
GROUP BY admID
) t1
WHERE Diag > 2
The whole script
CREATE TABLE #TempTable (admID smallint, diagID smallint);
CREATE TRIGGER tr_newTest
ON Adm_Diag
FOR INSERT
AS
BEGIN
DECLARE #admID smallint
SELECT #admID = Adm_ID
FROM inserted
DECLARE #diagID smallint
SELECT #diagID=Diag_ID
FROM inserted
INSERT INTO #TempTable VALUES (#admID, #diagID)
-- Below I'm tring to create #TempGroupTable
SELECT *
INTO #TempGroupTable
FROM
(
SELECT admID, COUNT(*) as Diag
FROM #TempTable
GROUP BY admID
) t1
WHERE Diag > 2
END
After executing the trigger I get an error:
Msg 208, Level 16, State 0, Line 41 Invalid object name
'#TempGroupTable'.
How can I create #TempGroupTable?
Not quote sure what you are trying to do but would a global temporary tables which starts with ## work for you? So make the #TempGroupTable into ##TempGroupTable?
Why not dispense with all the overhead of temp tables and variables? Try:
CREATE TRIGGER tr_newTest
ON Adm_Diag
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO Adm_Diag (adminID, Diag)
SELECT admID, COUNT(*) as Diag
FROM inserted
GROUP BY admID
END

Insert next records

I have requirement like, I have to insert the records whenever for one BID, one SID, if the execdate and stopbilldate exist, then I need to insert new record with NULL as Stopbilldate
sample example is as follows:
Sno BID SID LID Comapny Execdate StopBilldate
5 BLDG100 C 6500 Cole 1/5/2012 5/29/2012
6 BLDG100 C 000000 Vacant 5/30/2012 NULL
You can do this with a TRIGGER on your table. A trigger is a kind of stored procedure that will execute when an event occurs.
Here is a sample of what you could place on your table:
CREATE TRIGGER [trg_yourTable]
ON [yourTable]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
INSERT INTO yourTable (bid, sid, lid, company, execdate, stopbilldate)
SELECT i.bid, i.sid, 0, 'Vacant', DATEADD(day, 1, i.stopbilldate), null
FROM inserted i
WHERE i.bid is not null
and i.sid is not null
END
When you INSERT data in the table, this will run and INSERT the additional row that you want added to the table.

SQL Server Identity Column Insert Fails

Hi guys I just have one quick question:
what happens when an insert statement fails on an identity column?
Is it possible that say for example that if I insert a row with an identity column, that identity column will be 1, and insert again but that fails and does not insert and data. Then try to insert again and that identity for that row is now 3?
Any advice will be much appreciated.
Thanks.
It depends on what the cause of the fail on data insert is. If for example the values are invalid (wrong types), then the identity value won't be incremented. However, if the first insert is successful, but is then removed (by a transaction failed and rolled back), then the identity value IS incremented.
-- Next identity value = 1
INSERT INTO Table1 (
field1)
VALUES ('a')
-- Next identity value = 2
BEGIN TRAN
INSERT INTO Table1 (
field1)
VALUES ('b')
-- Next identity value = 3
ROLLBACK TRAN
-- Next identity value = 3, although the insertion was removed.
INSERT INTO Table1 (
field1)
VALUES ('c')
-- Next identity value = 4
The first insert will have identity column value = 1, the second one fails, and the third one will have identity column value = 3.
Just because a column has an IDENTITY specification doesn't necessarily mean it's unique.
If you don't have a unique constraint (or a primary key constraint) on that column, you can definitely insert multiple identical values into rows for that column.
Typically, though, your IDENTITY columns will be the primary key (or at least have a UNIQUE constraint on them) and in that case, attempting to insert a value that already exists will result in an error ("unique constraint violation" or something like that)
In order to be able to insert specific values into an IDENTITY column you need to have the SET IDENTITY_INSERT (table name) ON - otherwise, SQL Server will prevent you from even specifying values for an IDENTITY column.
For illustration - try this:
-- create demo table, fill with values
CREATE TABLE IdentityTest (ID INT IDENTITY, SomeValue CHAR(1))
INSERT INTO IdentityTest(SomeValue) VALUES('A'), ('B'), ('C')
SELECT * FROM IdentityTest -- Output (1)
-- insert duplicate explicit values into table
SET IDENTITY_INSERT IdentityTest ON
INSERT INTO IdentityTest(ID, SomeValue) VALUES(1, 'Z'), (2, 'Y')
SET IDENTITY_INSERT IdentityTest OFF
SELECT * FROM IdentityTest -- Output (2)
-- add unique constraint
TRUNCATE TABLE dbo.IdentityTest
ALTER TABLE IdentityTest ADD CONSTRAINT UX_ID UNIQUE(ID)
INSERT INTO IdentityTest(SomeValue) VALUES('A'), ('B'), ('C')
SET IDENTITY_INSERT IdentityTest ON
INSERT INTO IdentityTest(ID, SomeValue) VALUES(1, 'Z') -- error message (3)
DROP TABLE IdentityTest
Output (1):
ID SomeValue
1 A
2 B
3 C
Output (2):
ID SomeValue
1 A
2 B
3 C
1 Z
2 Y
Error Message (3):
Msg 2627, Level 14, State 1, Line 9
Violation of UNIQUE KEY constraint 'UX_ID'. Cannot insert duplicate key in object 'dbo.IdentityTest'. The duplicate key value is (1).
One way is to prevent the insert if the row already exists.
IF (Not Exists (Select ID From Table Where SomeCol = #SomeVal)
Insert Into Table Values (#SomeVal)

Resources