我的表格中有以下索引/唯一约束。
[ApiVersion1RoutePrefix("tests")]
public class TestController : ApiController
{
[Route("PackageDropOffLocation/{}")]
[HttpPut]
[HttpPatch]
public IHttpActionResult PackageDropOffLocation(HttpRequestMessage, PackageDropOffLocationRequest packageDropOffLocationRequest)
{
return null;
}
[Route("PackageOnBoard")]
[HttpPut]
[HttpPatch]
public IHttpActionResult PackageBoarded(HttpRequestMessage requestMessage, PackageBoardedRequest packageBoardedRequest)
{
return null;
}
}
public class PackageBoardedRequest
{
public string PackageId { get; set; }
}
public class PackageDropOffLocationRequest
{
public string Id { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
}
现在我在我的darabase上运行以下代码段。
INDNAME COLNAMES
SQL160215110206240 +ID
SQL160215110206360 +ENTITY_TYPE+TENANT_ID+ENTITY_LOCAL_USERSTORE+ENTITY_NAME
SQL160215145445420 +ENTITY_TYPE+TENANT_ID+ENTITY_LOCAL_USERSTORE+ENTITY_NAME+PROVISIONING_CONFIG_ID
当我第一次运行时,我得到了以下回应。
BEGIN
DECLARE v_rcount VARCHAR(128);
DECLARE STMT VARCHAR(200);
select INDNAME into v_rcount from SYSCAT.INDEXES WHERE TABNAME='IDP_PROVISIONING_ENTITY' AND COLNAMES='+ENTITY_TYPE+TENANT_ID+ENTITY_LOCAL_USERSTORE+ENTITY_NAME';
SET STMT = 'ALTER TABLE IDP_PROVISIONING_ENTITY DROP CONSTRAINT ' || v_rcount;
PREPARE S1 FROM STMT;
EXECUTE S1;
END
但是当我列出表的索引时,我仍然像以前一样看到所有3个索引。
此外,当我再次运行相同的代码段时,我收到了以下错误。
DB20000I The SQL command completed successfully.
不仅是这个索引,如果我尝试删除同一个数据库中的任何其他索引,我也会得到同样的错误。这是什么原因?我怎么解决这个问题?
答案 0 :(得分:0)
这个问题的原因是,我从SYSCAT.INDEXES获取名称。所以它返回了INDEX的名称。即使为每个唯一约束创建了INDEX,索引的名称也可以与Constraint的名称不同。所以这里我放弃了约束,然后我检查了索引表是否已删除。这就是为什么我在删除约束后仍能看到相同的索引名称的原因。
SYSCAT.INDEXES中的每个索引名称也不会引用约束。因此,每次使用SYSCAT.INDEXES中的名称运行DROP CONSTRAINT都不会返回成功。
答案 1 :(得分:0)
与约束和索引的其他众所周知的数据库相比,IBM DB2的行为略有不同。因此,让我详细解释您的问题的解决方案。
您有下表。
CREATE TABLE IDP_PROVISIONING_ENTITY ( ID INTEGER NOT NULL, PROVISIONING_CONFIG_ID INTEGER NOT NULL, ENTITY_TYPE VARCHAR(255) NOT NULL, ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, ENTITY_NAME VARCHAR(255) NOT NULL, ENTITY_VALUE VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, PRIMARY KEY (ID), UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE) /
它有一个主键和两个唯一约束。 DB2将自动为这三个约束创建索引。
问题是,我们没有将约束定义为命名约束。因此,我们需要额外努力找出索引的名称以及DB2自动生成的约束。
这是我们在表格中的两个唯一约束。
UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME),
UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE)
通过运行以下查询,您可以找到唯一约束的自动生成的名称。对于唯一约束,constraintyp ='U',对于主键,它是'P'。 db2“从sysibm.systabconst中选择NAME,其中tbname ='IDP_PROVISIONING_ENTITY'和constraintyp ='U'”
NAME -------- SQL160219074557840 SQL160219074557920
以上是我得到的结果。您将在数据库中获得不同的值,因为这些值是随机生成的。
您可以运行以下查询以查看为IDP_PROVISIONING_ENTITY表创建的索引。 db2“SELECT NAME,COLNAMES FROM SYSIBM.SYSINDEXES WHERE TBNAME ='IDP_PROVISIONING_ENTITY'”
NAME COLNAMES SQL160219074557290 +ID SQL160219074557790 +PROVISIONING_CONFIG_ID+ENTITY_TYPE+ENTITY_VALUE SQL160219074557860 +ENTITY_TYPE+TENANT_ID+ENTITY_LOCAL_USERSTORE+ENTITY_NAME
现在我们知道两个唯一约束的约束名称和IDP_PROVISIONING_ENTITY表的索引名称。
您可以通过为上述查询添加where子句来找到需要删除的特定索引,如下所示。 db2“从SYSIBM.SYSINDEXES中选择名称,其中TBNAME ='IDP_PROVISIONING_ENTITY'和COLNAMES ='+ ENTITY_TYPE + TENANT_ID + ENTITY_LOCAL_USERSTORE + ENTITY_NAME'”
NAME ---------- SQL160219074557860
在IBM DB2中,您不能直接删除为约束(主键或唯一)生成的索引。为此,您需要删除将删除索引的约束。
但问题是我们不知道与索引“+ ENTITY_TYPE + TENANT_ID + ENTITY_LOCAL_USERSTORE + ENTITY_NAME”相关联的唯一约束的名称是什么。我们已经知道我们需要删除的索引名是SQL160219074557860。
通过运行以下查询,您可以找到哪个约束与哪个索引相关联。 db2“从SYSCAT.CONSTDEP中选择CONSTNAME,BNAME,其中TABNAME ='IDP_PROVISIONING_ENTITY'”
CONSTNAME BNAME SQL160219074557790 SQL160219074557290 SQL160219074557840 SQL160219074557790 SQL160219074557920 SQL160219074557860
根据结果,您可以了解约束的名称。 因此,与索引名称“SQL160219074557860”关联的约束名称为“SQL160219074557920”。
因为我们现在知道约束名称,所以我们可以删除唯一约束。 db2“ALTER TABLE IDP_PROVISIONING_ENTITY DROP UNIQUE SQL160219074557920” 这将删除约束以及为约束创建的索引。