104

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?

5

11 Answers 11

89

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;
Sign up to request clarification or add additional context in comments.

3 Comments

"[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.
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?!?!
any more simple way for managing bulk columns inserting and avoid dublications
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;

2 Comments

1+ I did using it, but xperienced some trouble with php, but nevertheless I like this approach. dba.stackexchange.com/questions/160476/…
I'm following this solution but got some error, please help. stackoverflow.com/questions/59999879/…
60

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 ?

7 Comments

I am surprised this answer is not better ranked. Is there any reason for that? Looks elegant to me.
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.
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?
@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.
@rain_ perhaps because this will skip ANY exception, not only when column_name already exists. answer by Harsh will not suppress any exceptions.
|
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;
$$

Comments

10

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.

Comments

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;

Comments

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";
}

Comments

2

Simplified:

ALTER TABLE my_table ADD COLUMN IF NOT EXISTS my_column VARCHAR(255);

6 Comments

This won't work, have you tested this in mysql?
@AnkitJindal It will works, this is valid on both mysql / mariadb
@Paul-Marie 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 1
@AnkitJindal it's available since years, which is your mysql version ? did you server stayed block in 2010's ?
@AnkitJindal Yes I had.
|
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;

Comments

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;

Comments

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 ;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.