MySQL: ALTER TABLE if column not exists
Asked Answered
B

12

101

I have this code:

ALTER TABLE `settings`
ADD COLUMN `multi_user` TINYINT(1) NOT NULL DEFAULT 1

And I want to alter this table only if this column doesn't exist.

I'm trying a lot of different ways, but nothing works:

ALTER TABLE `settings`
ADD COLUMN IF NOT EXISTS `multi_user` TINYINT(1) NOT NULL DEFAULT 1

With procedure:

DELIMITER $$
CREATE PROCEDURE Alter_Table()
BEGIN
    DECLARE _count INT;
    SET _count = (  SELECT COUNT(*) 
                    FROM INFORMATION_SCHEMA.COLUMNS
                    WHERE   TABLE_NAME = 'settings' AND 
                            COLUMN_NAME = 'multi_user');
    IF _count = 0 THEN
        ALTER TABLE `settings` ADD COLUMN `multi_user` TINYINT(1) NOT NULL DEFAULT 1
    END IF;
END $$
DELIMITER ; 

I got error in END IF, then in END and then in 1

How can I make this as simple as possible?

Breastfeed answered 4/7, 2014 at 9:57 Comment(5)
possible duplicate of MySQL add column if not existMicra
possible duplicate of MySQL: How to add a column if it doesn't already exist?Grateful
I've tried this answer! i got errorsBreastfeed
Worth mentioning that MariaDB allows ALTER TABLE tablename ADD COLUMN IF NOT EXISTS columnname columntype;.Mantelet
possible duplicate #973422Saskatchewan
H
86

Use the following in a stored procedure:

IF NOT EXISTS( SELECT NULL
            FROM INFORMATION_SCHEMA.COLUMNS
           WHERE table_name = 'tablename'
             AND table_schema = 'db_name'
             AND column_name = 'columnname')  THEN

  ALTER TABLE `TableName` ADD `ColumnName` int(1) NOT NULL default '0';

END IF;
Halfassed answered 3/4, 2015 at 8:33 Comment(3)
"[I]n a stored procedure" is worth restating here. The above is valid T-SQL on its own, and using mostly that for the last couple of years, I was banging my head for a little bit before re-reading this post.Publicness
So how would you do it in an adhoc script for example? This answer would work nicely in sql server, but MySql is being a real pain for me?!?!Bus
any more simple way for managing bulk columns inserting and avoid dublicationsAldercy
M
64

Use PREPARE/EXECUTE and querying the schema. The host doesn't need to have permission to create or run procedures :

SET @dbname = DATABASE();
SET @tablename = "tableName";
SET @columnname = "colName";
SET @preparedStatement = (SELECT IF(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " INT(11);")
));
PREPARE alterIfNotExists FROM @preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;
Martins answered 13/8, 2015 at 13:23 Comment(2)
1+ I did using it, but xperienced some trouble with php, but nevertheless I like this approach. dba.stackexchange.com/questions/160476/…Thekla
I'm following this solution but got some error, please help. #60000379Tanjatanjore
E
59

Here is a solution that does not involve querying INFORMATION_SCHEMA, it simply ignores the error if the column does exist.

DROP PROCEDURE IF EXISTS `?`;
DELIMITER //
CREATE PROCEDURE `?`()
BEGIN
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
  ALTER TABLE `table_name` ADD COLUMN `column_name` INTEGER;
END //
DELIMITER ;
CALL `?`();
DROP PROCEDURE `?`;

P.S. Feel free to give it other name rather than ?

