Why would this table allow a PK id of 0? - sql-server

In SQL Server 2008 R2, I have a table that allows 0 as a foreign key. This is odd because a primary key constraint is specified, and the IDENTITY(1,1) descriptor is also used.
When the first record is inserted to the table, it's PK (RegionID) is 0.
I don't have IDENTITY-INSERT turned ON when I am doing an insert. (Normal operation)
Here's the table definition:
CREATE TABLE [dbo].[tdfRegions](
[RegionID] [int] IDENTITY(1,1) NOT NULL,
[RegionName] [nvarchar](50) NOT NULL,
[RegionDescription] [nvarchar](50) NOT NULL,
[Active] [bit] NOT NULL,
CONSTRAINT [PK_tdfRegions] PRIMARY KEY CLUSTERED
(
[RegionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
I have been acting under the assumption that the first record inserted to this table would have a RegionID of 1.
INSERT INTO
tdfRegions (RegionName, RegionDescription, Active)
VALUES
('test','test', 1)
Produces:
RegionID RegionName RegionDescription Active
0 test test 1
Why might this be happening?
EDIT:
Ok, I've got a little more background information here. Someone ran a
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
To clear the database when it was first created. Could this have been responsible?

The only reason it you could end up with 0 in the RegionID is --
when you truncate the table and reseed the identity to 0 using below command
DBCC CHECKIDENT('tdfRegions', RESEED, 0)
If you then insert into the table with your insert block, it will be RegionID = 0.

The ways I know to reset the PK are:a) use truncateBut that would put the see back to 1b) use something like:DBCC CHECKIDENT (MyTable, RESEED, 1)If you used a 0 instead of a 1 in the last statement, that would get the seed set to 0.Someother people talking about this.
http://social.msdn.microsoft.com/Forums/en-US/sqldatabaseengine/thread/ca0db3d2-e3ae-46ce-b8f0-bfc3bf95a509/

Related

Reset IDENTITY column whitout deleting all rows

I have the following table
CREATE TABLE [dbo].[MyTable](
[Name] NVARCHAR(200) NOT NULL,
[Surname] NVARCHAR(200) NOT NULL,
[Permanent] [bit] NULL,
[Idx] [bigint] IDENTITY(1,1) NOT NULL
CONSTRAINT [MyTable] PRIMARY KEY CLUSTERED
(
[Idx] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
that contains 1000 rows where [Permanent]=1 and 500.000 rows with [Permanent] NULL
In addition, I have a stored procedure (called MySP) that do the following steps:
DELETE FROM [MyTable] WHERE [Permanent] IS NULL
(lots of calculations)
INSERT results of point 2 into [MyTable]
MySP runs every day so the number of [Idx] increase very quickly as every day 500.000 rows are deleted and inserted.
My target is, during the execution of the SP, to reset the value of column [Idx] to mantain the max number of [Idx] lower possible.
1st try
I have tried to update with the following query at the end of MySP but the system gives me a (correct) error.
UPDATE A
SET A.[Idx]=B.[Idx_new]
FROM [dbo].[MyTable] A
INNER JOIN (
SELECT [Idx],ROW_NUMBER() OVER (ORDER BY [Idx]) AS [Idx_new]
FROM [dbo].[MyTable]
) B
ON A.[Idx]=B.[Idx]
2nd try
After reading the following two questions/answers
Reset identity seed after deleting records in SQL Server
How to update Identity Column in SQL Server?
I have add the following at the end of MySP
DBCC CHECKIDENT ('MyTable', RESEED, 1);
but also this doesn't not work as in [MyTable], differently from the situation of both quesions, remain some rows, so the is a concrete risk that [Idx] is not unique and that's not good as [Idx] is my primary key.
How could I reset the identity column value and also the rows that still remains into [MyTable]?
Using #Killer Queen suggest, I have solved using this snippet of code, which find the MAX([Idx]) of MyTable after the DELETE and the reeseed the identity before the new INSERT.
It works because the rows with [Permanent]=1 are the first rows inserted in the table so their [Idx] values start from 1 and are very low.
DELETE
FROM [MyTable]
WHERE [Permanent]!=1 OR [Permanent] IS NULL
DECLARE #MaxIdx As bigint
SET #MaxIdx = (SELECT ISNULL(MAX([Idx]),0) FROM [MyTable])
DBCC CHECKIDENT ('MyTable', RESEED, #MaxIdx);

How do you deal with foreign keys, unique indexes and default constraints when using a shadow table copy and rename?

I have a large table in a MSSQL 2008 database, to which I need to add a new column, set a value on that new column and then make it not null.
Because the table is large, it keeps timing out on our deployment process. I read that I can use a shadow table and SELECT INTO.., then use sp_rename to replace the original table. As per this answer: https://stackoverflow.com/a/19141346/119624
The table has lots of foreign keys, indexes and constraints. I'm slightly confused as to how I should deal with those.
I assume that the process is as below. But I would appreciate it if someone could confirm whether I'm doing this in the optimum way.
Imagine this is my current table:
CREATE TABLE [dbo].[MyTable](
[MyTableId] [int] IDENTITY(1,1) NOT NULL,
[SomeFkId] [int] NOT NULL,
[IsLocked] [bit] NOT NULL CONSTRAINT [DF_MyTable_IsLocked] DEFAULT ((0)),
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[MyTableId] ASC
) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] WITH CHECK
ADD CONSTRAINT [FK_MyTable_SomeFk] FOREIGN KEY([SomeFkId])
REFERENCES [dbo].[SomeFk] ([SomeFkId])
GO
ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_SomeFk]
GO
I now want to add a new shadow table. Do I need to create the table with the defaults and constraints like so?
CREATE TABLE [dbo].[MyTableShadow](
[MyTableId] [int] IDENTITY(1,1) NOT NULL,
[SomeFkId] [int] NOT NULL,
[SomeColumn] [int] NOT NULL,
[IsLocked] [bit] NOT NULL CONSTRAINT [DF_MyTableShadow_IsLocked] DEFAULT ((0)),
[NewColumn] [int] NOT NULL,
CONSTRAINT [PK_MyTableShadow] PRIMARY KEY CLUSTERED
(
[MyTableId] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTableShadow] WITH CHECK
ADD CONSTRAINT [FK_MyTableShadow_SomeFk] FOREIGN KEY([SomeFkId])
REFERENCES [dbo].[SomeFk] ([SomeFkId])
GO
ALTER TABLE [dbo].[MyTableShadow] CHECK CONSTRAINT [FK_MyTableShadow_SomeFk]
GO
Then do the SELECT INTO...
SELECT MyTable.*, MyTable.SomeColumn -- copying value
INTO MyTableShandow
FROM MyTable
Then do the rename:
EXEC sp_rename 'MyTable', 'MyTableOld'
EXEC sp_rename 'MyTableShadow', 'MyTable'
Then do the drop:
DROP TABLE MyTableOld
Then rename the constraints and foreign keys:
EXEC sp_rename 'PK_MyTableShadow', 'PK_MyTable', 'object' -- PK
EXEC sp_rename 'FK_MyTableShadow_SomeFk', 'FK_MyTable_SomeFk', 'object' -- FK
EXEC sp_rename 'DF_MyTableShadow_IsLocked', 'DF_MyTable_IsLocked', 'object' -- DF
Is that the correct process, or is there another easier way? (I have a table that has a lot of FKs and constraints, so I'm trying to reduce the pain!

Convert INT to BIGINT in SQL Server

SQL 2005, 600,000,000 rows.
I have a table called Location currently using the data type INT in identity PK column LocationID. I would like to attempt converting this data type to BIGINT.
The following script I think should help to allow inserted into the PK column but i am unsure how to progress form here.
SET IDENTITY_INSERT LOCATION ON /*allows insert into the identity column*/`
SET IDENTITY_INSERT LOCATION OFF /*Returns the identity column to initial state*/`
Location table create script below:
CREATE TABLE [dbo].[Location](
[LocationID] [int] IDENTITY(1,1) NOT NULL,
[JourneyID] [int] NULL,
[DeviceID] [int] NOT NULL,
[PacketTypeID] [int] NULL,
[PacketStatusID] [int] NULL,
CONSTRAINT [Location_PK] PRIMARY KEY CLUSTERED
(
[LocationID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Location] WITH CHECK ADD CONSTRAINT [Device_Location_FK1] FOREIGN KEY([DeviceID])
REFERENCES [dbo].[Device] ([DeviceID])
GO
ALTER TABLE [dbo].[Location] CHECK CONSTRAINT [Device_Location_FK1]
GO
ALTER TABLE [dbo].[Location] WITH CHECK ADD CONSTRAINT [PacketStatus_Location_FK1] FOREIGN KEY([PacketStatusID])
REFERENCES [dbo].[PacketStatus] ([PacketStatusID])
GO
ALTER TABLE [dbo].[Location] CHECK CONSTRAINT [PacketStatus_Location_FK1]
GO
ALTER TABLE [dbo].[Location] WITH CHECK ADD CONSTRAINT [PacketType_Location_FK1] FOREIGN KEY([PacketTypeID])
REFERENCES [dbo].[PacketType] ([PacketTypeID])
GO
ALTER TABLE [dbo].[Location] CHECK CONSTRAINT [PacketType_Location_FK1]
One option i think would be to copy the data to a new table then delete the old table and rename the new one however we have constraints that will need to be dropped for this to work.
Your idea of a new table is the way to go.
On a development server, you can see the script that SSMS would produce if you change the data type using the table designer. It is a good start. This will add triggers and constraints back afterwards.
A tool like Red gate SQL Compare also allows you to check that everything was created OK

Trigger Not Putting Data in History Table

I have the following trigger (along with others on similar tables) that sometimes fails to put data into the historic table. It should put data into a historic table exactly as it's inserted/updated and stamped with a date.
CREATE TRIGGER [dbo].[trig_UpdateHistoricProductCustomFields]
ON [dbo].[productCustomFields]
AFTER UPDATE,INSERT
AS
BEGIN
IF ((UPDATE(data)))
BEGIN
SET NOCOUNT ON;
DECLARE #date bigint
SET #date = datepart(yyyy,getdate())*10000000000+datepart(mm,getdate())*100000000+datepart(dd,getdate())*1000000+datepart(hh,getdate())*10000+datepart(mi,getdate())*100+datepart(ss,getdate())
INSERT INTO historicProductCustomFields (productId,customFieldNumber,data,effectiveDate) (SELECT productId,customFieldNumber,data,#date from inserted)
END
END
Schema:
CREATE TABLE [dbo].[productCustomFields](
[id] [int] IDENTITY(1,1) NOT NULL,
[productId] [int] NOT NULL,
[customFieldNumber] [int] NOT NULL,
[data] [varchar](50) NULL,
CONSTRAINT [PK_productCustomFields] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[historicProductCustomFields](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[productId] [int] NOT NULL,
[customFieldNumber] [int] NOT NULL,
[data] [varchar](50) NULL,
[effectiveDate] [bigint] NOT NULL,
CONSTRAINT [PK_historicProductCustomFields] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I insert and update only on one record at a time on the productCustomFields table. It seems to work 99% of the time and hard to test for failure. Can anyone shed some light on what I may be doing wrong or better practices for this type of trigger?
Environment is Sql Server Express 2005. I haven't rolled out the service pack yet for sql server either for this particular client.
I think the right way to solve this is keep a TRY CATCH block when inserting into the dbo.historicProductCustomFields table and write the errors into a custom errorlog table. From there it is easy to track this down.
I also see a PK on the historicProductCustomFields table but if you insert and update a given record in ProductCustomFields table then won't you get primary key violations on the historicProductCustomFields table?
You should schema qualify your table that you are inserting into.
You should check to ensure that there are not multiple triggers on the table, as if there are, only 1 trigger for that type of trigger will fire and if there are 2 defined, they are run in random order. In other words, 2 triggers of the same type (AFTER INSERT) then one would fire and the other would not, but you don't necessary have control as to which will fire.
try to use this trigger. i just give you example try to write trigger with this trigger.
create TRIGGER [dbo].[insert_Assets_Tran]
ON [dbo].[AssetMaster]
AFTER INSERT , UPDATE
AS BEGIN
DECLARE #isnum TINYINT;
SELECT #isnum = COUNT(*) FROM inserted;
IF (#isnum = 1)
INSERT INTO AssetTransaction
select [AssetId],[Brandname],[SrNo],[Modelno],[Processor],[Ram],[Hdd],[Display],[Os],[Office],[Purchasedt]
,[Expirydt],[Vendor],[VendorAMC],[Typename],[LocationName],[Empid],[CreatedBy],[CreatedOn],[ModifiedBy]
,[ModifiedOn],[Remark],[AssetStatus],[Category],[Oylstartdt],[Oylenddt],[Configuration]
,[AStatus],[Tassign]
FROM inserted;
ELSE
RAISERROR('some fields not supplied', 16, 1)
WITH SETERROR;
END

SQL Server won't let me make column identity

So I have a table in SQL Server w/ a primary key column, and 4 other columns. When I modify the table, and select the primary key column to be identity, it won't let me save the table.
How can I make it an identity column through T-SQL or something without going to the UI?
Thanks.
Here's the create
USE [db]
GO
/****** Object: Table [dbo].[tblMessages] Script Date: 04/05/2011 11:58:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tblMessages](
[messageId] [int] NOT NULL,
[messageText] [varchar](500) NOT NULL,
[messageLatitude] [float] NOT NULL,
[messageLongitude] [float] NOT NULL,
[messageTimestamp] [datetime] NOT NULL,
PRIMARY KEY CLUSTERED
(
[messageId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
You cannot turn an existing column into an IDENTITY column after it's been created.
ALTER TABLE dbo.YourTable
ALTER COLUMN YourColumn INT IDENTITY
will cause an error:
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword
'IDENTITY'.
You need to create a new column of type INT IDENTITY and then possibly drop the old one. Or if your table is still empty: drop it and re-create it with the correct settings for your ID column
ALTER TABLE MyTable
ADD NewIdentity INT IDENTITY;
ALTER TABLE MyTable
DROP COLUMN OldPK;
EDIT
If your table is empty, just drop it and add IDENTITY after INT on your PK column and be done with it.

Resources