MySQL, проверьте, существует ли столбец в таблице с SQL

Я пытаюсь написать запрос, который будет проверять, имеет ли конкретная таблица в MySQL определенный столбец, а если нет - создайте его. В противном случае ничего не делать. Это действительно простая процедура в любой базе данных корпоративного класса, но MySQL, похоже, является исключением.

Я подумал что-то вроде

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
           WHERE TABLE_NAME='prefix_topic' AND column_name='topic_last_update') 
BEGIN 
ALTER TABLE `prefix_topic` ADD `topic_last_update` DATETIME NOT NULL;
UPDATE `prefix_topic` SET `topic_last_update` = `topic_date_add`;
END;

будет работать, но он терпит неудачу. Есть ли способ?

Ответ 1

Это хорошо работает для меня.

SHOW COLUMNS FROM `table` LIKE 'fieldname';

С PHP это будет что-то вроде...

$result = mysql_query("SHOW COLUMNS FROM `table` LIKE 'fieldname'");
$exists = (mysql_num_rows($result))?TRUE:FALSE;

Ответ 2

@julio

Спасибо за пример SQL. Я попробовал запрос, и я думаю, что для его нормальной работы требуется небольшое изменение.

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'

Это сработало для меня.

Спасибо!

Ответ 3

Ниже приведен другой способ сделать это, используя простой PHP без базы данных information_schema:

$chkcol = mysql_query("SELECT * FROM `my_table_name` LIMIT 1");
$mycol = mysql_fetch_array($chkcol);
if(!isset($mycol['my_new_column']))
  mysql_query("ALTER TABLE `my_table_name` ADD `my_new_column` BOOL NOT NULL DEFAULT '0'");

Ответ 4

Выберите только имя_каталога из информационной схемы и поместите результат этого запроса в переменную. Затем проверьте переменную, чтобы решить, нужно ли изменять таблицу или нет.

P.S. Не пытайтесь указывать TABLE_SCHEMA для таблицы COLUMNS.

Ответ 5

Просто, чтобы помочь любому, кто ищет конкретный пример того, что @Mchl описывает, попробуйте что-то вроде

SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_table' AND COLUMN_NAME = 'my_column'

Если он возвращает false (ноль результатов), то вы знаете, что столбец не существует.

Ответ 6

Я бросил эту хранимую процедуру вместе с началом из комментариев @lain выше, вроде приятно, если вам нужно называть это более чем несколько раз (и не нужно php):

delimiter //
-- ------------------------------------------------------------
-- Use the inforamtion_schema to tell if a field exists.
-- Optional param dbName, defaults to current database
-- ------------------------------------------------------------
CREATE PROCEDURE fieldExists (
OUT _exists BOOLEAN,      -- return value
IN tableName CHAR(255),   -- name of table to look for
IN columnName CHAR(255),  -- name of column to look for
IN dbName CHAR(255)       -- optional specific db
) BEGIN
-- try to lookup db if none provided
SET @_dbName := IF(dbName IS NULL, database(), dbName);

IF CHAR_LENGTH(@_dbName) = 0
THEN -- no specific or current db to check against
  SELECT FALSE INTO _exists;
ELSE -- we have a db to work with
  SELECT IF(count(*) > 0, TRUE, FALSE) INTO _exists
  FROM information_schema.COLUMNS c
  WHERE 
  c.TABLE_SCHEMA    = @_dbName
  AND c.TABLE_NAME  = tableName
  AND c.COLUMN_NAME = columnName;
END IF;
END //
delimiter ;

Работа с fieldExists

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_option', NULL) //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_options', 'etrophies') //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        1 |
+----------+

Ответ 7

Я использую этот простой script:

mysql_query("select $column from $table") or mysql_query("alter table $table add $column varchar (20)");

Он работает, если вы уже подключены к базе данных.

Ответ 8

НЕ ВКЛЮЧАЙТЕ ALTER TABLE/MODIFY COLS или любые другие подобные операции с табличными модулями внутри транзакции. Транзакции предназначены для отката запроса QUERY, а не для ALTERATIONS... он будет выходить из строя каждый раз в транзакции.

Просто запустите запрос SELECT * в таблице и проверьте, есть ли там столбец...

Ответ 9

