我无法删除索引,因为有些表将它用于外键
消息3723,级别16,状态6,行1显式DROP INDEX不是 允许索引'tbl1.ix_cox'。它被用于FOREIGN KEY 约束执行。
我试图在删除之前先禁用索引
ALTER INDEX ix_cox On tbl1
DISABLE
Go
但仍然无法放弃它。
我真的需要删除那些使用该索引的表上的外键吗?因为它大约有30张桌子。
答案 0 :(得分:6)
如果创建的索引定义了PRIMARY KEY或UNIQUE约束(https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-index-transact-sql?view=sql-server-2017),您将遇到相同的异常。
在那种情况下,简单的解决方案是改用ALTER-TABLE-command:
ALTER TABLE tbl1 DROP CONSTRAINT ix_cox
答案 1 :(得分:2)
恐怕这是你唯一的选择。您必须删除引用到表的所有外键约束,并且除非您在删除索引的表上指定另一个唯一索引,否则无法重新创建外键约束。
答案 2 :(得分:0)
您可以禁用临时存在的FK约束 - >删除索引 - >重新启用约束,如
ALTER TABLE your_fk_table NOCHECK CONSTRAINT constraint_name
drop index ids_name
ALTER TABLE your_fk_table CHECK CONSTRAINT constraint_name
答案 3 :(得分:0)
美好的一天,
这是一个完整的例子:
use tempdb
GO
-- NOTE!
-- This sample code presents a POOR CODING where the user
-- does not explicitly named the objects
-- or explicitly create CLUSTERED INDEX
DROP TABLE IF EXISTS dbo.Users_tbl;
DROP TABLE IF EXISTS dbo.Categories_tbl;
GO
CREATE TABLE dbo.Categories_tbl(
CategoryID INT IDENTITY(1,1) PRIMARY KEY
, CategoryName NVARCHAR(100)
)
GO
-- find the CLUSTERED INDEX created automatically for us
SELECT * FROM sys.indexes
WHERE object_id = OBJECT_ID('Categories_tbl')
GO
-- you can notice that by default the PRIMARY KEY become CLUSTERED INDEX
-- If we did not configure a different CLUSTERED INDEX
-- In my case the automatic name was: PK__Categori__19093A2BAE0EA4C3
-- Let's create the secondary table
CREATE TABLE dbo.Users_tbl(
UserID INT IDENTITY(1,1) PRIMARY KEY
, UserName NVARCHAR(100)
, CategoryID INT
, FOREIGN KEY (CategoryID) REFERENCES Categories_tbl(CategoryID)
)
GO
-- Insert sample data
INSERT Categories_tbl (CategoryName) VALUES ('a'),('b')
GO
INSERT Users_tbl(UserName,CategoryID)
VALUES ('a',1),('b',1)
GO
SELECT * FROM Categories_tbl
SELECT * FROM Users_tbl
GO
如果我们尝试删除PK的索引,则将收到此错误:
不允许在索引上使用显式的DROP INDEX。它正用于PRIMARY KEY约束实施。
解决方案是删除FK,删除PK,使用NONCLUSTERED索引而不是CLUSTERED索引创建新PK,然后创建FK
/************************************************ */
/********* REMOVE CLUSTERED INDEX from PRIMARY KEY */
/************************************************ */
------------------------------------------------------
-- Step 1: DROP the CONSTRAINTs
------------------------------------------------------
---- Get FOREIGN KEY name
SELECT DISTINCT OBJECT_NAME(f.constraint_object_id)
FROM sys.foreign_key_columns f
LEFT JOIN sys.indexes p ON p.object_id = f.referenced_object_id
WHERE p.object_id = OBJECT_ID('Categories_tbl')
GO
-- DROP FOREIGN KEY
ALTER TABLE dbo.Users_tbl
DROP CONSTRAINT FK__Users_tbl__Categ__59063A47 -- Use the name we found above
GO
---- Get PRIMARY KEY name
SELECT name FROM sys.indexes
WHERE object_id = OBJECT_ID('Categories_tbl')
GO
-- DROP PRIMARY KEY
ALTER TABLE dbo.Categories_tbl
DROP CONSTRAINT PK__Categori__19093A2B9F118674 -- Use the name we found above
GO
------------------------------------------------------
-- Step 2: CREATE new CONSTRAINTs
------------------------------------------------------
-- And now we can create new PRIMARY KEY NONCLUSTERED
-- Since we use PRIMARY KEY We need to have index,
-- but we do not have to use CLUSTERED INDEX
-- we can have NONCLUSTERED INDEX
ALTER TABLE dbo.Categories_tbl
ADD CONSTRAINT PK_CategoryID PRIMARY KEY NONCLUSTERED (CategoryID);
GO
-- Finaly we can create the
ALTER TABLE dbo.Users_tbl
ADD CONSTRAINT FK_Categories_tbl
FOREIGN KEY (CategoryID)
REFERENCES dbo.Categories_tbl(CategoryID)
GO
答案 4 :(得分:0)
好吧,如果您有30张桌子上的FK(例如EzLo),那么进行一些自动化肯定会很好。该视图最后两列中的脚本将删除并重新添加FK:
CREATE VIEW vwFK
AS
select *, addFK = 'ALTER TABLE '+FKtable+' WITH ' + case when is_not_trusted = 1 then 'NO' else '' end + 'CHECK'
+ ' ADD CONSTRAINT [FK_'+FKtbl+'_'+PKtbl+'] FOREIGN KEY ('+FKcol+') '
+ ' REFERENCES '+PKtable+' ('+PKcol+')'+' ON UPDATE '+onUpdate+' ON DELETE '+onDelete
+ case when is_not_for_replication = 1 then ' NOT FOR REPLICATION' else '' end + ';'
+ case when is_disabled = 1 then ' ALTER TABLE '+FKtable+' NOCHECK CONSTRAINT [FK_'+FKtbl+'_'+PKtbl+'];' else '' end
,dropFK = 'ALTER TABLE '+FKtable+' DROP ['+FK+'];'
from (
select
PKtable = object_schema_name(f.referenced_object_id)+'.'+object_name(f.referenced_object_id)
,PKtbl = object_name(f.referenced_object_id)
,PKcol = pc.name
,FKtable = object_schema_name(f.parent_object_id)+'.'+object_name(f.parent_object_id)
,FKtbl = object_name(f.parent_object_id)
,colseq = fk.constraint_column_id
,FKcol = fc.name
,FK = object_name(f.object_id)
,onUpdate = replace(f.update_referential_action_desc collate SQL_Latin1_General_CP1_CI_AS, '_', ' ')
,onDelete = replace(f.delete_referential_action_desc collate SQL_Latin1_General_CP1_CI_AS, '_', ' ')
,f.is_disabled
,f.is_not_trusted
,f.is_not_for_replication
from sys.foreign_key_columns as fk
join sys.foreign_keys f on fk.constraint_object_id = f.object_id
join sys.columns as fc on f.parent_object_id = fc.object_id and fk.parent_column_id = fc.column_id
join sys.columns as pc on f.referenced_object_id = pc.object_id and fk.referenced_column_id = pc.column_id
) t
不做任何保证,但是这些年来为我节省了很多的工作。 只需记住在运行dropFK之前保存addFK语句!