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

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

Related

How to save auto generated primary key Id in foreign key column in same table

Following is the table structure:
CREATE TABLE [User] (
[Id] bigint identity(1,1) not null,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint not null,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User] (Creator) Values ([Id] ?)
This is a case when table is empty and first user is going to add in table. Otherwise I don't have issue.
How can I insert Id in creator column with insert statement at the same time?
One way could be using Sequence instead of identity column. The below script might serve the same purpose:
CREATE SEQUENCE dbo.useridsequence
AS int
START WITH 1
INCREMENT BY 1 ;
GO
CREATE TABLE [User] (
[Id] bigint DEFAULT (NEXT VALUE FOR dbo.useridsequence) ,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint DEFAULT NEXT VALUE FOR dbo.useridsequence ,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User]
(
-- Id -- this column value is auto-generated
FirstName,
LastName,
Title,
UserName,
[Password],
Inactive,
Created,
Creator,
Modified,
Modifier
)
VALUES
(
'Foo',
'Bar',
'Title',
'UserName ',
'Password',
0,
GETDATE(),
DEFAULT,
GETDATE(),
1
)
SELECT * FROM [User] AS u
Result :
The short answer is that you can't do this. And I suggest your model is logically flawed in the first place. Do you intend to define all actual database users (e.g., create user ... for login ...) as rows in [Users]? You need to think about that - but the typical answer is no. If the answer is yes, then you don't need the creator column at all because it is redundant. All you need is the created date - for which you probably should have defined a default.
But if you want to do this, you will need to do it in two steps (and you will need to make the column nullable). You insert a row (or rows) with values for the "real" data columns. Then update those same rows with the identity values generated for id. An example showing different ways to do this
use tempdb;
set nocount on;
CREATE TABLE dbo.[user] (
[user_id] smallint identity(3,10) not null primary key,
[name] nvarchar(20) not null,
[active] bit not null default (1),
[created] Datetime not null default (current_timestamp),
[creator] smallint null
);
ALTER TABLE dbo.[user] ADD CONSTRAINT [fk_user] FOREIGN KEY(creator) REFERENCES dbo.[user](user_id);
GO
-- add first row
insert dbo.[user] (name) values ('test');
update dbo.[user] set creator = SCOPE_IDENTITY() where user_id = SCOPE_IDENTITY()
-- add two more rows
declare #ids table (user_id smallint not null);
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
-- mess things up a bit
delete dbo.[user] where name = 'pom';
-- create an error, consume an identity value
insert dbo.[user](name) values (null);
-- add 2 morerows
delete #ids;
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
drop table dbo.[user];
And I changed the identity specification to demonstrate something few developers realize. It isn't always defined as (1,1) and the next inserted value can jump for many reasons - errors and caching/restarts for example. Lastly, I think you will regret naming a table with a reserved word since references to it will require the use of delimiters. Reduce the pain.

Nested cursor, While Loop SQL

I am trying to insert data into two tables(at one shot 100 to 150 rows on both tables). First Table Primary key have a reference with Second Table Foreign key.I Read that Cursor is having problem for ##Fetch_Status is global variable. Which is best way to loop and do data insertion in both tables Cursor or While Loop or any other.
CREATE TABLE Table1
(
FirstTablePK [int] NOT NULL, --Mannual Increment(Not Identity)
Description [varchar](100) NOT NULL,
CONSTRAINT PK_Table1 PRIMARY KEY CLUSTERED (FirstTablePK)
)
CREATE TABLE Table2
(
SecondTablePK [int] NOT NULL, --Mannual Increment(Not Identity)
FirstTablePK [int] NOT NULL, -- Foreign Key Reference with Table1
Description [varchar](100) NOT NULL,
CONSTRAINT PK_Table2 PRIMARY KEY CLUSTERED (SecondTablePK),
CONSTRAINT FK_Table1 FOREIGN KEY (FirstTablePK) REFERENCES Table1(FirstTablePK)
)
Thanks in Advance.
Hari
A cursor is not often used to look up foreign keys. It's faster and easier to use a set-based query:
insert into SaleOrder
(remarks, product_id, customer_id, ...)
select 'please deliver fast'
, (select id from Products where name = 'Car Oil')
, (select id from Customers where name = 'India Corp')
, ...

Use trigger how to copy just inserted row

