Dropping PRIMARY KEY constraint - sql-server

I have created a table which has two columns combined as a primary key.
CREATE TABLE [dbo].[Workflow_Name]
(
[Workflow_ID] [int] NOT NULL,
[Unique_Workflow_ID] [int] NOT NULL,
[Workflow_Name] [varchar](255) NULL,
[Row_ID] [int] NULL,
[ReleaseVersion] [varchar](255) NULL,
[Release] [varchar](255) NULL,
CONSTRAINT [PK_WorkFlowName] PRIMARY KEY CLUSTERED
([Workflow_ID] ASC, [Unique_Workflow_ID] ASC )
)
As seen , [Workflow_ID] ASC, [Unique_Workflow_ID] ASC combined together are forming the Primary key.
Now i want to remove [Unique_Workflow_ID] from the Primary key constraint and maintain only [Workflow_ID] as Primary Key.
How to do it?

You can do it by executing the following statements in SSMS Query Window after selecting the database that the table is in.
ALTER TABLE [dbo].[Workflow_Name]
DROP CONSTRAINT [PK_WorkFlowName]
ALTER TABLE [dbo].[Workflow_Name]
ADD CONSTRAINT [PK_WorkFlowName] PRIMARY KEY ([Workflow_ID] ASC)
Please note, in order for it to work, if you have existing rows in the [Workflow_Name], then the data in this new single column Primary Key i.e. in [Workflow_ID] must be unique per row. Otherwise the ALTER statement will (rightly) throw an error that data is not unique in that column.

You can remove your primary key constraint and then create a new one only with the Workflow_ID. But make sure it has only unique values.

Related

Creating Primary Keys

I would like to know which column should I put in the PK first, [ID_CHECK] or [ID_CONTROL].
CREATE TABLE QUALITY_CONTROL
(
[ID_CHECK] [int] NULL,
[ID_CONTROL] [int] NOT NULL
)
ALTER TABLE QUALITY_CONTROL ADD CONSTRAINT QUALITY_CONTROL_P01 PRIMARY KEY ([ID_CHECK], [ID_CONTROL])
or
ALTER TABLE QUALITY_CONTROL
ADD CONSTRAINT QUALITY_CONTROL_P01 PRIMARY KEY ([ID_CONTROL], [ID_CHECK])
The [ID_CHECK] column has more repeated data, I don't know if that means anything.
Thanks.

SQL Server foreign key with several cascading paths

