如果不存在,则将列添加到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 '';