Why is SSMS-produced script missing indexes? - sql-server

SSMS 17.4, SQL Server 2017 Developer's Edition on Win10 1709
I have installed the WorldWideImporters sample database. One of the tables, Sales.Customers, has several foreign keys AND several foreign key indexes. When scripting the table (Script Table, CREATE To…), the script includes the foreign keys, but not the foreign key indexes. If I just change the name of the table and run the generated script, the table is created with all of the FK constraints, but none of the FK indexes.
For something you can see even if you don't have the WWI sample installed, I did this.
CREATE TABLE bar (
bar_id int,
col1 varchar(20),
CONSTRAINT pk_bar PRIMARY KEY CLUSTERED (bar_id)
)
CREATE TABLE foo (
foo_id int,
foobar_id int,
col1 varchar(20),
CONSTRAINT pk_foo PRIMARY KEY CLUSTERED (foo_id)
)
ALTER TABLE foo WITH CHECK
ADD CONSTRAINT FK_bar FOREIGN KEY (foobar_id) REFERENCES bar (bar_id)
ALTER TABLE foo CHECK CONSTRAINT FK_bar
That creates two tables, with foo having a FK constraint to bar. I then scripted the table from SSMS.
CREATE TABLE [dbo].[foo](
[foo_id] [int] NOT NULL,
[foobar_id] [int] NULL,
[col1] [varchar](20) NULL,
CONSTRAINT [pk_foo] PRIMARY KEY CLUSTERED
(
[foo_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [USERDATA]
) ON [USERDATA]
GO
ALTER TABLE [dbo].[foo] WITH CHECK ADD CONSTRAINT [FK_bar] FOREIGN KEY([foobar_id])
REFERENCES [dbo].[bar] ([bar_id])
GO
ALTER TABLE [dbo].[foo] CHECK CONSTRAINT [FK_bar]
GO
So far, so good.
But then I added an index on foo on the FK column.
CREATE NONCLUSTERED INDEX FK_bar ON foo (foobar_id)
Scripting the table then produces the exact same script as above. Thus, SSMS is producing the same script whether there's an index on the FK column or not. (I confirmed with sp_helpindex that the FK index does indeed exist.)
Is this a bug in SSMS or am I mis-understanding something?

Scripting out the index is turned off by default in SSMS. Personally, that is one of the first things I turn back on along with scripting permissions and triggers. You can find this setting by:
In SSMS, open the Tools menu and pick Options
Scroll down to SQL Server Object Explorer and expand the tree
Click on the Scripting node and change Script indexes to true

Related

How can Reference Foreign key to Multiple tables?

I am trying to create a BOM structure i have 6 product tables which contains different attributes and a BOMHEADER and BOMDETAIL tables. Before creating the BOM structure i like to Validate or check the existence of the bomitem in either of the six tables. So i tried to creating BOMHEADER field as shown below using multiple constraints, but i get the following error message
"The INSERT Statement conflicted with the FOREIGN KEY constraint
What is the best way to resolve the issue.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[BOMHEAD](
[bomItem] [int] NOT NULL,
[bomRev] [nvarchar](6) NOT NULL,
[rollup] [bit] NULL,
CONSTRAINT [PK_BOMHEAD_KEY_0] PRIMARY KEY CLUSTERED
(
[bomItem] ASC,
[bomRev] 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].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[parts] ([itemId])
GO
ALTER TABLE [dbo].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[Tires] ([titemId])
GO
ALTER TABLE [dbo].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[Discs] ([itemId])
GO
ALTER TABLE [dbo].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[Rims] ([itemId])
GO
ALTER TABLE [dbo].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[Wheel] ([wheelItemId])
GO
ALTER TABLE [dbo].[BOMHEAD] WITH CHECK ADD FOREIGN KEY([bomItem])
REFERENCES [dbo].[Assemblies] ([itemId])
GO
The structure you post is not check that bomItem is exists in any of that given table but it is required that bomItem must exists in ALL TABLES.
You should do it the other way round by making BOMHEAD to primary key table and set fk of other table to refer pk on BOMHEAD.
This way it will guarantee that every other part table will have BOMHEAD.
The way you did is to guarantee that BOMHEAD will have every other parts.
But if you insist that bomItem need to check for existence in either of the six tables(maybe to prevent unwanted reference from other table?),You can't use fk what you need is check constrain with user defined function or create association table which maintain the relation between BOMHEAD and others.
You should have general table with BOMs that are referenced via Foreign Key by all these tables.

Difference between 'Foreign Key Relations' window and 'Keys' in Object explorer SSMS

In the image, the Foreign Key Relationships window is showing the FK for the itemModifier_Rel table while on the object explorer it doesn't shows the same results.
What are the differences between these?
I'm having a problem of duplicated keys, some DBA have a wrong process that causes this and I'm trying to fix it.
I deleted the duplicates but now I'm seeing this. Although the resulting CREATE TABLE script for the table shows just 3 FK while on the Foreign Key Relationships I'm seeing 6
Here's the table's script after dropping the duplicated FK
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[itemModifier_Rel](
[ItemModifierTypeID] [bigint] NOT NULL,
[ItemID] [bigint] NOT NULL,
[ModifierItemID] [bigint] NULL,
[ModifierSequenceID] [bigint] NULL,
PRIMARY KEY NONCLUSTERED
(
[ItemModifierTypeID] ASC,
[ItemID] 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].[itemModifier_Rel] WITH CHECK ADD FOREIGN KEY([ItemID])
REFERENCES [dbo].[item] ([ItemID])
GO
ALTER TABLE [dbo].[itemModifier_Rel] WITH CHECK ADD FOREIGN KEY([ItemModifierTypeID])
REFERENCES [dbo].[itemModifierType_Cat] ([ItemModifierTypeID])
GO
ALTER TABLE [dbo].[itemModifier_Rel] WITH CHECK ADD FOREIGN KEY([ModifierItemID])
REFERENCES [dbo].[item] ([ItemID])
GO
On left you see the keys constraint names under Keys. On right you have the dialog for setting up key properties visually. That dialog is listing all the foreign keys of your table plus all the foreign keys that reference to table. IOW you have 3 FK + 2 references to your table PK in that picture.

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

Include not available in covering indexes in SQL Server 2008 Express

In MS SQL Server Manager Studio for 2008 Express, the "Included Columns" field is always grayed out in the "Indexes/Keys" window in the Database Diagram designer.
Per the help, this should be available so long as I'm not creating a clustered index.
Further, if I run a query to create the index (which runs fine), the created query doesn't list for the table it was added against.
I don't see anywhere where MS says this feature is unavailable in the Express version.
Any ideas?
Further data:
This is the script that creates the table:
CREATE UNIQUE INDEX IX_SocialTypes_Cover ON ClientSocialTypes(ClientID, SocialTypeID, [Source]) INCLUDE (URLID)
Here is the table gen script (the index is missing):
CREATE TABLE [dbo].[ClientSocialTypes](
[SocialTypeID] [int] IDENTITY(1,1) NOT NULL,
[ClientID] [int] NOT NULL,
[SocialTypeClassID] [tinyint] NOT NULL,
[Source] [nvarchar](50) NOT NULL,
[TagCount] [int] NOT NULL,
[URLID] [int] NULL,
CONSTRAINT [PK_ClientSources] PRIMARY KEY CLUSTERED
(
[SocialTypeID] 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].[ClientSocialTypes] WITH CHECK ADD CONSTRAINT [FK_ClientSocialTypes_Clients] FOREIGN KEY([ClientID])
REFERENCES [dbo].[Clients] ([ClientID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[ClientSocialTypes] CHECK CONSTRAINT [FK_ClientSocialTypes_Clients]
GO
ALTER TABLE [dbo].[ClientSocialTypes] WITH CHECK ADD CONSTRAINT [FK_ClientSocialTypes_SocialTypeClasses] FOREIGN KEY([SocialTypeClassID])
REFERENCES [dbo].[SocialTypeClasses] ([SocialTypeClassID])
GO
ALTER TABLE [dbo].[ClientSocialTypes] CHECK CONSTRAINT [FK_ClientSocialTypes_SocialTypeClasses]
GO
ALTER TABLE [dbo].[ClientSocialTypes] ADD CONSTRAINT [DF_ClientSocialTypes_SocialTypeClassID] DEFAULT ((1)) FOR [SocialTypeClassID]
GO
ALTER TABLE [dbo].[ClientSocialTypes] ADD CONSTRAINT [DF_ClientSocialTypes_TagCount] DEFAULT ((0)) FOR [TagCount]
GO
ALTER TABLE [dbo].[ClientSocialTypes] ADD CONSTRAINT [DF_ClientSocialTypes_HasTrackedURL] DEFAULT ((0)) FOR [URLID]
GO
There's TWO different index dialogs. An ancient horrible awful one, and a new (only just discovered it) one that actually lets you change these things.
OLD HORRIBLE ONE
Right click on a table in your main tables list
Click 'Design'
Right click on the list of columns and select 'Indexes/Keys'
This doesn't let you change included columns.
NEW NICE ONE
Expand the table in your main tables list to show the 'Columns', 'Keys', 'Constraints', 'Triggers' etc folders
Expand the Indexes folder
Right click Indexes folder for New Index
Right click existing index and click Properties to edit an existing index
This newer dialog allows you to do a lot more and I'm kind of disappointed in Microsoft for keeping the old one alive and for how long it's taken me to discover it.
It turns out this is grayed out in the full version of SQL Server too. In SSMS, use the Object Explorer (not the Designer) to navigate to {database_name} > Tables > {table_name} > Indexes to manage indexes that have includes.
The index may actually be a unique constraint (using CREATE/ALTER TABLE) rather than an index created using CREATE INDEX. Unique constraints don't allow INCLUDEs.
It's quite confusing... generate a script for the index/key entry or table and you'll be able to confirm.
Edit:
When you create the index separately you have to refresh Object Explorer
Do you have 2 SocialType tables in different schemas? (eg dbo.SocialType and [domain\myuser].SocialType). This can happen if you don't specify the schema in DDL statements.

resolving foreign constraints among connected tables

I have two tables A and B with A referencing a column in B with foreign key constraint. Now, i am trying to add more columns and constraints to table A by dropping table A and creating the table A again with new columns. SQL Server Mgmt Studio provides the "Drop and Create" option to do this where i alter the create table statement to add more columns.
Executing the statements throws an error stating A is referenced by a foreign key constraint. To fix this, i had to removed the foreign key constraint from the table A and then execute "drop and create" the statement. In my case, i could do this by dropping one constraint. I can't image doing the same with a set of tables cross referencing each other.
This should be a common occurrence for most of the SQL designers and i am wondering if there is a way to manage this situation without deleting and recreating the web of constraints across tables.
Appreciate your comments!
EXAMPLE OF SQL:
Current table:
CREATE TABLE [dbo].[TableA](
[PhotoId] [bigint] IDENTITY(1,1) NOT NULL,
[PhotoTypeId] [bigint] NOT NULL,
[PhotoDescription] [nvarchar](max) NULL,
[LastModifiedBy] [bigint] NOT NULL,
[LastModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED
(
[PhotoId] 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].[TableA] WITH NOCHECK ADD CONSTRAINT [FK_TableA_TableAType] FOREIGN KEY([PhotoTypeId])
REFERENCES [dbo].[TableAType] ([PhotoTypeId])
GO
ALTER TABLE [dbo].[TableA] NOCHECK CONSTRAINT [FK_TableA_TableAType]
GO
ALTER TABLE [dbo].[TableA] WITH NOCHECK ADD CONSTRAINT [FK_TableA_TableB1] FOREIGN KEY([LastModifiedBy])
REFERENCES [dbo].[TableB] ([UserId])
GO
ALTER TABLE [dbo].[TableA] NOCHECK CONSTRAINT [FK_TableA_TableB1]
GO
ALTER TABLE [dbo].[TableA] ADD CONSTRAINT [DF_TableA_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO
expected table
CREATE TABLE [dbo].[TableA](
[PhotoId] [bigint] IDENTITY(1,1) NOT NULL,
[PhotoTypeId] [bigint] NOT NULL,
[PhotoDescription] [nvarchar](max) NULL,
***[PhotoWidth] [int] NOT NULL,
[PhotoHeight] [int] NOT NULL,***
[LastModifiedBy] [bigint] NOT NULL,
[LastModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED
(
[PhotoId] 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].[TableA] WITH NOCHECK ADD CONSTRAINT [FK_TableA_TableAType] FOREIGN KEY([PhotoTypeId])
REFERENCES [dbo].[TableAType] ([PhotoTypeId])
GO
ALTER TABLE [dbo].[TableA] NOCHECK CONSTRAINT [FK_TableA_TableAType]
GO
ALTER TABLE [dbo].[TableA] WITH NOCHECK ADD CONSTRAINT [FK_TableA_TableB1] FOREIGN KEY([LastModifiedBy])
REFERENCES [dbo].[TableB] ([UserId])
GO
ALTER TABLE [dbo].[TableA] NOCHECK CONSTRAINT [FK_TableA_TableB1]
GO
ALTER TABLE [dbo].[TableA] ADD CONSTRAINT [DF_TableA_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO
Solution: Don't use the table designer in Management Studio. Seriously. Don't. It's a relic from more than a decade ago, and it doesn't know SQL very well. (Check out connect.microsoft.com, and you'll find many, many bugs and suggestions filed against it.)
You can (and should) add columns and constraints using SQL without dropping and recreating the table, copying data, recreating constraints, etc.
ALTER TABLE A ADD myNewColumn int;
ALTER TABLE A ADD CONSTRAINT ...
If you have a particular situation you don't know the SQL for, please give the CREATE TABLE/INDEX/CONSTRAINT statements and explain what you need to do.
Added: For the example you added to your question, here's the one line SQL. I added defaults just because you'll need them if your table already contains data when you add the columns, which are NOT NULL.
ALTER TABLE dbo.TableA ADD PhotoWidth INT NOT NULL DEFAULT 640, PhotoHeight INT NOT NULL DEFAULT 480;
I've never run into this problem. When I modify a table, I use the Designer to add the columns, save, and it works like magic... It warns me about other tables referencing this one, but I press "OK", and my table is modified !
Anyway, you can remove the reference constraints on the tables by doing:
ALTER TABLE [name] NOCHECK CONSTRAINT ALL
and enable them with:
ALTER TABLE [name] CHECK CONSTRAINT ALL
If you are modifying a lot of tables, you can do:
Before modifications:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
After modifications:
EXEC sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
No, you have to drop the constrainsts. But the Good News!™ is that you can use a select from the information_schema tables (or your rdbms' equivalent) to generate the alter table drop constraint statements.
Ah, but Steve Kass read your question more closely than I did. Just add the columns, without dropping the table, with alter table add column ....

Resources