2009-08-10 57 views
0

我有两个表A和B,其中A引用B中具有外键约束的列。现在,我试图通过删除表A并使用新列再次创建表A来向表A添加更多列和约束。 SQL Server Mgmt Studio提供了“删除和创建”选项,以便在更改create table语句以添加更多列时执行此操作。解决连接表之间的外部约束问题

执行语句会抛出一个错误,指出A被外键约束引用。要解决这个问题,我必须从表A中删除外键约束,然后执行“删除并创建”语句。在我的情况下,我可以通过删除一个约束来做到这一点。我无法用一组表格交叉引用相同的图像。 这对大多数SQL设计人员来说应该是很常见的事情,我想知道是否有办法在不删除和重新创建跨表的约束网络的情况下管理这种情况。

感谢您的意见!

实例的SQL: 当前表:

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 

预期表

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 

回答

2

解决办法:不要使用Management Studio中的表设计。认真。别。这是十多年前的一个遗留物,它不太了解SQL。 (请查看connect.microsoft.com,你会发现许多错误和建议都是针对它提出的。)

你可以(也应该)使用SQL添加列和约束,而不必删除和重新创建表,复制数据,重建约束等

ALTER TABLE A ADD myNewColumn int; 
ALTER TABLE A ADD CONSTRAINT ... 

如果你有你不知道的SQL特定情况下,请给CREATE TABLE/INDEX /约束声明,并解释你需要做什么。

已添加:对于您添加到问题中的示例,这里是一行SQL。我添加了默认值,只是因为如果添加不为NULL的列时表中已经包含数据,那么您将需要它们。

ALTER TABLE dbo.TableA ADD PhotoWidth INT NOT NULL DEFAULT 640, PhotoHeight INT NOT NULL DEFAULT 480; 
+0

我一直使用设计,它实际上工作得很好。它在大多数情况下也快得多。 – Kevin 2009-08-10 03:07:21

+0

谢谢史蒂夫。添加了示例sql代码。 – pencilslate 2009-08-10 03:29:14

+0

@凯文:“比大多数情况下快”比什么?设计器生成任何人都可以编写的SQL和/或存储的proc调用(但通常不应该)。设计人员的SQL和proc调用如何能比开发人员的SQL和proc调用更快? – 2009-08-10 04:01:07

0

不,您必须删除约束。但好消息! ™是你可以使用information_schema表中的select(或你的rdbms的等价物)到生成alter table drop constraint语句。

啊,但史蒂夫卡斯比我更仔细地阅读你的问题。只需的列,不丢表,与alter table add column ....

+0

谢谢!阅读值得投票吗? :) – 2009-08-10 03:57:32

1

我从来没有遇到过这个问题。当我修改一个表格时,我使用Designer来添加列,保存,并且它像魔术一样工作......它引用了其他引用这个表格的表格,但是我按下了“OK”,并且我的表格被修改了!

无论如何,你可以通过做删除表上的参考约束:

ALTER TABLE [name] NOCHECK CONSTRAINT ALL 

,并让他们:

ALTER TABLE [name] CHECK CONSTRAINT ALL 

如果修改了很多表,你可以这样做:

修改之前:

EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL' 

经过修改后:

EXEC sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL' 
+0

NOCHECK约束不起作用。我已将示例sql添加到我的帖子中。 – pencilslate 2009-08-10 03:30:02

+0

为了记录,如果您执行NOCHECK,然后按照您的建议进行CHECK,则检查和外键约束将不会在表数据上重新检查,并且它们将保持“不可信”并且不可由优化器使用。 如果你想重新检查数据,你必须说CHECK CHECK,不管你信不信! ALTER TABLE [name] CHECK CHECK CONSTRAINT ALL – 2009-08-10 04:14:47

+0

由于某种原因,NOCHECK仍然不允许我更改表格。听起来像,它更简单地执行列的alter语句,而不是删除和创建表。再次,我相信我需要删除和创建如果被修改的列有与之相关的约束。欣赏解释。谢谢! – pencilslate 2009-08-10 04:40:16