добавить столбец в таблицу MySQL, если он не существует
мои исследования и эксперименты не дали ответа, поэтому надеюсь на некоторую помощь.
Я изменяю установочный файл приложения, которое в предыдущих версиях не было столбца, который я хочу добавить сейчас. Я не хочу, чтобы добавить столбец вручную, но и в установочном файле и только если новый столбец не существует в таблице.
таблица создается следующим образом:
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.';
Если я добавлю следующее, ниже создать оператор таблицы, то я не уверен, что произойдет, если столбец уже существует (и, возможно, заполнен):
ALTER TABLE `#__comm_subscribers` ADD `subscriber_surname`;
ALTER TABLE `#__comm_subscribers` MODIFY `subscriber_surname` varchar(64) NOT NULL default '';
Итак, я попробовал следующее, что я нашел где-то. Это, кажется, не работает, но я не совсем уверен, что использовал его правильно.
/*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;*/
у кого-нибудь есть хороший способ сделать это?
15 ответов:
отметим, что
INFORMATION_SCHEMAНе поддерживается в MySQL до 5.0. Также хранимые процедуры не поддерживаются до 5.0, поэтому, если вам нужно поддерживать MySQL 4.1, это решение не очень хорошо.одно решение, используемое фреймворками, которые используют миграция базы данных - это запись в базе данных, номер версии схемы. Просто таблица с одним столбцом и одной строкой, с целым числом, указывающим, какая ревизия является текущей в действительности. Когда вы обновляете схему, увеличить число.
другое решение было бы просто попробовать the . Он должен выдать ошибку, если столбец уже существует.
ERROR 1060 (42S21): Duplicate column name 'newcolumnname'поймать ошибку и игнорировать ее в сценарии обновления.
вот рабочее решение (только что опробовал с MySQL 5.0 на Solaris):
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 client- более элегантный и лаконичный
SHOW COLUMNSне работает в хранимой процедуре, поэтому должны использовать INFORMATION_SCHEMA- в синтаксис для разграничения операторов является странным в MySQL, поэтому вы должны переопределите разделитель, чтобы иметь возможность создавать хранимые процедуры. Не забудьте переключить разделитель обратно!
- INFORMATION_SCHEMA является глобальным для всех баз данных, не забудьте фильтр на
TABLE_SCHEMA=DATABASE().DATABASE()возвращает имя выбранной базы данных.
большинство ответов касаются того, как безопасно добавить столбец в хранимую процедуру, мне нужно было добавить столбец в таблицу безопасно без использования сохраненного proc и обнаружил, что MySQL не позволяет использовать
IF Exists()за пределами SP. Я опубликую свое решение, что это может помочь кому-то в той же ситуации.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;
Если вы находитесь на MariaDB, нет необходимости использовать хранимые процедуры. Просто используйте, например:
ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name tinyint(1) DEFAULT 0;
другой способ сделать это было бы игнорировать ошибку с
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();;Я думаю, что его аккуратней, чем с
existsподзапрос. Особенно если у вас есть много столбцов для добавления, и вы хотите запустить скрипт несколько раз.дополнительную информацию о обработчиках продолжения можно найти по адресу http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html
Я использую MySQL 5.5.19.
мне нравится иметь скрипты, которые вы можете запускать и перезапускать без ошибок, особенно там, где предупреждения, похоже, задерживаются, снова появляются позже, когда я запускаю скрипты, у которых нет ошибок/предупреждений. Что касается добавления полей, я написал себе процедуру, чтобы сделать ее немного меньше набрав:
-- 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');код для создания addFieldIfNotExists процедура выглядит следующим образом:
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; $$Я не писал процедуру, чтобы безопасно изменить столбец, но я думаю, что описанная выше процедура может быть легко изменена для этого.
Я взял sproc OP и сделал его многоразовым и независимым от схемы. Очевидно, что он все еще требует 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 Docs показать, что символы-разделители не нужны одинарные кавычки.Итак, вы хотите:
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 :)
процедура от Джейка https://stackoverflow.com/a/6476091/6751901 это очень простое и хорошее решение для добавления новых столбцов, но с одной дополнительной строкой:
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();;
$smpt = $pdo->prepare("SHOW fields FROM __TABLE__NAME__"); $smpt->execute(); $res = $smpt->fetchAll(PDO::FETCH_ASSOC); //print_r($res);затем в $res по циклу найдите ключ вашего столбца Что-то вроде этого:
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; }
Ниже приведена хранимая процедура в MySQL для добавления столбцов в разные таблицы в разных базах данных, если столбец не существует в таблице базы данных со следующими преимуществами
- несколько столбцов могут быть добавлены использовать сразу, чтобы изменить несколько таблиц в разных базах данных
- выполняются три команды mysql, т. е. DROP, CREATE, CALL for Procedure
- имя базы данных должно быть изменено в соответствии с использованием в противном случае проблема может возникнуть для нескольких данные
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 '';
Comments