T-SQL/SSIS - Tables locking after redesign with primary/foreign keys - sql

I've managed to get myself into a bit of a pickle, I did a quick redesign of the tables used in a notifications system & have managed to make the things entirely useless.
Any attempt to use them (select/update/insert/delete/alter) results in a query that runs indefinitely. I believe that I've managed to accidentally misuse the CASCADE option to nearing epic proportions. Below are the three tables and associated keys that I've used
I have managed to SELECT form the tables by using the "WITH (NOLOCK)" hint, however my attempts to delete/alter the CONSTRAINTS on the TBL_NOTIFICATIONS table have met with no luck. Hopefully one of you will be able to see where I've gone wrong & chastise me properly.
http://i.imgur.com/s8YrFFn.png (Relationship structure, I don't have enough reputation in include images yet)
TBL_NOTIFICATIONS:
CREATE TABLE [dbo].[TBL_NOTIFICATIONS]
(
[NotificationID] INT IDENTITY(0,1) NOT NULL,
[ApplicationID] INT NULL,
[SubApplicationID] INT NULL,
[Title] NVARCHAR(50) NULL,
[ShortDesc] NVARCHAR(512) NULL,
[Link] NVARCHAR(100) NULL,
[RaisedBy] NVARCHAR(36) NULL,
[RaisedFor] NVARCHAR(36) NULL,
[Show] INT NULL,
[DateCreated] DATETIME NULL,
[DateToArchive] DATETIME NULL,
CONSTRAINT [PK_TBL_NOTIFICATIONS] PRIMARY KEY CLUSTERED
(
[NotificationID] 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].[TBL_NOTIFICATIONS]
WITH CHECK ADD CONSTRAINT [FK_TBL_NOTIFICATIONS_TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS]
FOREIGN KEY( [ApplicationID] )
REFERENCES [dbo].[TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS] ( [ApplicationID] )
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[TBL_NOTIFICATIONS] CHECK CONSTRAINT [FK_TBL_NOTIFICATIONS_TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS]
GO
ALTER TABLE [dbo].[TBL_NOTIFICATIONS]
WITH CHECK ADD CONSTRAINT [FK_TBL_NOTIFICATIONS_TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS]
FOREIGN KEY( [SubApplicationID], [ApplicationID] )
REFERENCES [dbo].[TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS] ( [SubApplicationID], [ApplicationID] )
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[TBL_NOTIFICATIONS] CHECK CONSTRAINT [FK_TBL_NOTIFICATIONS_TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS]
GO
TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS:
CREATE TABLE [dbo].[TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS]
(
[ApplicationID] [int] NOT NULL,
[Description] [nvarchar](50) NULL,
CONSTRAINT [PK_TBL_NOTIFICATIONS_APPLICATION_DESCRIPTIONS] PRIMARY KEY CLUSTERED
(
[ApplicationID] 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
And finally...
TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS:
CREATE TABLE [dbo].[TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS]
(
[SubApplicationID] [int] NOT NULL,
[ApplicationID] [int] NOT NULL,
[Description] [nvarchar](50) NULL,
[ImagePath] [nvarchar](200) NULL,
CONSTRAINT [PK_TBL_NOTIFICATIONS_SUBAPPLICATION_DESCRIPTIONS] PRIMARY KEY CLUSTERED
(
[SubApplicationID] ASC,
[ApplicationID] 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
As I've mentioned, SELECT statements can be executed against the tables by using "WITH (NOLOCK)" however any attempt to modify them meets with infinitely loading queries. I've attempted to alter the UPDATE and DELETE CONSTRAINTS (to "NO ACTION" and "SET NULL") with no success. Likewise using ALTER TABLE with DROP CONSTRAINT does nothing but run forever.
I can view the constraints when querying "sys.foreign_keys" however I don't believe I can modify system tables directly, although I'd very much like being told otherwise on this point.
Does anyone have any ideas on either:
a) How to remove the constraints/keys on these tables, or
b) How to drop the tables without encountering another lock
Any and all ideas welcome, especially welcome would be a hint to how on earth I've managed to make these tables immune to my SQL-fu.
Thanks in advance

I don't have enough reputation to comment, so forgive me for posting this as an answer, maybe a Mod wants to move it?
Have you tried going to the "Activity Monitor" in SSMS and seeing if you have a blocked process (you can kill processes from there)? A stuck process holding a lock would cause the symptoms you are describing.
There is a nice thread on blocking here How to find what is locking my tables

Related

What is the right way to create relations between these tables in a SQL database?

I have three tables: offices, suboffices, and sales. Each office owns several suboffices, both offices and suboffices sell products. How should I design my sales table to store there office or suboffice where this sale was made?
I was thinking about having a compound foreign key made of office_id and suboffice_id (where suboffice_id may be null, in which case a sale was made in office)
Is it the right way to design a database?
I was also thinking about having two sales tables: for offices and suboffices. But in my opinion it makes things a bit harder..
UPDATE
Sales can be of different types, so they will need different tables. And there will be one table 'SALES' which will store type of a sale and where it was made
Your sub-offices sound the same as your offices from a properties point of view. Here is a diagram of what your table design could look like by having your Office table include a ParentOffice foreign key.
And here is the SQL to create those tables:
CREATE TABLE [dbo].[Office](
[OfficeId] [int] NOT NULL,
[ParentOfficeId] [int] NULL,
[MoreStuff] [nvarchar](50) NULL,
CONSTRAINT [PK_Office] PRIMARY KEY CLUSTERED
(
[OfficeId] 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].[Office] WITH CHECK ADD CONSTRAINT [FK_Office_Office] FOREIGN KEY([ParentOfficeId])
REFERENCES [dbo].[Office] ([OfficeId])
GO
ALTER TABLE [dbo].[Office] CHECK CONSTRAINT [FK_Office_Office]
GO
CREATE TABLE [dbo].[Product](
[ProductId] [int] NOT NULL,
[MoreStuff] [nvarchar](50) NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[ProductId] 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].[Sale](
[SaleId] [int] NOT NULL,
[ProducitId] [int] NOT NULL,
[OfficeId] [int] NOT NULL,
CONSTRAINT [PK_Sale] PRIMARY KEY CLUSTERED
(
[SaleId] 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].[Sale] WITH CHECK ADD CONSTRAINT [FK_Sale_Office] FOREIGN KEY([OfficeId])
REFERENCES [dbo].[Office] ([OfficeId])
GO
ALTER TABLE [dbo].[Sale] CHECK CONSTRAINT [FK_Sale_Office]
GO
ALTER TABLE [dbo].[Sale] WITH CHECK ADD CONSTRAINT [FK_Sale_Sale] FOREIGN KEY([ProducitId])
REFERENCES [dbo].[Product] ([ProductId])
GO
ALTER TABLE [dbo].[Sale] CHECK CONSTRAINT [FK_Sale_Sale]
GO
One way to go about this, assuming OFFICE and SUBOFFICE share many of the same attributes is to eliminate the SUBOFFICE table and add a PARENT_OFFICE_ID column to the OFFICE table. Under this design, the distinction between an office and a sub-office would be whether or not PARENT_OFFICE_ID is null. Then SALES can simply have an OFFICE_ID column that can reference either kind of office.

Violation of PRIMARY KEY constraint even though i use proper indexes and query scheme

I have several unique indexes. For example
SET ansi_nulls ON
go
SET quoted_identifier ON
go
CREATE TABLE [dbo].[tblrelatedwords]
(
[cl_orgwordid] [BIGINT] NOT NULL,
[cl_relatedwordid] [BIGINT] NOT NULL,
[cl_relatedwordtypecode] [SMALLINT] NOT NULL,
[cl_relation_sourceid] [TINYINT] NOT NULL,
CONSTRAINT [PK_tblSeeAlso] PRIMARY KEY CLUSTERED ( [cl_orgwordid] ASC,
[cl_relatedwordid] ASC, [cl_relatedwordtypecode] ASC )WITH (pad_index = OFF
, statistics_norecompute = OFF, ignore_dup_key = OFF, allow_row_locks = on,
allow_page_locks = on, FILLFACTOR = 90) ON [PRIMARY]
)
ON [PRIMARY]
go
ALTER TABLE [dbo].[tblrelatedwords]
ADD CONSTRAINT [DF_tblSeeAlso_cl_RelatedWordTypeCode] DEFAULT ((255)) FOR
[cl_RelatedWordTypeCode]
go
When i use below query systematic even though i check with If not exists, i am still getting the below error
IF NOT EXISTS
( SELECT 1
FROM tblRelatedWords
WHERE (cl_OrgWordId=#cl_OrgWordId
AND cl_RelatedWordId=#cl_RelatedWordId
AND cl_RelatedWordTypeCode=#cl_RelatedWordTypeCode)
OR (cl_OrgWordId=#cl_RelatedWordId
AND cl_RelatedWordId=#cl_OrgWordId
AND cl_RelatedWordTypeCode=#cl_RelatedWordTypeCode) ) BEGIN
INSERT INTO tblRelatedWords
VALUES (#cl_OrgWordId,
#cl_RelatedWordId,
#cl_RelatedWordTypeCode,
#cl_Relation_SourceId) END
Error
Violation of PRIMARY KEY constraint 'PK_tblSeeAlso'. Cannot insert duplicate key in object 'dbo.tblRelatedWords'. The duplicate key value is (11439364, 2495501, 243). The statement has been terminated.
Yes multiple threads are adding to the same table however aren't IF NOT EXISTS supposed to prevent such cases?
Microsoft SQL Server 2016 (SP1-CU2) (KB4013106) - 13.0.4422.0 (X64)

How to create two or more Unique Columns in SQL Azure?

I want to select two columns in my table and make them unique but I don't know how to do it in SQL Azure database. As you can see in the image below, it doesn't show any option to modify the table properties, so everything is done using sql queries:
Here is the generated script of the table:
USE [mydbase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[clientaccess](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[ModuleName] [nvarchar](50) NOT NULL,
[ClientAuthenticationId] [bigint] NOT NULL,
[HasAccess] [bit] NOT NULL,
CONSTRAINT [PK_clientaccess_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
ALTER TABLE [dbo].[clientaccess] WITH CHECK ADD CONSTRAINT [CAI_caID] FOREIGN KEY([ClientAuthenticationId])
REFERENCES [dbo].[clientauthentication] ([ID])
GO
ALTER TABLE [dbo].[clientaccess] CHECK CONSTRAINT [CAI_caID]
GO
This is the preview where I encountered the problem, it contains duplicate records:
Hope someone understand my explanation.
Sometimes GUIS have limitations (or not but you haven't discovered yet how all functionalities work). You can always add a unique constraint with ALTER TABLE:
ALTER TABLE [dbo].[clientaccess]
ADD CONSTRAINT Module_Client_UQ --- choose a name
UNIQUE (ModuleName, ClientAuthenticationId) ;

SQL Server equivalent to MySQL enum data type?

Does SQL Server 2008 have a a data-type like MySQL's enum?
It doesn't. There's a vague equivalent:
mycol VARCHAR(10) NOT NULL CHECK (mycol IN('Useful', 'Useless', 'Unknown'))
The best solution I've found in this is to create a lookup table with the possible values as a primary key, and create a foreign key to the lookup table.
IMHO Lookup tables is the way to go, with referential integrity.
But only if you avoid "Evil Magic Numbers" by following an example such as this one:
Generate enum from a database lookup table using T4
Have Fun!
CREATE FUNCTION ActionState_Preassigned()
RETURNS tinyint
AS
BEGIN
RETURN 0
END
GO
CREATE FUNCTION ActionState_Unassigned()
RETURNS tinyint
AS
BEGIN
RETURN 1
END
-- etc...
Where performance matters, still use the hard values.
Probably the best solution for this is a simple look-up table (What is a lookup table?). Nevertheless you can implement something like this:
Solution
SQL Server Management Studio (SSMS)
User.Role is the Foreign Key here, and Role.Type is the Primary Key it refers. And in that table, you'll have the following values:
The type of which must match in both tables. In this case that type is: nvarchar(15)
If you try to add a value at User.Role different than those available at the Role table, you'll get an error.
SQL Code
CREATE TABLE [dbo].[User](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](50) NOT NULL,
[Email] [nvarchar](75) NOT NULL,
[Password] [nvarchar](25) NOT NULL,
[Role] [nvarchar](15) NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_User_Role] FOREIGN KEY([Role])
REFERENCES [dbo].[Role] ([Type])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Role]
GO
CREATE TABLE [dbo].[Role](
[Type] [nvarchar](15) NOT NULL,
CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED
(
[Type] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
Solution 2
You can implement a lookup table like this one: Create enum in SQL Server
You can try something like
ALTER TABLE dbo.yourTable
ADD CONSTRAINT yourColumn CHECK(yourColumn IN('XL','L','M','S','XS'))

How do you add Foreign Key Relationships?

I'm working with an existing SQL 2005 database that was not implemented with FK relationships between tables. I tried to add the relationships with a database diagram and my application immediately blew up trying to edit or insert any data that is tied to the new FK.
dbo.person [person_id | firstname | lastname | dateofbirth]
dbo.campaign [campaign_id | campaign_description]
dbo.disposition [disposition_id | disposition_description]
dbo.person_campaigns [person_campaign_id | person_id | campaign_id | disposition_id]
The person_campaigns table is where a person, campaign, and disposition are tied together. Can you please provide the appropriate SQL syntax for adding the proper FK relationships between these entities?
EDIT
CREATE TABLE [dbo].[person_campaigns](
[person_campaigns_id] [int] IDENTITY(1,1) NOT NULL,
[person_id] [int] NOT NULL,
[d_campaign_id] [int] NOT NULL,
[d_physician_disposition_id] [int] NULL,
CONSTRAINT [PK_person_campaigns] PRIMARY KEY CLUSTERED
(
[person_campaigns_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]
GO
CREATE TABLE [dbo].[d_campaign](
[d_campaign_id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NULL,
[year] [int] NULL,
[isactive] [bit] NOT NULL,
CONSTRAINT [PK_d_campaign] PRIMARY KEY CLUSTERED
(
[d_campaign_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]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[d_campaign] ADD CONSTRAINT [DF_d_campaign_isactive] DEFAULT ((1)) FOR [isactive]
GO
CREATE TABLE [dbo].[d_disposition](
[d_disposition_id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NULL,
[isactive] [bit] NOT NULL,
CONSTRAINT [PK_d_disposition] PRIMARY KEY CLUSTERED
(
[d_disposition_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]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[d_disposition] ADD CONSTRAINT [DF_d_disposition_isactive] DEFAULT ((1)) FOR [isactive]
GO
CREATE TABLE [dbo].[person](
[person_id] [int] IDENTITY(1,1) NOT NULL,
[firstname] [varchar](30) NULL,
[lastname] [varchar](30) NULL,
[dateofbirth] [datetime] NULL
CONSTRAINT [PK__person__0BC6C43E] PRIMARY KEY CLUSTERED
(
[person_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]
GO
the easiest way to do it is through the database diagram editor; do them one at a time and save the diagram to affect the tables after each connection is made. If it "blows up" it is most likely because the tables contain foreign-key values that do not exist; you'll have to clean these up first.
If you have to add them after the table is created the syntax is
create table person (person_id int primary key
,firstname varchar(10)
, lastname varchar(10)
, dateofbirth varchar(10))
create table campaign (campaign_id int primary key
, campaign_description varchar(10))
create table disposition (disposition_id int primary key
,disposition_description varchar(10))
create table person_campaigns(person_campaign_id int
,person_id int, campaign_id int ,disposition_id int)
go
alter table person_campaigns add Constraint
fk_person_campaigns_person_id
Foreign Key (person_id) References person(person_id)
GO
alter table person_campaigns add Constraint
fk_person_campaigns_campaign_id
Foreign Key (campaign_id) References campaign(campaign_id)
GO
alter table person_campaigns add Constraint
fk_person_campaigns_disposition_id
Foreign Key (disposition_id) References disposition(disposition_id)
GO
Suppose I had two tables that should have had a foreign key but did not. The first thing to do is check to see if there will be a data problem if I set a foreign key.
something like the below code would get you the records in the child table that do not have a match in the parent table.
select t2.FKField, t2.PKfield from table2 t2
left join Table1 t1 on t2.fkfield = t1.pkfield
where t1.pkfield is null
Once you can see what is wrong with the existing data, then you need to create a way to fix it. The fix will vary depending on what data you have that has no relationship to the Parent table and what the tables represent. Suppose your parent table contained a VIN number for automobiles as the PK. If your child table contains the cars that were worked on by the shop, you would want to fix the issue by adding the nonexisting VINS to the primary table becasue you wouldn't want to lose the history of what was worked on. There are other structures where you might want to simply delete the records that don't match in child table because they are meaningless. In other circumstances you might want to update those records to some default value (perhaps a customer in the customer table called unknown). In still other circumstances, you might need to go to audit tables or backups to find the value of the PK that was deleted without the associated child records being deleted. The actual way to fix this problem is highly dependent on what the data is used for and how important it is to retain all historical records. Since you should never delete any record that might be related to a financial transaction for legal (and accounting) reasons, you need to be most careful with those.
After fixing all the data, then you run the code to create the FK constraint.
Since I don't have SQL Server on this PC and I don't memorize the syntax, the easiest thing to do is to create two new test tables, create TableA with an ID field, TableB with a field that is a FK of TableA.ID, and then script out TableB to see the ADD CONSTRAINT syntax. Do this using SQL Server Management Studio via a database diagram.
However, if you were able to successfully create the FKs in a data diagram, and you only can't add or update records, I believe something else is wrong. Script out the person_campaigns table and post the code.