【问题标题】:Drop indexes or alter删除索引或更改
【发布时间】:2016-05-23 18:54:55
【问题描述】:

我正在尝试在 informatica 中删除目标表上的 pk 约束和删除索引,以下这些语句第一次成功运行。

IF EXISTS (SELECT Name FROM sysindexes WHERE Name = 'xyz') 
DROP INDEX [xyz] ON [dbo].[Table_Name];

IF EXISTS (SELECT Name FROM sysindexes WHERE Name = 'xyz')
ALTER TABLE [dbo].[Table_Name] DROP CONSTRAINT [xyz];

但是如果我第二次运行相同的查询,它会给出一个错误:

无法删除索引“dbo.Table_Name.xyz”,因为它不存在或您没有权限

我需要一个 If ... Else 语句语法,例如 if exists drop else end 或success something。

【问题讨论】:

  • 解析器看到你试图删除一个不存在的索引,但它不够聪明,无法遵循你的 IF 逻辑。使用动态 SQL (IF EXISTS (...) EXEC sys.sp_executesql N'DROP INDEX ...';)。此外,使用sys.indexes 而不是已弃用的sysindexes,并确保您确定索引属于该表(在另一个表上也可能有一个名为xyz 的索引)。

标签: sql sql-server


【解决方案1】:

造成这种情况的可能原因是您的数据库中可能有多个名为xyz 的索引。您的 IF EXISTS SELECT 语句未考虑 whichxyz 处于打开状态。

您可以自己运行 select 语句来检查这种情况。

尝试将您的查询更改为以下内容以限制范围:

If Exists 
(
    Select * 
    From   sys.indexes 
    Where  name = 'xyz' 
    And    Object_Id = Object_Id('dbo.Table_Name')
)
Drop Index xyz On dbo.Table_Name;

【讨论】:

  • 不,虽然这在技术上更好,但它并不能解决由非智能解析器引起的鸡和蛋问题。
  • @AaronBertrand ... 或者缺少“如果存在则删除”的语法;)。
  • @AaronBertrand 我不同意。如果他在同一个数据库中有两个索引名称相同,那么他的IF EXISTS 语句仍然会返回为真。 然后它会尝试删除Table_Name 上的索引。如果在EXISTS 语句中不包括表,并且两个索引名称相同,他会得到那个错误。我怀疑这就是这里发生的事情。
  • 嘿 siyual,上面的命令对我有用,对不起,我的错误有两个以上的索引但名称不同,但是当我发布问题时,我使用了相同的索引名称,但我的目的如果不存在仍然成功。非常感谢您的帮助
  • @Gordon 在 2016 年你可以说 DROP INDEX IF EXISTS xyz ON dbo.abc;
【解决方案2】:

解决此问题的一种方法是欺骗解析器:

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE SCHEMA_NAME = 'dbo' AND TABLE_NAME = 'Table_Name' AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME = 'xyz')
BEGIN
    EXEC('ALTER TABLE [dbo].[Table_Name] DROP CONSTRAINT [xyz]')
END

【讨论】:

  • 好吧,这实际上不起作用,因为 (1) 数据库中不能有两个名为 xyz 的主键,并且 (2) OBJECT_ID 函数可能正在识别一个 pk on另一个表,在这种情况下,EXEC() 仍将运行。
  • (1) 你的意思是什么? (2) 您是否尝试过将两个同名的 PK 放在同一个数据库中?不可能有两个,因为 SQL Server 不允许您将两个 PK 命名为相同的东西,即使它们位于不同的表上。
  • @AaronBertrand pk 的名称不同,但在上面我以它为例,我有多个不同名称的 pk。
  • (1) 我的观点是使用 PK 作为对象类型不是很有用(OP 没有 PK)。 (2) 当然,这就是我所说的。
  • 不过,我的主要观点是,如果您使用 OBJECT_ID 之类的东西来识别某物是否存在,您无法确定它是否存在于正确的表中。例如,创建此表:CREATE TABLE dbo.OtherTable(id int, CONSTRAINT xyz PRIMARY KEY(id)); 现在运行您的代码。 EXEC() 仍然运行,因为 OBJECT_ID() 返回了一个有效值,但由于它来自不同的表而失败。
猜你喜欢
  • 1970-01-01
  • 2011-06-17
  • 2015-08-11
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多