2013-10-31 84 views
1

我对此很陌生,所以我会尽力解释。我在表中有一个UNIQUE键,我希望通过添加另一列来改变它。mysql - 修改唯一密钥

所以,我有一个UNIQUE键 - UNIQUE_tablename_column1_column2。我的目标是放弃此密钥并创建一个名为 - UNIQUE_tablename_column1_column2_column3的新密钥。另外,如果需要的话,我正在寻求确保这可以一遍又一遍地运行。

我把基本的sql下来了,ALTER TABLE tablename DROP index UNIQUE_tablename_column1_column2,将drop掉原来的key。然后ALTER TABLE tablename ADD CONSTRAINT UNIQUE_tablename_column1_column2_column3 UNIQUE (column1,column2,column3)将添加我需要的新。

我想要做的就是把它放在某种IF/IF EXISTS THEN语句中,其中IF EXISTS UNIQUE_tablename_column1_column2然后DROP UNIQUE_tablename_column1_column2和ADD UNIQUE_tablename_column1_column2_column3。

任何想法,帮助和援助非常感谢。 谢谢!

回答

2

简短的回答是,您需要在存储过程中编写这样的逻辑,因为IF/ELSE结构只能在存储的程序中工作。

下面是我经常使用的两个示例脚本来删除和创建索引,首先检查是否存在。它支持任何类型的索引(唯一或非唯一)。

-- Use to create indexes via a CALL statement. Be sure to use DELIMITER when creating these 
-- procedures on your system: 

    CREATE PROCEDURE `admin_create_index`(
     index_name VARCHAR(64),  
     column_list VARCHAR(64), 
     table_name VARCHAR(64), 
     is_unique TINYINT(1), 
     db_name VARCHAR(64) 
    ) 
    BEGIN 
    SET @sqlexec := 
    CONCAT 
    (
     'SELECT @i := COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME = \'', 
     index_name, 
     '\' AND TABLE_NAME = \'', 
     table_name, 
     '\' AND TABLE_SCHEMA = \'', 
     db_name, 
     '\'' 
    ); 

    SELECT CONCAT('Executing: "', @sqlexec, '"') AS 'Info'; 
    PREPARE lookup FROM @sqlexec; 
    EXECUTE lookup; 
    DEALLOCATE PREPARE lookup; 

    IF @i = 0 THEN 
     SET @sqlexec := CONCAT('CREATE ', IF(is_unique > 0, 'UNIQUE ', ''), 'INDEX ', index_name, ' ON `', db_name, '`.`', table_name, '`(', column_list, ')'); 
     SELECT CONCAT('Executing: "', @sqlexec, '"') AS 'Info'; 
     PREPARE statement FROM @sqlexec; 
     EXECUTE statement; 
     DEALLOCATE PREPARE statement; 
     SELECT CONCAT('Successful execution of: "', @sqlexec, '"') AS 'Info'; 
    ELSE 
     SELECT CONCAT('Warning: Index `', index_name, '` already exists on `', db_name, '`.`', table_name, '`') AS 'Warning'; 
    END IF; 
    END; 

-- Use to drop an index (if it exists): 

CREATE PROCEDURE `admin_drop_index`(
    index_name VARCHAR(64),  
    table_name VARCHAR(64), 
    db_name VARCHAR(64) 
) 
BEGIN 
SET @sqlexec := 
CONCAT 
(
    'SELECT @i := COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME = \'', 
    index_name, 
    '\' AND TABLE_NAME = \'', 
    table_name, 
    '\' AND TABLE_SCHEMA = \'', 
    db_name, 
    '\'' 
); 

SELECT CONCAT('Executing: "', @sqlexec, '"') AS 'Info'; 
PREPARE lookup FROM @sqlexec; 
EXECUTE lookup; 
DEALLOCATE PREPARE lookup; 

IF @i > 0 THEN 
    SET @sqlexec := CONCAT('ALTER TABLE `', db_name, '`.`', table_name, '` DROP INDEX `', index_name, '`'); 
    SELECT CONCAT('Executing: "', @sqlexec, '"') AS 'Info'; 
    PREPARE statement FROM @sqlexec; 
    EXECUTE statement; 
    DEALLOCATE PREPARE statement; 
    SELECT CONCAT('Successful execution of: "', @sqlexec, '"') AS 'Info'; 
ELSE 
    SELECT CONCAT('Warning: Index `', index_name, '` does not exist on `', db_name, '`.`', table_name, '`') AS 'Warning'; 
END IF; 

END; 

而且这里的例子CALL声明:

CALL admin_create_index('my_index_name', 'col_name_a, col_name_b', 'table_name', TRUE, DATABASE()); 

CALL admin_drop_index('my_index_name', 'table_name', DATABASE()); 
+0

我很欣赏的响应。我将不得不尝试并报告! – Dubl1n