2016-01-07 162 views
4

时,请参见下面的DDL:错误减少VARCHAR长度

CREATE TABLE Person 
(
    ID int identity not null, 
    Name VARCHAR(100), 
    Age int, 
    EyeColour varchar(20), 
    primary key (ID) 
) 

CREATE INDEX Name ON Person (Name) 
CREATE INDEX Age ON Person (Age) 
CREATE INDEX EyeColour ON Person (EyeColour) 

我可以执行以下语句:

ALTER TABLE person 
ALTER COLUMN name VARCHAR(110) 

但是,我不能执行以下语句:

ALTER TABLE person 
ALTER COLUMN name VARCHAR(90) 

错误是:

消息5074,级别16,状态1,行1
索引'名称'依赖于'名称'列。

消息4922,级别16,状态9,行1
ALTER TABLE ALTER COLUMN名称失败,因为一个或多个对象访问此列。

为什么我在减少VARCHAR的长度时看到这些错误。在其他情况下,我会看到这个错误,例如改变数据类型?

是否有一种自动方式来识别受数据类型变化影响并处理它们的所有索引和约束?

+0

你真的需要索引所有三个领域,还是只是一个简单的例子? – HardCode

+1

删除索引,修改表格,创建索引...赚取利润。 – Hackerman

+0

@HardCode,是的,它是简化的,所以我可以得到我的观点。 – w0051977

回答

0

你肯定可以自动识别部分。这是一个脚本,它将根据表格列找到所有的索引和外键(我已经发现检查约束作为读者的练习)。由于它是一个脚本,所以在运行时必须更改参数。你也可以把它变成一个存储过程。

但是,我不建议自动执行诸如删除索引或约束等操作。根据您对使用这些数据的应用程序的了解,您最好审查输出并确定是否真的可以减小列的大小。

-- parameters 
DECLARE 
    @nm_schema sysname = N'Purchasing', 
    @nm_table sysname = N'PurchaseOrderHeader', 
    @nm_column sysname = N'EmployeeID'; 

DECLARE 
    @id_table int, 
    @id_column smallint; 

SELECT @id_table = o.object_id 
    FROM sys.objects o 
    JOIN sys.schemas s 
     ON o.schema_id = s.schema_id 
    WHERE o.name = @nm_table 
     AND s.name = @nm_schema 
     AND o.type = 'U'; 

IF @@ROWCOUNT = 0 
BEGIN 
    RAISERROR(N'Schema %s table %s not found', 0, 1, @nm_schema, @nm_table); 
    RETURN; 
END; 

SELECT @id_column = column_id 
    FROM sys.columns 
    WHERE object_id = @id_table 
     AND name = @nm_column; 

IF @@ROWCOUNT = 0 
BEGIN 
    RAISERROR(N'Column %s not found in schema %s table %s', 0, 2, @nm_column, @nm_schema, @nm_table); 
    RETURN; 
END; 

SELECT 'Index' AS 'dependency', i.name 
    FROM sys.indexes i 
    JOIN sys.index_columns ic 
     ON i.object_id = ic.object_id 
     AND i.index_id = ic.index_id 
    WHERE i.object_id = @id_table 
     AND ic.column_id = @id_column 
     AND NOT i.type = 0 -- heap 
UNION ALL 
SELECT 'FKey', f.name 
    FROM sys.foreign_keys f 
    JOIN sys.foreign_key_columns fc 
     ON f.object_id = fc.constraint_object_id 
    WHERE (f.parent_object_id = @id_table AND fc.parent_column_id = @id_column) 
     OR (f.referenced_object_id = @id_table AND fc.referenced_column_id = @id_column);