Большое спасибо Mfoo, который положил действительно приятный script для динамического добавления столбцов, если не существует в таблице. Я улучшил свой ответ с помощью PHP. script дополнительно помогает вам узнать, сколько таблиц действительно необходимо "Добавить столбец" mysql comand. Просто попробуйте рецепт. Работает как шарм.

<?php
ini_set('max_execution_time', 0);

$host = 'localhost';
$username = 'root';
$password = '';
$database = 'books';

$con = mysqli_connect($host, $username, $password);
if(!$con) { echo "Cannot connect to the database ";die();}
mysqli_select_db($con, $database);
$result=mysqli_query($con, 'show tables');
$tableArray = array();
while($tables = mysqli_fetch_row($result)) 
{
     $tableArray[] = $tables[0];    
}

$already = 0;
$new = 0;
for($rs = 0; $rs < count($tableArray); $rs++)
{
    $exists = FALSE;

    $result = mysqli_query($con, "SHOW COLUMNS FROM ".$tableArray[$rs]." LIKE 'tags'");
    $exists = (mysqli_num_rows($result))?TRUE:FALSE;

    if($exists == FALSE)
    {
        mysqli_query($con, "ALTER TABLE ".$tableArray[$rs]." ADD COLUMN tags VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL");
        ++$new;
        echo '#'.$new.' Table DONE!<br/>';
    }
    else
    {
        ++$already;
        echo '#'.$already.' Field defined alrady!<br/>';    
    }
    echo '<br/>';
}
?>

Ответ 10

Эта работа для меня с образцом PDO:

public function GetTableColumn() {      
$query  = $this->db->prepare("SHOW COLUMNS FROM `what_table` LIKE 'what_column'");  
try{            
    $query->execute();                                          
    if($query->fetchColumn()) { return 1; }else{ return 0; }
    }catch(PDOException $e){die($e->getMessage());}     
}

Ответ 11

Если вам нужна функциональность, если существует индекс для столбца (здесь по порядку первое место), вы можете использовать/принять этот код.

CREATE FUNCTION 'fct_check_if_index_for_column_exists_at_first_place'(
    'IN_SCHEMA' VARCHAR(255),
    'IN_TABLE' VARCHAR(255),
    'IN_COLUMN' VARCHAR(255)
)
RETURNS tinyint(4)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Check if index exists at first place in sequence for a given column in a given table in a given schema. Returns -1 if schema does not exist. Returns -2 if table does not exist. Return -3 if column does not exist. If index exists in first place it returns 1, otherwise 0.'
BEGIN

-- Check if index exists at first place in sequence for a given column in a given table in a given schema. 
-- Returns -1 if schema does not exist. 
-- Returns -2 if table does not exist. 
-- Return -3 if column does not exist. 
-- If the index exists in first place it returns 1, otherwise 0.
-- Example call: SELECT fct_check_if_index_for_column_exists_at_first_place('schema_name', 'table_name', 'index_name');

-- check if schema exists
SELECT 
    COUNT(*) INTO @COUNT_EXISTS
FROM 
    INFORMATION_SCHEMA.SCHEMATA
WHERE 
    SCHEMA_NAME = IN_SCHEMA
;

IF @COUNT_EXISTS = 0 THEN
    RETURN -1;
END IF;


-- check if table exists
SELECT 
    COUNT(*) INTO @COUNT_EXISTS
FROM 
    INFORMATION_SCHEMA.TABLES
WHERE 
    TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE
;

IF @COUNT_EXISTS = 0 THEN
    RETURN -2;
END IF;


-- check if column exists
SELECT 
    COUNT(*) INTO @COUNT_EXISTS
FROM 
    INFORMATION_SCHEMA.COLUMNS
WHERE 
    TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE
AND COLUMN_NAME = IN_COLUMN
;

IF @COUNT_EXISTS = 0 THEN
    RETURN -3;
END IF;

-- check if index exists at first place in sequence
SELECT 
    COUNT(*) INTO @COUNT_EXISTS
FROM 
    information_schema.statistics 
WHERE 
    TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE AND COLUMN_NAME = IN_COLUMN
AND SEQ_IN_INDEX = 1;


IF @COUNT_EXISTS > 0 THEN
    RETURN 1;
ELSE
    RETURN 0;
END IF;


END