MySQL,使用SQL检查表中是不是存在列

Posted

技术标签:

【中文标题】MySQL,使用SQL检查表中是不是存在列【英文标题】: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;

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

【问题讨论】:

看到这个:cryer.co.uk/brian/mysql/howto_add_column_unless_exists.htm 为什么不直接创建呢?如果存在,创建将失败,但你不在乎。 创建发生在事务内部,失败将终止整个事务,可悲但真实 @haim — 谢谢提醒,但链接中建议的查询仅在过程中有效:( DDL 语句导致当前事务中的隐式提交。 dev.mysql.com/doc/refman/5.0/en/implicit-commit.html 【参考方案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 等语句的过程中。有关如何围绕测试包装一个过程的示例,请参见 ***.com/questions/7384711/…列和条件 DML 语句。 @Iain : ***.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/>';

?>

【讨论】:

以上是关于MySQL,使用SQL检查表中是不是存在列的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python pyodbc 检查表中是不是存在列?

SQL Server:检查表列是不是存在并删除行

如何检查 var 是不是存在于数据库列中,如果不存在则不执行任何操作

检查 OleDb 表中是不是存在列

不存在多于一列

检查表中是不是存在列,如果没有,则添加列