Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
Studevs
Starting Member
15 Posts |
Posted - 2012-08-06 : 10:41:45
|
Dear all,I have this table in my database:USE [MyDb]GO/****** Object: Table [dbo].[Persons] Script Date: 08/06/2011 16:22:32 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [dbo].[Persons]( [PersonRecId] [int] IDENTITY(1,1) NOT NULL, [PersonNumber] [varchar](100) NOT NULL, [FirstName] [varchar](100) NOT NULL, [LastName] [varchar](100) NOT NULL, [MiddleName] [varchar](100) NOT NULL, [NameSuffix] [varchar](100) NOT NULL, [MaidenName] [varchar](100) NOT NULL, [FullName] AS (case when [IsAnonymous]=(1) then [FirstName] else ltrim(rtrim(([FirstName]+' ')+ltrim(([MiddleName]+' ')+[LastName]))) end) PERSISTED, [Street] [varchar](100) NOT NULL, [HouseNumber] [varchar](100) NOT NULL, [ZipCode] [varchar](20) NOT NULL, [City] [varchar](100) NOT NULL, [Gender] [tinyint] NOT NULL, [Birthdate] [date] NULL, [EmailAddress] [varchar](100) NULL, [FaxNumber] [varchar](30) NULL, [PhoneNumber] [varchar](30) NULL, [IsAnonymous] [bit] NOT NULL, [PersonStatus] [tinyint] NULL, [CountryRecId] [smallint] NULL, [MobileNumber] [varchar](30) NULL, [Removed] [bit] NOT NULL, CONSTRAINT [PK_Persons_PersonRecId] PRIMARY KEY CLUSTERED ( [PersonRecId] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOSET ANSI_PADDING OFFGOALTER TABLE [dbo].[Persons] WITH CHECK ADD CONSTRAINT [FK_Persons_Countries] FOREIGN KEY([CountryRecId])REFERENCES [dbo].[Countries] ([CountryRecId])GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_FirstName] DEFAULT ('') FOR [FirstName]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_LastName] DEFAULT ('') FOR [LastName]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_MiddleName] DEFAULT ('') FOR [MiddleName]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_NameSuffix] DEFAULT ('') FOR [NameSuffix]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_MaidenName] DEFAULT ('') FOR [MaidenName]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_Street] DEFAULT ('') FOR [Street]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_HouseNumber] DEFAULT ('') FOR [HouseNumber]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_PersonStatus] DEFAULT ((1)) FOR [PersonStatus]GOALTER TABLE [dbo].[Persons] ADD CONSTRAINT [DF_Persons_Removed] DEFAULT ((0)) FOR [Removed]GONow when i try to insert a new Person in my table with PersonNumber 'AlphaOmega', i'm getting the message :'Cannot insert duplicate key row in object 'dbo.Persons' with unique index 'UNQ_Persons_PersonNumber'. The duplicate key value is (AlphaOmega).The statement has been terminated.'But i want to get this message only when the Person with PersonNumber 'AlphaOmega' , has 0 in his 'Removed' column.So when Removed = 1 , then i want to be able to reuse the PersonNumber.How can i do this, please some help.Thanks in advance. |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-08-06 : 10:58:43
|
then you should remove unique index on PersonNumber and replace it with check constraint likeALTER TABLE dbo.Persons ADD CONSTRAINT Chk_PersonNumber CHECK (dbo.PersonNumberReuse(PersonNumber,Removed)=1)AND function PersonNumberReuse should be likeCREATE FUNCTION PersonNumberReuse(@PersonNumber varchar(100),@Removed bit)RETURNS bitASBEGINDECALRE @Ret bit,@Cnt intSELECT @Cnt=COUNT(*) FROM dbo.PersonsWHERE PersonNumber=@PersonNumberAND Removed=@RemovedSELECT @Ret=CASE WHEN @Removed=0 AND @Cnt > 1 THEN 0 ELSE 1 ENDRETURN (@Ret)END ------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
LoztInSpace
Aged Yak Warrior
940 Posts |
Posted - 2012-08-06 : 11:24:38
|
| Think carefully about this. What happens to the "old" person's rows when you select based on person name? Are you going to include them in the search when the person has been replaced?You obviously know your requirement better than I do but this is a classic antipattern/pitfall and is rarely as simple as you show. |
 |
|
|
Studevs
Starting Member
15 Posts |
Posted - 2012-08-07 : 02:55:20
|
quote: Originally posted by visakh16 then you should remove unique index on PersonNumber and replace it with check constraint likeALTER TABLE dbo.Persons ADD CONSTRAINT Chk_PersonNumber CHECK (dbo.PersonNumberReuse(PersonNumber,Removed)=1)AND function PersonNumberReuse should be likeCREATE FUNCTION PersonNumberReuse(@PersonNumber varchar(100),@Removed bit)RETURNS bitASBEGINDECALRE @Ret bit,@Cnt intSELECT @Cnt=COUNT(*) FROM dbo.PersonsWHERE PersonNumber=@PersonNumberAND Removed=@RemovedSELECT @Ret=CASE WHEN @Removed=0 AND @Cnt > 1 THEN 0 ELSE 1 ENDRETURN (@Ret)END ------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/
Hi Visakh16,Thank you for your answer. I tried to create the function like this:SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION PersonNumberReuse(@PersonNumber varchar(100),@Removed bit)RETURNS bitASBEGINDECALRE @Ret bit,@Cnt intSELECT @Cnt=COUNT(*) FROM dbo.PersonsWHERE PersonNumber=@PersonNumberAND Removed=@RemovedSELECT @Ret=CASE WHEN @Removed=0 AND @Cnt > 1 THEN 0 ELSE 1 ENDRETURN (@Ret)ENDGO When executing, i'm getting this errors:Msg 102, Level 15, State 1, Procedure PersonNumberReuse, Line 14Incorrect syntax near 'DECALRE'.Msg 137, Level 15, State 1, Procedure PersonNumberReuse, Line 16Must declare the scalar variable "@Cnt".Msg 137, Level 15, State 2, Procedure PersonNumberReuse, Line 21Must declare the scalar variable "@Cnt".Msg 137, Level 15, State 2, Procedure PersonNumberReuse, Line 22Must declare the scalar variable "@Ret". |
 |
|
|
lionofdezert
Aged Yak Warrior
885 Posts |
Posted - 2012-08-07 : 03:55:41
|
| Just a typo..SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION PersonNumberReuse(@PersonNumber varchar(100),@Removed bit)RETURNS bitASBEGINDECLARE @Ret bit,@Cnt intSELECT @Cnt=COUNT(*) FROM dbo.PersonsWHERE PersonNumber=@PersonNumberAND Removed=@RemovedSELECT @Ret=CASE WHEN @Removed=0 AND @Cnt > 1 THEN 0 ELSE 1 ENDRETURN (@Ret)ENDGO--------------------------http://connectsql.blogspot.com/ |
 |
|
|
|
|
|
|
|