【问题标题】:MySQL, Check if a column exists in a table with SQLMySQL,使用SQL检查表中是否存在列
【发布时间】:2011-03-24 16:09:38
【问题描述】:

我正在尝试编写一个查询来检查 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;

会工作,但它失败了。有什么办法吗?

【问题讨论】:

标签: mysql


【解决方案1】:

这对我很有效。

SHOW COLUMNS FROM `table` LIKE 'fieldname';

使用 PHP 会是这样的......

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

【讨论】:

  • 你回答了这个问题 + 一些对我和其他人有帮助的信息,+1
  • @Mfoo 谢谢 Mfoo,你拯救了我的一天!像魅力一样工作。除了为此任务创建程序之外的最佳解决方案之一。
  • Yura:纯粹的 SQL / MySQL 答案是他说使用“SHOW COLUMNS FROM table LIKE 'fieldname'”的第一部分。您可以忽略 PHP 代码,这只是您碰巧使用 PHP 时检索和解释结果的一种方式的示例。
  • 找不到存储过程SHOW
  • @codenamezero 我假设您指的是使用 MSSQL,这个问题是关于 MySQL 的。 MSSQL 参考this post
【解决方案2】:

@julio

感谢 SQL 示例。我尝试了查询,我认为它需要进行一些小改动才能使其正常工作。

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

这对我有用。

谢谢!

【讨论】:

  • 从我有限的研究看来,并非所有托管环境都有 information_schema 数据库。我用过的所有 cpanel 环境都有它。此提供的解决方案取决于现有的此数据库。
  • 这个答案比使用“SHOW COLUMNS”更好,因为它使用 ANSI 标准方式来获取表信息,这与特定于 MySQL 的 SHOW COLUMNS 不同。所以这个解决方案将适用于其他数据库。使用“information_schema”听起来很奇怪,你会认为这不是标准的 SQL 方法,但它确实是。
  • 请注意,此答案只会为您提供有关列存在的信息。如果你想有条件地执行一些 DDL 语句,你必须将整个事情包装在一个允许像 IF 等语句的过程中。有关如何围绕测试包装一个过程的示例,请参见 stackoverflow.com/questions/7384711/…列和条件 DML 语句。
  • @Iain : stackoverflow.com/questions/32962149/… 我参考了你的答案
  • 这比下面的“SHOW COLUMNS”方法更好,因为可以在参数化查询中使用,从而降低 SQL 注入的风险。只是想添加您可以使用 DATABASE() 函数来填充 TABLE_SCHEMA 列。
【解决方案3】:

只是为了帮助任何正在寻找@Mchl 描述的具体示例的人,请尝试类似

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

如果它返回 false(零个结果),那么您知道该列不存在。

【讨论】:

  • 我认为应该是TABLE_NAME = 'my_table',TABLE_SCHEMA 是表所在的架构。即SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'
【解决方案4】:

我把这个存储过程和上面@lain 的 cmets 放在一起,如果你需要多次调用它(而不需要 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 |
+----------+

【讨论】:

  • 先生@quickshiftin,非常感谢。这有助于我检查表是否过期,方法是检查是否有ExpirationDate 字段。 ?
  • @JeancarloFontalvo 我的荣幸!另请查看我的mysql-inspectors project 我开始使用更高级别的方法检查架构。
  • 天啊,这就像一个图书馆?。谢谢楼主分享!
【解决方案5】:

以下是使用没有 information_schema 数据库的普通 PHP 的另一种方法:

$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'");

【讨论】:

  • 为什么要避免使用 information_schema?它的存在就是为了这个目的。 (另外,这个帖子很老了,已经回答了。)
  • 在我的测试中,这比使用 information_schema 快大约 10-50 倍。它确实要求表格至少有一行,但您不能总是保证。
  • 如果数组键存在但值为 NULLisset() 将抛出“false”。最好像if( !array_key_exists( 'my_new_column', $mycol ) )一样使用array_key_exists()
  • 这个答案让我大吃一惊,因为我忽略了一个简单的isset() 检查。它不能解决问题,但如果您已经需要执行选择查询并将结果保存在内存中,那就更好了。
【解决方案6】:

仅从信息模式中选择 column_name 并将此查询的结果放入变量中。然后测试变量以确定表是否需要更改。

附:不要忘记为 COLUMNS 表指定 TABLE_SCHEMA。

【讨论】:

  • 我对 MySQL 比较陌生,你能在这里发布一个小例子吗?
【解决方案7】:

我正在使用这个简单的脚本:

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

如果您已经连接到数据库,它就可以工作。

【讨论】:

  • 这只有在表中也有数据行的情况下才有效。但如果表是空的,这将不起作用。
  • 不完美,使用旧驱动程序,如果表为空则不起作用,输入未转义,但我喜欢你在一行中的做法。 +1
【解决方案8】:

这适用于我的示例 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());}     
}

【讨论】:

    【解决方案9】:

    请勿将 ALTER TABLE/MODIFY COLS 或任何其他此类表 mod 操作放入 TRANSACTION 中。事务是为了能够回滚 QUERY 失败而不是 ALTERations...它每次在事务中都会出错。

    只需对表运行 SELECT * 查询并检查该列是否存在...

    【讨论】:

    • MySQL 中的 ALTER (以及类似的 DDL)确实(隐式)提交了事务。但是使用 SELECT * 会在网络中产生很大的开销来检查列的存在。您可以改为尝试SELECT my_col_to_check FROM t LIMIT 0:如果mysql 生成错误,则列可能不存在(仍然检查错误,因为它可能是网络问题或其他原因!);如果它没有产生错误,那么列存在。我不确定这是检查列是否存在的最佳方法。
    【解决方案10】:

    非常感谢 Mfoo,他提供了非常好的脚本,用于动态添加列(如果表中不存在)。 我已经用 PHP 改进了他的答案脚本还可以帮助您找到实际需要多少表'添加列' mysql 命令。尝尝食谱。像魅力一样工作。

    <?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/>';
    }
    ?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 2013-05-17
      • 1970-01-01
      • 2014-06-24
      • 2010-10-02
      • 2011-07-21
      • 2010-09-13
      相关资源
      最近更新 更多