Assistance with an auto increment primary key - sql

I'm adding a row to a SQL Server table that has the primary key column as auto increment (identity). When I insert a new row into the table programmatically, is there a way to get the value of the key of the row that was added, as I want to use that as a foreign key in another related table?

You can use the OUTPUT clause.
INSERT INTO YourTable (SomeInteger)
OUTPUT INSERTED.IncrementedColumn
VALUES (1)

This is how I do it:
DECLARE #lastId int
INSERT INTO ...
SET #lastId = SCOPE_IDENTITY();
select #lastId

Related

Using ##identity for consecutive inserts

I have this situation,
INSERT INTO TABLE1()...
--Get the primary key from the above insert
SELECT ##identidy
INSERT INTO TABLE2()...
The auto generated primary key has to be a foreign key in TABLE 2. How can I construct my second INSERT to have the value of ##identity?
This doesn't seem to work,
INSERT INTO TABLE1 (user_id, name) (##identity, 'ABC')
I get an error saying Must declare variable '##identidy'.
Cheers!!
1) you spelled ##identity wrong (##identidy)
2) You should create a local variable (#LastIdentity) to store the last inserted identity immediately after the first insert. Then use that variable as the input to the second INSERT:
DECLARE #LastIdentity int
INSERT INTO TABLE1()...
--Get the primary key from the above insert
SELECT #LastIdentity = ##identity
INSERT INTO TABLE2(...) VALUES (#LastIdentity, ...

Add Row number to a new column

I want to create a new column and populate the value of each row in that column with the row number.
This could be achieved in oracle by doing this.
alter table mytable add (myfield integer);
update mytable set myfield = rownum;
How would this be done in SYBASE ASE?
alter table mytable
add id bigint identity not null
That's all. There will be a column id in every row that contains a unique sequence number for that row.
create column table some_names
(ID bigint not null primary key generated by default as IDENTITY,
NAME nvarchar(30));
And now we can do things like this:
insert into some_names (name) values ('Huey');
insert into some_names (name) values ('Dewey');
insert into some_names (name) values ('Louie');
In my case when I tried to do it with identity column time it wasn't able to finish in reasonable time (196400 rows).
Fast and easy way was to create an INT column and fill it up using a temporary variable #id incremented after each row.
This solution finished in ~4 seconds.
alter mytable add myfield INT
DECLARE #id INT
SET #id = 0
UPDATE mytable
SET #id = myfield = #id + 1
You can find more info here: https://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/

Inserting a new column for serial number

I have table with 500 records in it and want to insert new column as "serial number" starting with 1.
If you care about the order in which the identity values are assigned, you are best off doing this:
CREATE TABLE dbo.NewTable
(
SerialNumber INT IDENTITY(1,1),
... other columns from original table ...
);
INSERT dbo.NewTable(...other columns...)
SELECT ...other columns...
FROM dbo.OriginalTable
ORDER BY ...ordering criteria...
OPTION (MAXDOP 1); -- to prevent parallelism from messing with identity
DROP TABLE dbo.OriginalTable;
EXEC sp_rename N'dbo.NewTable', N'OriginalTable', N'OBJECT';
You may have to deal with constraints etc. and you will want to do this in a transaction. The point is that just adding an identity column to the table with assign the identity values in an arbitrary order. If you don't care about how the existing values are assigned serial numbers, then just use Kyle's answer.
This could be achieved as follows:
alter table YourTable
add SrNo int identity(1,1)
in PostgreSQL just do:
ALTER TABLE ttaabbllee ADD COLUMN columnName serial NOT NULL; and done!..

Update value on insert into table in SQL Server

I am working with SQL Server - on inserting into a table, I have a unique constraint on a table column id. There is a possibility that when inserting, the value going into the id column is 0. This will cause an error.
Is it possible to update this id to another value during the insert if the id value is 0? This is to prevent the error and to give it a valid value.
Possibly a trigger?
A trigger is one way, but you may want to use a filtered index (CREATE UNIQUE INDEX, not as a table constraint) to ignore zero value. This way, you don't have to worry about what value to put there
Alternatively, if you want to populate it from another column, you can have a computed column with a unique constraint.
ALTER TABLE whatever
ADD ComputedUniqueCol = CASE WHEN Id = 0 THEN OtherCol ELSE Id END
If that's your primary key you can specify it as IDENTITY. Then it should generate a value for itself based on seed and increment (the default is seed=1 and default=1) so you don't have to worry about it.
CREATE TABLE MyTable
(
ID int PRIMARY KEY IDENTITY,
...
)
create an "instead of" trigger and check for the value on the ID.
CREATE trigger checkID
on YOUR_TABLE
instead of insert
as
begin
declare #id int
select #id=id from inserted
if (#id==0) begin
--DO YOUR LOGIC HERE AND THEN INSERT
end else begin
insert into DESTINATION_TABLE (VALUES)
SELECT VALUES FROM INSERTED
end
end

How do I insert into a table and get back the primary key value?

I have a primary key set up to auto increment.
I am doing multiple queries and I need to retrieve that primary key value to use as a foreign key in another table (IsIdentity = TRUE).
Is there any elegant way to get back the primary key value when I do an insert query? Right now I am requerying and getting the highest value in that column which seems really hacky.
Any suggestions?
If you are using SQL Server 2005 or later, you can use the OUTPUT clause.
create table T(
pk int identity primary key,
dat varchar(20)
);
go
insert into T
output inserted.pk
values ('new item');
go
drop table T;
The output can be directed to a table as well as to the client. For example:
create table T(
pk int identity primary key,
dat varchar(20)
);
create table U(
i int identity(1001,1) primary key,
T_pk int not null,
d datetime
);
go
insert into T
output inserted.pk, getdate()
into U(T_pk,d)
values ('new item'), ('newer item');
go
select * from T;
select * from U;
go
drop table T, U;
Beginning with SQL Server 2008, you can use "composable DML" for more possibilities.
insert into YourTable values (...)
get the new PK with scope_identity()
select scope_identity()
INSERT INTO YourTable (1, 2, etc.)
OUTPUT inserted.yourIDcolumn
VALUES (value1, value2, value...)
Note: This is for MS SQL 2005 and greater
SCOPE_IDENTITY() is probably what you want. It returns the ID of the last record inserted by the same code context in which it executes.
IDENT_CURRENT('tablename') is subject to concurrency issues. That is, there's no guarantee that another record won't be inserted between the INSERT and the call to IDENT_CURRENT.
I must confess, I'm not sure to what source of amazement the VillageIdiot's outburst refers, but I myself am quite astonished that this question does not appear to be a duplicate at all.
holy crap!!!
just call SCOPE_IDENTITY() function:
insert into your_talble(col1,col2) values('blah','more blah')
select scope_identity()
because selecting highest value will return error if any other statement make an insert. the function scope_identity() returns the identity created in current context (that is by your statement)
You should use scope_identity(). And I recommend to wrap insert statement and scope_identity() into transaction.