Reputation: 163
I have a table called Cases
that has information about interviews such as IV_Date
, IV_Length
, Interviewer
, etc. I also have a field within Cases
called Case_Code
(a varchar
) which is a six-character (three letters + three numbers) identifier; e.g. "ABC123" or "ZZZ999." There is a foreign key on ContactID
(an int
), which points to a Contact
table. I have created a computed column which is the PRIMARY KEY of this Cases
table, called CaseID
. CaseID
is simply a concatenation of Case_Code
and ContactID
. So, ContactID
"25" working on case "ZZZ999" is given a CaseID
of "ZZZ99925". Neither Case_Code
nor ContactID
accepts nulls, so CaseID
obviously does not. When setting up CaseID
I created it as NOT NULL, PRIMARY KEY, and used the formula "[Case_Code] + CONVERT([varchar], [contactID], 0)". I thought everything was working fine but when I try to rearrange any fields in the SQL Studio table design view, I get thrown this error:
'Cases (dbo)' table
- Unable to create index 'PK_Cases_1'.
Cannot define PRIMARY KEY constraint on nullable column in table 'Cases'.
Could not create constraint. See previous errors.'
I do not understand why I'm getting this error, since all NOT NULL columns in my table contain data. Any help or ideas would be greatly appreciated. Thanks!
Edit with code:
CREATE TABLE [dbo].[Cases](
[ContactID] [int] NOT NULL,
[Case_Code] [varchar](16) NOT NULL,
[Assigned_To] [varchar](100) NULL,
[LEK_Interviewer] [varchar](255) NULL,
[Case_Notes] [varchar](max) NULL,
[IV_Status] [varchar](100) NULL,
[IV_Quality] [numeric](18, 0) NULL,
[IV_Date] [date] NULL,
[IV_Length] [varchar](50) NULL,
[Address] [varchar](100) NULL,
[City] [varchar](100) NULL,
[State] [varchar](50) NULL,
[Zip] [varchar](25) NULL,
[Country] [varchar](50) NULL,
[Total_Honorarium] [money] NULL,
[Currency] [varchar](20) NULL,
[Last_Update] [varchar](50) NULL,
[CaseID] AS ([Case_Code]+CONVERT([varchar],[contactID],0)) PERSISTED NOT NULL,
CONSTRAINT [PK_Cases_1] PRIMARY KEY CLUSTERED
(
[CaseID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Upvotes: 14
Views: 78120
Reputation: 176
This appears to be a bug in the SQL Server Management Studio. The easiest approach is to make your changes using the designer. Then generate the change script using:
Right-click > Generate Change Script...
Copy the generated SQL or save it to a file. Then, add "NOT NULL" to the computed column in the CREATE TABLE statement and run the SQL file
Upvotes: -1
Reputation: 176
Use this query
Alter table tablename
add column datatype identity(1,1)
Upvotes: 0
Reputation:
I bumped into this, too. You can create a PK on a calculated field, as long as it's marked NOT NULL, but the SQL Server table design interface does not handle this situation; it seems to mark all calculated fields as NULLable when modifying a table.
First, I strongly recommend that you always create and modify your tables with scripts, not the GUI. Doing so gives you a record of what you have and what changes you've made; you can run them to recreate your database as of any point in time. As HLGEM mentioned, you can also keep these scripts in source control. Having these scripts makes it easier to do things which are difficult to do with the GUI, and as you've discovered here, they make it possible to do things which are impossible in the GUI.
Within the table designer, delete your PK. You should then be able to save the table, effecting the reordering of fields you wanted to achieve. Next, you need to drop and recreate the calculated field, and finally you can recreate your PK. E.g.:
ALTER TABLE Cases DROP COLUMN CaseID
ALTER TABLE Cases ADD CaseID AS (Case_Code + CAST(ContactID AS CHAR(6))) PERSISTED NOT NULL
ALTER TABLE Cases ADD CONSTRAINT CPK_Cases PRIMARY KEY CLUSTERED (CaseID)
If you have any indices which reference the calculated field (other than the PK, which we've already dropped), you'll need to delete them before you can drop the calculated field. Be sure to re-create them after, of course.
Finally, while Dean did not support his assertion that calculated fields are bad for PKs, he is correct that it would be simpler to put your PK on { Case_Code
, ContactID
}. You could then stop persisting CaseID
(if you even need it all) and save yourself a little disk space.
Upvotes: 3
Reputation: 435
A primary key cannot be applied on a column with a null constraint (nullable). When a table is created, by default every column is nullable.
So first off all we have to remove the null constraint and apply a NOT NULL constraint on the column. To do this execute the following query
ALTER TABLE tbl_name alter column column_name int NOT NULL
After that you can apply a primary key on that same column. To do this execute the following query
ALTER TABLE tbl_name ADD PRIMARY KEY (column_name)
I hope this will help you
Upvotes: 31
Reputation: 10098
Don't use computed column as a primary key, very bad idea. In your case, just define the PK on both CaseCode and ContactID columns. In the designer, select both columns, right-click and choose "set prinary key" from the menu.
Upvotes: -1