简体   繁体   中英

How to increment a primary key in an insert statement in SQL Server 2005

I need to write an insert statement into a table the columns looks like this

  • demandtypeid ( PK, FK, int, not null )
  • characvalueid ( PK, FK, int, not null )
  • percentage ( int null )
  • lastuser ( varchar(100), null )
  • lastedited ( datetime, null )

Here is the INSERT statement. Notice the there is not values at the

value( ,  , 'Bob')

as I think that's where the auto-increment command should go

insert into tr_demandtypecharac(demandtypeID, characvalueid, lastuser) 
values(  , , 'Bob')

Please help with a simple little statement

I just want to know how to manually insert into this table

Here's my table structure:

CREATE TABLE [dbo].[tr_demandtypecharac](
[demandtypeid] [int] NOT NULL,
[characvalueid] [int] NOT NULL,
[percentage] [int] NULL,
[lastuser] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[lastedited] [datetime] NULL,
 CONSTRAINT [PK_tr_dtc_pkey] PRIMARY KEY CLUSTERED 
(
[demandtypeid] ASC,
[characvalueid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
 ) ON [PRIMARY]

ALTER TABLE [dbo].[tr_demandtypecharac]  WITH CHECK 
ADD CONSTRAINT [FK_tr_dtc_cvid] 
FOREIGN KEY([characvalueid]) REFERENCES [dbo].[tr_characvalue] ([characvalueid])

ALTER TABLE [dbo].[tr_demandtypecharac]  WITH CHECK 
ADD CONSTRAINT [FK_tr_dtc_dtid] 
FOREIGN KEY([demandtypeid]) REFERENCES [dbo].[tr_demandtype] ([demandtypeid])

If you want an int column that is unique and autoincrementing, use the IDENTITY keyword:

CREATE TABLE new_employees
(
 id_num int IDENTITY(1,1),
 fname varchar (20),
 minit char(1),
 lname varchar(30)
)

Then when you insert into the table, do not insert anything for that column -- it will autoincrement itself.

Given the CREATE TABLE statement you posted, without auto-increment (aka identity) columns, you would insert providing all columns and values, like this:

insert into tr_demandtypecharac(
       demandtypeid, characvalueid, 
       percentage, lastuser, lastedited) 
values(2, 3, 80, 'Bob', '01/01/2012')

If, however, you do make them auto-increment by changing the CREATE TABLE to:

CREATE TABLE [dbo].[tr_demandtypecharac](
[demandtypeid] [int] NOT NULL IDENTITY(1,1),
[characvalueid] [int] NOT NULL IDENTITY(1,1),
[percentage] [int] NULL,
[lastuser] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[lastedited] [datetime] NULL,
 CONSTRAINT [PK_tr_dtc_pkey] PRIMARY KEY CLUSTERED 
(
[demandtypeid] ASC,
[characvalueid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
 )

Then you would insert providing all non-identity (non-autoincrement) columns like this:

insert into tr_demandtypecharac(
      percentage, lastuser, 
      lastedited) 
values(80, 'Bob', '01/01/2012')

However, it is not common to have more than one column as an identity (autoincrement) column, and generally, this column is the only PRIMARY KEY column.

If a column is an autoincement column (which is different than a primary key column) then you omit the column in your insert statement and it will be filled in.

INSERT INTO tr_demandtypecharac (lastuser) VALUES ('Bob')

I had a similar issue and needed to update a purchased database with a set of records. My solution was to find the highest key used so far, then use that as the base of my insert. The core of it was ROWNUMBER() OVER(ORDER BY PART_CODE).

The key is the "recnum" field in the inadjinf table. I determined that the highest current key was 675400 and updated my query to be:

insert into inadjinf (recnum, user_id, adj_type, adj_status, trans_date, part_code, lotqty, uom, cost_ctr, lot, location, to_cost_ctr, to_location, rec_status, to_part_grade, to_rec_status, remarks1, uom_conv) 
select ROW_NUMBER() OVER(ORDER BY INVDET.PART_CODE) + 675400 as recnum, 'CHRSTR' as user_id, 'M' as adj_type, 'O' as adj_status, '2020-10-23' as trans_date, invdet.part_code, sum(lotqty) as lotqty, uom, 
cost_ctr, lot, location, 'NS' as to_cost_ctr, '500A' as to_location, rec_status, 'Q' as to_part_grade, 'H' as to_rec_status, 'NS Scrap Request from MSobers 10/21/2020' as remarks1, '1' as uom_conv
from invdet
inner join partmstr on invdet.part_code = partmstr.part_code
where 
invdet.part_code In
(
'86038',
'1271',
'VM-0021',
'CO-0107',
...
'FO-0391',
'FO-0376'
)
and lot not in (select lot from inadjinf where trans_date = '2020-10-23' and user_id = 'CHRSTR')
group by invdet.part_code, uom, cost_ctr, lot, location, rec_status

My output started with 675401 and went up from there. In the end, I updated the system's internal "next id field" table record.

You should not use int as primary keys... heres a article about it: http://techtrainedmonkey.com/2012/07/30/why-integers-are-lousy-primary-keys/

but if you do... set the field as identity and Sql Server will do it for you... check it out: http://msdn.microsoft.com/en-us/library/ms186775.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM