如果不存在,则将列添加到mysql表中

我的研究和实验还没有得到答案,所以我希望得到一些帮助。

我正在修改应用程序的安装文件,在以前的版本中没有我现在要添加的列。 我不想手动添加列,而是在安装文件中,只有在表中不存在新列的情况下。

该表格创build如下:

CREATE TABLE IF NOT EXISTS `#__comm_subscribers` ( `subscriber_id` int(11) NOT NULL auto_increment, `user_id` int(11) NOT NULL default '0', `subscriber_name` varchar(64) NOT NULL default '', `subscriber_surname` varchar(64) NOT NULL default '', `subscriber_email` varchar(64) NOT NULL default '', `confirmed` tinyint(1) NOT NULL default '0', `subscribe_date` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`subscriber_id`), UNIQUE KEY `subscriber_email` (`subscriber_email`) ) ENGINE=MyISAM CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' COMMENT='Subscribers for Comm are stored here.'; 

如果我在create table语句的下面添加以下内容,那么我不确定如果列已经存在(也许已经填充)会发生什么情况:

 ALTER TABLE `#__comm_subscribers` ADD `subscriber_surname`; ALTER TABLE `#__comm_subscribers` MODIFY `subscriber_surname` varchar(64) NOT NULL default ''; 

所以,我尝试了以下我find的地方。 这似乎没有工作,但我不完全确定我正确使用它。

 /*delimiter '//' CREATE PROCEDURE addcol() BEGIN IF NOT EXISTS( SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME='subscriber_surname' AND TABLE_NAME='#__comm_subscribers' ) THEN ALTER TABLE `#__comm_subscribers` ADD COLUMN `subscriber_surname` varchar(64) NOT NULL default ''; END IF; END; // delimiter ';' CALL addcol(); DROP PROCEDURE addcol;*/ 

有没有人有这样做的好方法?

请注意, INFORMATION_SCHEMA在5.0之前的MySQL中不受支持。 5.0之前的存储过程也不支持,所以如果你需要支持MySQL 4.1,这个解决scheme是不好的。

使用数据库迁移的框架使用的一种解决scheme是在数据库中logging模式的修订号。 只是一个单列和单行的表,用一个整数表示哪个版本是当前有效的。 更新架构时,增加数字。

另一种解决方法是只尝试 ALTER TABLE ADD COLUMN命令。 如果列已经存在,它应该会抛出一个错误。

 ERROR 1060 (42S21): Duplicate column name 'newcolumnname' 

抓住错误,并在升级脚本中忽略它。

这是一个可行的解决scheme(刚刚在Solaris上使用MySQL 5.0):

 DELIMITER $$ DROP PROCEDURE IF EXISTS upgrade_database_1_0_to_2_0 $$ CREATE PROCEDURE upgrade_database_1_0_to_2_0() BEGIN -- rename a table safely IF NOT EXISTS( (SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='my_old_table_name') ) THEN RENAME TABLE my_old_table_name TO my_new_table_name, END IF; -- add a column safely IF NOT EXISTS( (SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND COLUMN_NAME='my_additional_column' AND TABLE_NAME='my_table_name') ) THEN ALTER TABLE my_table_name ADD my_additional_column varchar(2048) NOT NULL DEFAULT ''; END IF; END $$ CALL upgrade_database_1_0_to_2_0() $$ DELIMITER ; 

乍一看,它可能看起来比它应该更复杂,但我们必须在这里处理以下问题:

  • IF语句只能在存储过程中使用,而不能在直接运行时使用,例如在mysql客户端中
  • 更优雅和简洁的SHOW COLUMNS在存储过程中不起作用,所以必须使用INFORMATION_SCHEMA
  • 在MySQL中定界语句的语法很奇怪,所以你必须重新定义定界符才能创build存储过程。 不要忘记将分隔符切换回来!
  • INFORMATION_SCHEMA是所有数据库的全局数据库,不要忘记在TABLE_SCHEMA=DATABASE()上进行过滤。 DATABASE()返回当前select的数据库的名称。

大多数的答案解决了如何在存储过程中安全地添加一列,我需要安全地添加一列到一个表,而不使用存储过程,并发现MySQL不允许在SP之外使用IF Exists() 。 我会发布我的解决scheme,它可能会帮助在相同的情况下的人。

 SELECT count(*) INTO @exist FROM information_schema.columns WHERE table_schema = database() and COLUMN_NAME = 'original_data' AND table_name = 'mytable'; set @query = IF(@exist <= 0, 'alter table intent add column mycolumn4 varchar(2048) NULL after mycolumn3', 'select \'Column Exists\' status'); prepare stmt from @query; EXECUTE stmt; 

另一种方法是使用declare continue handler来忽略错误:

 delimiter ;; create procedure foo () begin declare continue handler for 1060 begin end; alter table atable add subscriber_surname varchar(64); end;; call foo();; 

我认为它比整洁的子查询更整洁。 特别是如果你有很多列要添加,而且你想多次运行这个脚本。

继续处理程序的更多信息可以在http://dev.mysql.com/doc/refman/5.0/en/declare-handler.htmlfind。;

如果你在MariaDB上,不需要使用存储过程。 只要使用,例如:

 ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name tinyint(1) DEFAULT 0; 

看这里

我正在使用MySQL 5.5.19。

我喜欢有可以运行并且没有错误地重新运行的脚本,特别是在警告似乎徘徊的时候,当我运行没有错误/警告的脚本时,再次显示。 至于添加字段,我写了一个程序,使它less一点打字:

 -- add fields to template table to support ignoring extra data -- at the top/bottom of every page CALL addFieldIfNotExists ('template', 'firstPageHeaderEndY', 'INT NOT NULL DEFAULT 0'); CALL addFieldIfNotExists ('template', 'pageHeaderEndY', 'INT NOT NULL DEFAULT 0'); CALL addFieldIfNotExists ('template', 'pageFooterBeginY', 'INT NOT NULL DEFAULT 792'); 

创buildaddFieldIfNotExists过程的代码如下所示:

 DELIMITER $$ DROP PROCEDURE IF EXISTS addFieldIfNotExists $$ DROP FUNCTION IF EXISTS isFieldExisting $$ CREATE FUNCTION isFieldExisting (table_name_IN VARCHAR(100), field_name_IN VARCHAR(100)) RETURNS INT RETURN ( SELECT COUNT(COLUMN_NAME) FROM INFORMATION_SCHEMA.columns WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = table_name_IN AND COLUMN_NAME = field_name_IN ) $$ CREATE PROCEDURE addFieldIfNotExists ( IN table_name_IN VARCHAR(100) , IN field_name_IN VARCHAR(100) , IN field_definition_IN VARCHAR(100) ) BEGIN -- http://javajon.blogspot.com/2012/10/mysql-alter-table-add-column-if-not.html SET @isFieldThere = isFieldExisting(table_name_IN, field_name_IN); IF (@isFieldThere = 0) THEN SET @ddl = CONCAT('ALTER TABLE ', table_name_IN); SET @ddl = CONCAT(@ddl, ' ', 'ADD COLUMN') ; SET @ddl = CONCAT(@ddl, ' ', field_name_IN); SET @ddl = CONCAT(@ddl, ' ', field_definition_IN); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; $$ 

我没有编写一个程序来安全地修改一个列,但我认为上述过程可以很容易地修改。

我已经采取了OP的sproc,并使其可重用和架构独立。 显然它仍然需要MySQL 5。

 DROP PROCEDURE IF EXISTS AddCol; DELIMITER // CREATE PROCEDURE AddCol( IN param_schema VARCHAR(100), IN param_table_name VARCHAR(100), IN param_column VARCHAR(100), IN param_column_details VARCHAR(100) ) BEGIN IF NOT EXISTS( SELECT NULL FROM information_schema.COLUMNS WHERE COLUMN_NAME=param_column AND TABLE_NAME=param_table_name AND table_schema = param_schema ) THEN set @paramTable = param_table_name ; set @ParamColumn = param_column ; set @ParamSchema = param_schema; set @ParamColumnDetails = param_column_details; /* Create the full statement to execute */ set @StatementToExecute = concat('ALTER TABLE `',@ParamSchema,'`.`',@paramTable,'` ADD COLUMN `',@ParamColumn,'` ',@ParamColumnDetails); /* Prepare and execute the statement that was built */ prepare DynamicStatement from @StatementToExecute ; execute DynamicStatement ; /* Cleanup the prepared statement */ deallocate prepare DynamicStatement ; END IF; END // DELIMITER ; 

刚刚尝试了存储过程脚本。 似乎问题是围绕分隔符'标记。 MySQL文档显示分隔符不需要单引号。

所以你要:

 delimiter // 

代替:

 delimiter '//' 

适用于我:)

如果你正在脚本中运行这个脚本,那么你需要添加下面这行代码,使它可以重新运行,否则你会得到一个已经存在的程序错误。

 drop procedure foo; 

在PHP> PDO中添加列的最佳方法是:

 $Add = $dbh->prepare("ALTER TABLE `YourCurrentTable` ADD `YourNewColumnName` INT NOT NULL"); $Add->execute(); 

注意:表中的列是不可重复的,这意味着我们不需要检查列的存在,但为了解决问题,我们检查上面的代码:

例如,如果它工作警报1,如果不是0,这意味着列存在! 🙂

检查PDO中是否存在列(100%)

 { if(isset($_POST['Add'])) { $ColumnExist = $dbh->prepare("SELECT * FROM ColumnChecker where column_name='$insert_column_name' LIMIT 1"); $ColumnExist ->execute(); $ColumnName = $ColumnExist->fetch(2); $Display_Column_Name = $ColumnName['column_name']; if($Display_Column_Name == $insert_column_name) { echo "$Display_Column_Name already exist"; } //***************************** else { $InsertColumn = $dbh->prepare("insert into ColumnChecker ( column_name ) values ('$insert_column_name')"); $InsertColumn->execute(); if($InsertColumn) { $Add = $dbh->prepare("ALTER TABLE `$Table` ADD `$insert_column_name` $insert_column_type($insert_column_Length) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL "); $Add->execute(); if($Add) { echo 'Table has been updated'; } else { echo 'Sorry! Try again...'; } } } } }#Add Column into Table :) 
 $smpt = $pdo->prepare("SHOW fields FROM __TABLE__NAME__"); $smpt->execute(); $res = $smpt->fetchAll(PDO::FETCH_ASSOC); //print_r($res); 

然后在$ res循环中寻找你的列键Smth就像这样:

  if($field['Field'] == '_my_col_'){ return true; } + **Below code is good for checking column existing in the WordPress tables:** public static function is_table_col_exists($table, $col) { global $wpdb; $fields = $wpdb->get_results("SHOW fields FROM {$table}", ARRAY_A); foreach ($fields as $field) { if ($field['Field'] == $col) { return TRUE; } } return FALSE; } 

来自Jake的程序https://stackoverflow.com/a/6476091/6751901是添加新列的非常简单和好的解决scheme,但是增加了一行:;

 DROP PROCEDURE IF EXISTS foo;; 

您可以在稍后添加新列,并且也可以在下次使用:

 delimiter ;; DROP PROCEDURE IF EXISTS foo;; create procedure foo () begin declare continue handler for 1060 begin end; alter table atable add subscriber_surname varchar(64); alter table atable add subscriber_address varchar(254); end;; call foo();; 

以下是MySQL中的存储过程:如果数据库中不存在列,则在不同数据库中的不同表中添加列(一个或多个)具有以下优点

  • 可以一次添加多个列来更改不同数据库中的多个表
  • 三个mysql命令运行,即DROP,CREATE,CALL For Procedure
  • 数据库名称应根据USE更改,否则可能会出现多个数据的问题
 DROP PROCEDURE IF EXISTS `AlterTables`; DELIMITER $$ CREATE PROCEDURE `AlterTables`() BEGIN DECLARE table1_column1_count INT; DECLARE table2_column2_count INT; SET table1_column1_count = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'DATABASE_NAME' AND TABLE_NAME = 'TABLE_NAME1' AND COLUMN_NAME = 'TABLE_NAME1_COLUMN1'); SET table2_column2_count = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'DATABASE_NAME' AND TABLE_NAME = 'TABLE_NAME2' AND COLUMN_NAME = 'TABLE_NAME2_COLUMN2'); IF table1_column1_count = 0 THEN ALTER TABLE `TABLE_NAME1`ADD `TABLE_NAME1_COLUMN1` text COLLATE 'latin1_swedish_ci' NULL AFTER `TABLE_NAME1_COLUMN3`,COMMENT='COMMENT HERE'; END IF; IF table2_column2_count = 0 THEN ALTER TABLE `TABLE_NAME2` ADD `TABLE_NAME2_COLUMN2` VARCHAR( 100 ) NULL DEFAULT NULL COMMENT 'COMMENT HERE'; END IF; END $$ DELIMITER ; call AlterTables(); 
 ALTER TABLE `subscriber_surname` ADD IF NOT EXISTS `#__comm_subscribers`.`subscriber_surname`; ALTER TABLE `#__comm_subscribers` MODIFY `subscriber_surname` varchar(64) NOT NULL default '';