I have three tables in SQL Server 2014.
First one is a Product table (productid, ...)
Second one contains ProductVersions of that product (ProductVersionID, ProductID, ...)
Third one contains licenses for the products (LicenseID, ProductID)
These tables have foreign keys on the product ID with on delete cascade.
Now I want to add another table mapping the licenses to specific ProductVersions. This can be a n:m relationship, so I create an mapping table LicenseVersion (LicenseID, ProductVersionID)
When I try to add an foreign key to that relations I get an error saying can't add foreign key because there are loops or serveral cascading paths. Use on delete no action or change the foreign key.
I think, I get why this happens (deleting the product will cause the LicenseVersion row to be deleted from both ways in one transaction) but what is the best practice to solve this?
The database should be consistent anytime, so I don't want to solve this in the software application logic.
I could use a trigger (I think) and an foreign key with no action, but is this the best way?
CREATE TABLE [dbo].[Products]
(
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[ProductName] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_dbo.Products]
PRIMARY KEY CLUSTERED([ProductID] ASC)
)
CREATE TABLE [dbo].[ProductVersions]
(
[ProductVersionID] [int] IDENTITY(1,1) NOT NULL,
[ProductID] [int] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_dbo.ProductVersions]
PRIMARY KEY CLUSTERED ([ProductVersionID] ASC)
)
CREATE TABLE [dbo].[License]
(
[LicenseId] [int] IDENTITY(1,1) NOT NULL,
[LicenseName] [nvarchar](255) NOT NULL,
[ProductId] [int] NOT NULL,
CONSTRAINT [PK_dbo.License]
PRIMARY KEY CLUSTERED ([LicenseId] ASC)
)
CREATE NONCLUSTERED INDEX [IX_ProductId]
ON [dbo].[License] ([ProductId] ASC)
CREATE NONCLUSTERED INDEX [IX_ProductID]
ON [dbo].[ProductVersions] ([ProductID] ASC)
ALTER TABLE [dbo].[License] WITH CHECK
ADD CONSTRAINT [FK_dbo.License_dbo.Products_ProductId]
FOREIGN KEY([ProductId]) REFERENCES [dbo].[Products] ([ProductID])
ON UPDATE CASCADE
ON DELETE CASCADE
ALTER TABLE [dbo].[License] CHECK CONSTRAINT [FK_dbo.License_dbo.Products_ProductId]
ALTER TABLE [dbo].[ProductVersions] WITH CHECK
ADD CONSTRAINT [FK_dbo.ProductVersions_dbo.Products_ProductID]
FOREIGN KEY([ProductID]) REFERENCES [dbo].[Products] ([ProductID])
ON UPDATE CASCADE
ON DELETE CASCADE
ALTER TABLE [dbo].[ProductVersions] CHECK CONSTRAINT [FK_dbo.ProductVersions_dbo.Products_ProductID]
--add new table
CREATE TABLE [dbo].[LicenseVersion]
(
[LicenseID] [int] NOT NULL,
[ProductVersionID] [int] NOT NULL,
CONSTRAINT [PK_LicenseVersion]
PRIMARY KEY CLUSTERED ([LicenseID] ASC, [ProductVersionID] ASC)
)
ALTER TABLE [dbo].[LicenseVersion] WITH CHECK
ADD CONSTRAINT [FK_LicenseVersion_ProductVersions]
FOREIGN KEY([ProductVersionID]) REFERENCES [dbo].[ProductVersions] ([ProductVersionID])
ON UPDATE CASCADE
ON DELETE CASCADE
ALTER TABLE [dbo].[LicenseVersion] CHECK CONSTRAINT [FK_LicenseVersion_ProductVersions]
--error here:
ALTER TABLE [dbo].[LicenseVersion] WITH CHECK
ADD CONSTRAINT [FK_LicenseVersion_Licenses]
FOREIGN KEY([LicenseID]) REFERENCES [dbo].[License] ([LicenseID])
ON UPDATE CASCADE
ON DELETE CASCADE
ALTER TABLE [dbo].[LicenseVersion] CHECK CONSTRAINT [FK_LicenseVersion_Licenses]

Can SQL Server table have a foreign key to a table that resolves to many records?

Consider the following table...
CREATE TABLE [dbo].[Alerts]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[I18NMessageKey] [uniqueidentifier] NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
GO
and the following table...
CREATE TABLE [dbo].[I18NMessages]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Key] [uniqueidentifier] NOT NULL,
[Culture] [nvarchar](200) NOT NULL,
[Message] [nvarchar](max) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
GO
I would like to add a foreign key constraint to table [Alerts] on the column [I18NMessageKey] to refer to many records in table [I18NMessages].
Is this possible without a third table?
The [I18NMessages] table holds the same message for the [Key] but in different languages depending on [Culture]. The relationship between [Alerts] and [I18NMessages] doesn't care about the culture. The resolution of [Culture] depends on the user at runtime.
In SQL Server, the uniqueness of the referenced key column(s) must be enforced by a primary key, unique constraint, or unique index. You need a third table with a unique I18NMessageKey column key to enforce referential integrity.
You can create a trigger and implement custom business logic

Simple SQL Server Delete fails

