Insert new row with current Identity as value - sql

Don't ask me why, but I want to have a column where Identity is stored as varchar. Is it possible to assign this during creation or do I need to Scope Identity and Update?
EDIT: To clarify this is an existing table that I cannot amend in any way. I just want to insert new rows.
Normally I would do this:
INSERT INTO [User]
(
-- id -- this column value is auto-generated,
useridcr,
dtcr,
varcharid
)
VALUES
(
25,
'2015-01-30 00:00:00.000'
''
)
SET #id = SCOPE_IDENTITY()
UPDATE [User]
SET
varcharid = #id
WHERE id = #id
But is it possible to know the value of new identity before it's created? So I could use the value in the insert statement. Like this:
INSERT INTO [User]
(
-- id -- this column value is auto-generated,
useridcr,
dtcr,
varcharid
)
VALUES
(
25,
'2015-01-30 00:00:00.000'
[generatedID]
)
Thank you

Use computed column:
CREATE TABLE [User]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
useridcr INT,
dtcr INT ,
varcharid AS CAST(id AS VARCHAR(10))
);
LiveDemo
Then you don't need to catching last generating value and updating data.
Alternatively you can use VIEW:
CREATE VIEW vw_user
AS
SELECT *,
[varcharid] = CAST(id AS VARCHAR(10))
FROM [User]
EDIT:
You can use trigger for that:
CREATE TRIGGER trg_User
ON [User]
AFTER UPDATE, INSERT
AS
BEGIN
UPDATE u
SET varcharid = CAST(i.id AS VARCHAR(100))
FROM [User] u
JOIN inserted i
ON u.id = i.id;
END
GO
SqlFiddleDemo

Related

Using the identity column to add a value to a computed column

At times I need to store a temporary value to a field. I have a stored procedure that adds it using:
Insert new record first then
SELECT #Record_Value = SCOPE_IDENTITY();
UPDATE ADMIN_Publication_JSON
SET NonPubID = CAST(#Record_Value as nvarchar(20)) + '_tmp'
WHERE RecID = #Record_Value
It simply takes the identity value and adds an '_tmp' to the end. Is there a way that I can create a default value in the table that would do that automatically if I did not insert a value into that field?
The NonPubID column is just a NVARCHAR(50).
Thanks
You could write a trigger, that replaces NULL with that string upon INSERT.
CREATE TRIGGER admin_publication_json_bi
ON admin_publication_json
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE apj
SET apj.nonpubid = concat(convert(varchar(20), i.id), '_tmp')
FROM admin_publication_json apj
INNER JOIN inserted i
ON i.id = apj.id
WHERE i.nonpubid IS NULL;
END;
db<>fiddle
Downside: You cannot explicitly insert NULLs for that column, should that be desired.
Check out NewKey col below:
CREATE TABLE #Table
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
IDValue VARCHAR(1) ,
ModifiedDT DATETIME NULL,
NewKey AS ( CONVERT(VARCHAR(100),ID)+'_Tmp' )
)
INSERT #Table( IDValue, ModifiedDT )
SELECT 'A', GETDATE()
UNION ALL
SELECT 'Y', GETDATE() - 1
UNION ALL
SELECT 'N', GETDATE() - 5
SELECT * FROM #Table

How to return NULL for Identity when no INSERT is performed

I have two tables
CREATE TABLE Temp_1
(
ID Int IDENTITY(1,1),
Name Varchar(500)
)
CREATE TABLE Temp_2
(
ID Int IDENTITY(1,1),
Name Varchar(500)
)
INSERT INTO Temp_1
SELECT 'CC'
INSERT INTO Temp_2
SELECT Name
FROM Temp_1
WHERE 2 = 1
There is no insertion into the table Temp_2.So my expected output for the SCOPE_IDENTITY () for the table Temp_2 is NULL.
How can i get the Identity Value of the Temp_2 as null?
If we use the SCOPE_IDENTITY() OR ##IDENTITY, the identity value we are getting is only of the table Temp_1. We need to get the identity value of table Temp_2 which is "null" as there is no insertion in the table Temp_2 .
Neither. You want to use the output clause:
DECLARE #ids TABLE (id INT);
INSERT INTO Temp_1
OUTPUT inserted.id INTO #ids
SELECT 'CC' ;
This is session-safe, statement-safe, multi-threaded safe. And it allows you to handle multiple row inserts. And it allows you to return additional columns.
There is no reason to use any other method.

Prevent changes the default value of a column in a table sql server