I'm using SQL Server 2008, and I have a trigger which I want to copy any rows in the My_Table into a archive History_Table table.
How to copy the entire old content of the table into the archive each time someone inserts a new row?
My table structure is
CREATE TABLE [dbo].[Stu_Table]
(
[Stu_Id] [int] NOT NULL,
[Stu_Name] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Stu_Class] [int] NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Stu_Table] ADD CONSTRAINT [PK_Stu_Table] PRIMARY KEY CLUSTERED ([Stu_Id]) ON [PRIMARY]
GO
My archive table structure is
CREATE TABLE [dbo].[Stu_TableHistory]
(
[Stu_Id] [int] NOT NULL,
[Stu_Name] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Stu_Class] [int] NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Stu_TableHistory] ADD CONSTRAINT [PK_Stu_TableHistory] PRIMARY KEY CLUSTERED ([Stu_Id]) ON [PRIMARY]
GO
My trigger syntax is
Create TRIGGER [dbo].[HistoryKeep]
ON [dbo].[Stu_Table]
INSTEAD OF INSERT
AS
BEGIN
IF((SELECT COUNT(*) FROM Stu_Table WHERE Stu_Id = (SELECT Stu_Id FROM INSERTED)) >= 1)
BEGIN
INSERT INTO dbo.Stu_TableHistory( Stu_Id, Stu_Name, Stu_Class )
SELECT Stu_Id, Stu_Name, Stu_Class FROM Stu_Table WHERE Stu_Id = (SELECT Stu_Id FROM INSERTED)
UPDATE x
SET x.Stu_Name = i.Stu_Name
FROM dbo.Stu_Table AS x
INNER JOIN inserted AS i ON i.Stu_Id = x.Stu_Id
END
ELSE
BEGIN
INSERT INTO dbo.Stu_Table( Stu_Id, Stu_Name, Stu_Class )
SELECT Stu_Id, Stu_Name, Stu_Class FROM INSERTED
END
END
In a word need help to transfer the old data from student table to archive table. My above trigger syntax can not satisfy me.
If have any query plz ask thanks in advance.
Instead of your current trigger, you should have something like:
Create TRIGGER [dbo].[HistoryKeep]
ON [dbo].[Stu_Table]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #History table (
Action sysname not null,
STU_ID [int] NULL,
[Stu_Name] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Stu_Class] [int] NULL
)
;MERGE INTO Stu_Table t
USING INSERTED i ON t.STU_ID = i.STU_ID
WHEN MATCHED THEN UPDATE SET STU_Name = i.STU_Name
WHEN NOT MATCHED THEN INSERT (STU_ID,STU_NAME,STU_CLASS) VALUES (i.STU_ID,i.STU_NAME,i.STU_CLASS)
OUTPUT $Action,deleted.stu_id,deleted.stu_name,deleted.stu_class INTO #History;
INSERT INTO stu_TableHistory (stu_id,stu_name,stu_class)
select stu_id,stu_name,stu_class from #History where Action='UPDATE'
END
Note, also, that you'll need to drop your current PK constraint on STU_TableHistory, since as soon as a row is updated more than once, there'll be two entries containing the same STU_ID.
As per my comment, this treats INSERTED as a table containing multiple rows throughout. So if Stu_Table contains a row for STU_ID 1, the following insert:
INSERT INTO STU_Table (STU_ID,STU_Name,STU_Class) VALUES
(1,'abc',null),
(2,'def',null)
will update the row for STU_ID 1, insert a row for STU_ID 2, and insert one row into stu_tableHistory (for STU_ID 1)

Creating a unique column in SQL Azure Federation

I'm trying to create a unique column in SQL Azure Federation, but even though the following query creates a table, I'm still able to save entries to the table with the same Column1 value. What's the correct way to set up a unique column? I need to make sure ID is the federated uniqueidentifier column whereas, for the purposes of this demo, Column1 cannot have duplicate values.
CREATE TABLE dbo.Table1(
ID uniqueidentifier NOT NULL,
Column1 nvarchar(50) NOT NULL,
Column2 nvarchar(15) NULL,
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
(
ID ASC
),
CONSTRAINT [PK_Table2] UNIQUE NONCLUSTERED
(
ID ASC,
Column1 ASC
)
) FEDERATED ON ([dist] = ID)
GO
Without testing, can't you do this
CREATE TABLE dbo.Table1(
ID uniqueidentifier NOT NULL,
Column1 nvarchar(50) NOT NULL,
Column2 nvarchar(15) NULL,
CONSTRAINT [PK_Table1] UNIQUE NONCLUSTERED
(
ID ASC,
Column1 ASC
)
) FEDERATED ON ([dist] = ID)
GO
CREATE UNIQUE INDEX uix_table1_column1 ON Table1(Column1)
GO
Then you will have a primary key encompassing the Federation and a separate unique constraint.

sql server insert records from one table to another

how does one insert records from one table to another that has a unique index in the destination table without going through the insert and then removal of duplicates by deleting the index?
INSERT INTO forms(url,feedUrl, dateadded)
SELECT url, feedurl, dateadded
FROM Book3 T2
where not exists(select * from forms T1 where T1.url = T2.url;
T2.feedurl = T1.feedUrl and T2.dateadded =T1.dateadded)
Violation of UNIQUE KEY constraint 'IX_forms'. Cannot insert duplicate key in object 'dbo.forms'.
Table forms
CREATE TABLE [dbo].[forms](
[id] [int] IDENTITY(1,1) NOT NULL,
[url] [varchar](450) NULL,
[feedUrl] [varchar](450) NULL,
[dateadded] [datetime] NULL,
CONSTRAINT [PK_forms] PRIMARY KEY CLUSTERED
(
Table book3
CREATE TABLE [dbo].[Book3](
[url] [varchar](450) NULL,
[feedurl] [varchar](450) NULL,
[dateadded] [datetime] NULL
) ON [PRIMARY]
You may have duplicates in your results set. Does this query give you fewer records than the orginal select?
SELECT distinct url, feedurl, dateadded
FROM Book3 T2
where not exists(select * from forms T1 where T1.url = T2.url
T2.feedurl = T1.feedUrl and T2.dateadded =T1.dateadded)