Emend answered 7/8, 2017 at 13:24 Comment(7)
I am surprised this answer is not better ranked. Is there any reason for that? Looks elegant to me.Hartz
With this stored procedure I get to save resources for first checking if a table exists. Awesome answer, this should be voted as the best answer.Emotive
this works fine when I execute it in mysql workbench but does not work when I execute it in code using mysqli_query() :( Any ideas?Lustihood
@johnktejik try calling mysqli_query() 4 times, one for each command individually: line 1, lines 3-7 (omitting the // delimiter from line 7), line 9, and line 10.Emend
@Hartz perhaps because this will skip ANY exception, not only when column_name already exists. answer by Harsh will not suppress any exceptions.Outrageous
the only answer that worked for meGerger
@johnk adding to @Hartz comment, converting lines 2 through 7 to a one-liner should work (did for my particular case)... DELIMITER // CREATE PROCEDURE `?`() BEGIN DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; ALTER TABLE `table_name` ADD COLUMN `column_name` INTEGER; END // DELIMITER ;Persona
T
12

Add field if not exist:

CALL addFieldIfNotExists ('settings', 'multi_user', 'TINYINT(1) NOT NULL DEFAULT 1');

addFieldIfNotExists code:

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

    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;
$$
Tarratarradiddle answered 24/11, 2018 at 15:0 Comment(0)
C
9

I used this approach (Without using stored procedure):

SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tbl_name' AND COLUMN_NAME = 'column_name'

If it didnt return any rows then the column doesn't exists then alter the table:

ALTER TABLE tbl_name ADD COLUMN column_name TINYINT(1) NOT NULL DEFAULT 1

Hope this helps.

Churchly answered 26/9, 2018 at 12:33 Comment(0)
M
5

hope this will help you

SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
AND table_schema = 'db_name'
AND column_name = 'column_name'

or

delimiter '//'

CREATE PROCEDURE addcol() BEGIN
IF NOT EXISTS(
SELECT * FROM information_schema.COLUMNS
WHERE COLUMN_NAME='new_column' AND TABLE_NAME='tablename' AND TABLE_SCHEMA='the_schema'
)
THEN
    ALTER TABLE `the_schema`.`the_table`
    ADD COLUMN `new_column` TINYINT(1) NOT NULL DEFAULT 1;;

END IF;
END;
//

delimiter ';'

CALL addcol();

DROP PROCEDURE addcol;
Mizzen answered 4/7, 2014 at 10:2 Comment(0)
F
2
$sql="SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Your_Table_Name' AND COLUMN_NAME = 'Your_New_Column_Name'";
$RESULT = mysqli_query($conn,$sql);

The abobe query return 0 if the column is not present in your table then you need to run alter query like below

if($RESULT){
    $sqll="ALTER TABLE Your_table_Name ADD COLUMN Your_New_Column_Name varchar(20) NOT NULL DEFAULT 0";
}
Fiddlewood answered 26/8, 2019 at 10:21 Comment(0)
S
1
SET @dbname = DATABASE();
SET @tablename = "table";
SET @columnname = "fieldname";
SET @preparedStatement = (SELECT IF(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " DECIMAL(18,4) NULL;")
));
PREPARE alterIfNotExists FROM @preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists; 
Spinney answered 10/7, 2018 at 13:22 Comment(0)
S
1

This below worked for me:

    SELECT count(*)
    INTO @exist
    FROM information_schema.columns
    WHERE table_schema = 'mydatabase'
    and COLUMN_NAME = 'mycolumn'
    AND table_name = 'mytable' LIMIT 1;

    set @query = IF(@exist <= 0, 'ALTER TABLE mydatabase.`mytable`  ADD COLUMN `mycolumn` MEDIUMTEXT NULL',
    'select \'Column Exists\' status');

    prepare stmt from @query;

    EXECUTE stmt;
Seay answered 15/2, 2021 at 6:17 Comment(0)
G
1

Simplified:

ALTER TABLE my_table ADD COLUMN IF NOT EXISTS my_column VARCHAR(255);
Gramercy answered 13/6, 2023 at 20:48 Comment(6)
This won't work, have you tested this in mysql?Tripterous
@AnkitJindal It will works, this is valid on both mysql / mariadbJanuary
@January I have tried running on my system and it gives me this error - #1064 - You have an error in your SOL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF NOT EXISTS my column VARCHAR (255) ' at line 1Tripterous
@AnkitJindal it's available since years, which is your mysql version ? did you server stayed block in 2010's ?January
@AnkitJindal Yes I had.Gramercy
In MySQL 8.0.30, this doesn't work.Locomotion
S
0

Sometimes it may happen that there are multiple schema created in a database.

So to be specific schema we need to target, so this will help to do it.

SELECT count(*) into @colCnt FROM information_schema.columns WHERE table_name = 'mytable' AND column_name = 'mycolumn' and table_schema = DATABASE();
IF @colCnt = 0 THEN
    ALTER TABLE `mytable` ADD COLUMN `mycolumn` VARCHAR(20) DEFAULT NULL;
END IF;
Sarson answered 15/12, 2020 at 12:40 Comment(0)
I
0

Using this as an example: https://dbabulletin.com/index.php/2018/03/29/best-practices-using-flyway-for-database-migrations/

DELIMITER $$

DROP PROCEDURE IF EXISTS upgrade_database_4_to_5 $$

CREATE PROCEDURE upgrade_database_4_to_5()

BEGIN



IF NOT EXISTS( (SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE()

AND COLUMN_NAME='multi_user' AND TABLE_NAME='settings') ) THEN

ALTER TABLE `settings` ADD COLUMN `multi_user` TINYINT(1) NOT NULL DEFAULT 1;

END IF;



END $$

CALL upgrade_database_4_to_5() $$

DELIMITER ;
Invasion answered 5/1, 2023 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.