How can i prevent changes in a column value set to default in sql server
i have a table TimeTable in which Column is date which is of type varchar(20) i want that column should be updated with getdate() all the time when user insert the value and prevent from modify/change the value in insert statement or update statement. please help!
Use view + trigger -
CREATE TABLE dbo.TestTable
(
ID INT IDENTITY(1,1) PRIMARY KEY
, ProductName VARCHAR(25)
, PurchargeDate DATETIME DEFAULT(GETDATE())
)
GO
CREATE VIEW dbo.vw_TestTable
AS
SELECT
ID
, ProductName
, PurchargeDate
FROM dbo.TestTable
GO
CREATE TRIGGER dbo.trg_IOIU_TestTable
ON dbo.vw_TestTable
INSTEAD OF INSERT, UPDATE
AS BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.TestTable(ProductName)
SELECT i.ProductName
FROM INSERTED i
LEFT JOIN dbo.TestTable t ON t.ID = i.ID
WHERE t.ID IS NULL
UPDATE t
SET ProductName = i.ProductName
FROM dbo.TestTable t
JOIN INSERTED i ON t.ID = i.ID
END
GO
Use trigger for that. It might look like this
CREATE TRIGGER tg_default_value ON TimeTable
FOR INSERT, UPDATE
AS
UPDATE t
SET t.[Column] = GETDATE()
FROM TimeTable t JOIN INSERTED i
ON t.ID = i.ID;
See SQLFiddle example
I think use of trigger will be good approach to do this. In this trigger if opration is insert then you can insert the gatdate() value after change the format to char by using to_char().
and if operation is update then you can prevent to change the value for this column.

How to insert a record and make sure the entire row is unique

I want to insert multiple values into a row, but I want to make sure that the row is unique, i.e. no duplicate rows.
I am unsure how to do this (it is fairly easy to if there is only a single value to check for i.e. like this: SQL Server - How to insert a record and make sure it is unique).
This is my code, but it won't allow me to insert unique rows as it tests for single columns and multiple columns combined.
CREATE TABLE myCities (
UserID int null,
CityID int null
)
DECLARE #UserID int, #CityID int
SET #UserID = 1
SET #CityID = 1
INSERT INTO myCities (UserID,CityID)
SELECT #UserID,#CityID
WHERE
#UserID NOT IN ( SELECT UserID FROM myCities WHERE UserID = #UserID )
AND
#CityID NOT IN ( SELECT CityID FROM myCities WHERE CityID = #CityID )
The only sure way is to put the check in the database. In this case create a unique key on the table which will also be its primary key so
-- syntax for MS/Sybase at least is
ALTER TABLE myCities
ADD CONSTRAINT uc_myCities UNIQUE (UserID,CityID)
Then when you insert a duplicate then you will get an error and your code will have to deal with it.
Sometimes the obvious is right at hand - solved it by using NOT EXISTS, like this:
INSERT INTO myCities (UserID,CityID)
SELECT #UserID,#CityID
WHERE NOT EXISTS (
SELECT UserID FROM myCities
WHERE
UserID = #UserID and
CityID = #CityID
)

Simplest way to insert a related row for each row in a table and link them together?

What is the simplest way to insert a Car for each user in Users and set the users CarID to the ID of the inserted Car?
[Users]
- ID
- Name
- CarID
[Cars]
- ID (Auto increment)
- Name
Sorry if this might be a duplicate question but I can't find any simple solutions. Everything I've found is using complicated cursors, pointers etc.
A simple and reusable syntax for this would save me hours while migrating data during system upgrades etc.
If you are on SQL Server 2008 or later you can use merge and output something like this.
Sample tables and data:
declare #Users table
(
ID int identity primary key,
Name varchar(10) not null,
CarID int null
);
declare #Cars table
(
ID int identity primary key,
Name varchar(10) not null
);
insert into #Users(Name) values ('User1'),('User2'),('User3');
Add one care for each user and move the auto-generated CarID back to Users.
declare #ID table(CarID int, UserID int)
merge #Cars as C
using #Users as U
on 0 = 1
when not matched then
insert (Name) values ('CarName')
output inserted.ID, U.ID into #ID;
update U
set CarID = I.CarID
from #Users as U
inner join #ID as I
on U.ID = I.UserID
Try it out on SE Data.
More info on the merge/output trick can be found here.
I'm assuming the code you're using lets you call stored procedures?
create procedure dbo.CarUserInsert_sp
(
#p_UserID int,
#p_UserName varchar(100),
#p_CarID int,
#p_CarName varchar(100)
)
as
if not exists ( select 1 from Cars where ID = #p_CarID )
insert Cars values ( #p_CarID, #p_CarName )
if exists (select 1 from Users where ID = #p_UserID )
update Users set Name = #p_UserName, CarID = #p_CarID where ID = #p_UserID
else
insert Users values ( #p_UserID, #p_UserName, #p_CarID )
go
try this:
insert into cars (name)
select distinct(name) from users
update user
set carId = (select ID from cars where cars.name=user.Name)