I am seeing intermittent failures upon a simple delete.
Essentially I have a temporary note that has many entries. Each entry has a classification which is a lookup value. Once this note is completed, it gets sent to a note repository, and the temporary version needs to be deleted.
I can't replicate reliably, but on occasion, when calling the stored procedure that does the delete of the temp note, only SOME of the entries get deleted. Coincidentally (?) the entry left behind has always been of one specific classification type.
After many many many attempts I was able to reproduce the issue while running SQL Server Profiler. Despite trying to catch Attention, ErrorLog, EventLog, Exception, and Execution Warnings, the resulting profile shows nothing out of the ordinary.
None of the involved tables are large. In fact they're minuscule. ~100-1000 at any given time in Entry, ~100 in Draft, 9 in Classification, 3 in Category.
I don't believe it should matter, but just in case, this stored procedure is being called from Entity Framework.
Any ideas? Any ideas on what to try for troubleshooting? I'm completely at a loss. Thanks in advance for any help.
Here is the stored procedure for deletion:
CREATE PROCEDURE [NoteDraft].[ClearNoteDraft]
#DraftId BIGINT
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM NoteDraft.[Entry]
WHERE DraftId = #DraftId
DELETE FROM NoteDraft.Draft
WHERE Id = #DraftId
END
Here are the table definitions (with some columns left out for brevity as noted.)
CREATE TABLE [NoteDraft].[Category]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[SortOrder] [int] NULL,
CONSTRAINT [PK_Category]
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
CREATE TABLE [NoteDraft].[Classification]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[CategoryId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
[SortOrder] [int] NULL,
CONSTRAINT [PK_Classification]
PRIMARY KEY CLUSTERED ([Id] ASC)
)
CREATE TABLE [NoteDraft].[Draft]
(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[DateModified] [datetime] NOT NULL CONSTRAINT [DF_TestNoteDraft_DateModified] DEFAULT (getdate()),
[AccountNumber] [varchar](30) NULL,
--...10 other biz columns...
CONSTRAINT [PK_Notes]
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
CREATE TABLE [NoteDraft].[Entry]
(
[DraftId] [bigint] NOT NULL,
[ClassificationId] [int] NOT NULL,
[Body] [varchar](2100) NULL,
CONSTRAINT [PK_Entry]
PRIMARY KEY CLUSTERED ([DraftId] ASC, [ClassificationId] ASC)
) ON [PRIMARY]
ALTER TABLE [NoteDraft].[Classification] WITH CHECK
ADD CONSTRAINT [FK_Classification_Category]
FOREIGN KEY([CategoryId]) REFERENCES [NoteDraft].[Category] ([Id])
GO
ALTER TABLE [NoteDraft].[Classification] CHECK CONSTRAINT [FK_Classification_Category]
GO
ALTER TABLE [NoteDraft].[Entry] WITH CHECK
ADD CONSTRAINT [FK_Entry_Classification]
FOREIGN KEY([ClassificationId]) REFERENCES [NoteDraft].[Classification] ([Id])
GO
ALTER TABLE [NoteDraft].[Entry] CHECK CONSTRAINT [FK_Entry_Classification]
GO
ALTER TABLE [NoteDraft].[Entry] WITH CHECK
ADD CONSTRAINT [FK_Entry_Draft]
FOREIGN KEY([DraftId]) REFERENCES [NoteDraft].[Draft] ([Id])
GO
ALTER TABLE [NoteDraft].[Entry] CHECK CONSTRAINT [FK_Entry_Draft]
GO
As with everything simple like this, the answer wasn't where I was looking.
Turns out, there's an event listener on the page that's re-inserting the records post deletion.
Still having trouble figuring out why the listener is running, but at least I know what's going on.

How can I force one to one relationship on SQL Server 2008 or 2008 R2

Here is my scenario on SQL Server 2008 R2:
This is my first table:
CREATE TABLE [dbo].[Foos](
[FooId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Foos] PRIMARY KEY CLUSTERED
(
[FooId] ASC
)
) ON [PRIMARY]
This is the second table which has a relationship to Foos table:
CREATE TABLE [dbo].[Bars](
[BarId] [int] IDENTITY(1,1) NOT NULL,
[FooId] [int] NOT NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Bars] PRIMARY KEY CLUSTERED
(
[BarId] ASC
)
) ON [PRIMARY]
Go
ALTER TABLE [dbo].[Bars] WITH CHECK ADD CONSTRAINT [FK_Bars_Foos] FOREIGN KEY([FooId])
REFERENCES [dbo].[Foos] ([FooId])
ON DELETE CASCADE
GO
But it is not one to one. What should I do to force this to be one to one relationship? Should I use check constraints?
Add a unique constraint to FooId in Bars.
However, you don't need BarID then because they have the same key. So it looks like this
CREATE TABLE [dbo].[Bars] (
[FooId] [int] NOT NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Bars] PRIMARY KEY CLUSTERED (FooId),
CONSTRAINT [FK_Bars_Foos] FOREIGN KEY([FooId])
REFERENCES [dbo].[Foos] ([FooId])
ON DELETE CASCADE
)
GO
However again, you don't need Bars at all: it is one table...
You can keep Identity column(BarID) also. Then Unique key will help you out from this problem.
IF NOT EXISTS(SELECT OBJECT_ID from sys.objects WHERE name ='foo_bars')
alter table bars add constraint foo_bars unique(fooid)

Resources