2010-08-03 57 views
95

我正在尝试编写一个查询来检查MySQL中的特定表是否有特定的列,如果没有 - 创建它。否则什么都不要做这在任何企业级数据库中都是一个简单的过程,但MySQL似乎是个例外。MySQL,检查列中是否存在SQL列表

我觉得像

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; 

会的工作,但它失败得很惨。有没有办法?

+0

看到这一点: http://www.cryer.co.uk/brian/mysql/howto_add_column_unless_exists.htm – 2010-08-03 10:58:34

+0

为什么不创建它?如果存在,创建将失败,但你不在乎。 – 2010-08-03 10:59:43

+0

创建发生在一个事务中,并且失败将会终止整个事务,可悲但是是真的 – clops 2010-08-03 11:02:21

回答

133

@julio

感谢您的SQL示例。我试过查询,我认为它需要一个小改动才能正常工作。

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

这对我有效。

谢谢!

+0

它从我的有限研究并非所有的主机环境都有一个information_schema数据库我已经使用的所有cpanel环境都有它提供的解决方案取决于这个数据库的存在 – cardi777 2014-03-10 01:26:31

+2

这个答案比使用“SHOW COLUMNS”更好,因为它使用ANSI标准方法获得表信息,不像SHOW COLUMNS,它是MySQL特有的,所以这个解决方案将会w与其他数据库一起使用。使用“information_schema”听起来很奇怪,你会认为这不是标准的SQL方法来做到这一点,但它是。 – orrd 2014-03-25 19:46:21

+3

请注意,此答案只会让您了解有关列存在的信息。如果你想有条件地执行一些DDL语句,你必须将整个事件包装在允许像“IF”等语句的过程中。参见http://stackoverflow.com/questions/7384711/if-conditional- in-sql-script-for-mysql中有关如何在列和条件DML语句的测试周围包装过程的示例。 – 2014-07-23 20:14:55

5

从信息架构中只选择column_name,并将此查询的结果放入变量中。然后测试变量以决定表是否需要更改。

P.S.不要为COLUMNS表指定TABLE_SCHEMA。

+1

我对MySQL比较陌生,你可能会在这里发表一个小例子吗? – clops 2010-08-03 11:01:23

5

只是为了帮助别人谁是寻找什么@Mchi被描述的一个具体的例子,你可以试试

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

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

178

这对我很好。

SHOW COLUMNS FROM `table` LIKE 'fieldname'; 

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

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

问题不是如何使用php + sql或java + sql来做到这一点,这是如何使用纯SQL/MySQL的,因此downvote – Yura 2012-06-18 09:54:58

+42

你回答这个问题+一些信息,帮助我和其他人,+1 – 2012-11-22 22:38:01

+0

@MFoo谢谢Mfoo,你救了我的一天!像魅力一样工作。除了为此任务创建过程之外,最好的解决方案之一。 – webblover 2014-02-14 17:49:50

7

下面是使用纯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'"); 
+0

为什么你想避免使用information_schema?只是为了这个目的而存在。 (另外,这个线程已经很老了,已经得到了回答。) – Leigh 2012-04-07 04:07:46

+1

在我的测试中,这比使用information_schema大约快10-50倍。它确实要求表格至少有一行,这是你无法保证的。 – Martijn 2013-01-28 10:07:43

+0

如果数组键存在,但是值为** NULL **,则isset()将抛弃'false'。最好使用'array_key_exists()'如'if(!array_key_exists('my_new_column',$ mycol))' – 2016-01-20 08:47:43

5

我把这个存储程序以及从@ 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 | 
+----------+ 
+0

MIster @quickshiftin,非常感谢。这可以帮助我检查一个表是否可以过期**,通过_checking_ if有一个'ExpirationDate'字段。 – 2017-02-03 00:12:26

+0

@JeancarloFontalvo我的荣幸!同时检查我的[mysql-inspectors项目](https://github.com/quickshiftin/mysql-inspectors)我开始用更高级别的方法检查模式。 – quickshiftin 2017-02-03 00:15:31

+0

OMG它就像一个图书馆。感谢分享它先生! – 2017-02-03 00:37:11

1

工作我使用这个简单的脚本:

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

它的工作原理,如果你已经连接到数据库。

+0

这只有在表中也碰巧有数据行时才有效。但是如果表格是空的,这是行不通的。 – orrd 2014-03-25 19:08:19

+0

不完美,使用旧的驱动程序,如果表为空,输入不能逃脱,但我喜欢你是如何在一行中做到的。 +1 – 2015-01-05 21:06:34

0

不要把ALTER TABLE/MODIFY COLS或任何其他这样的表模操作放在TRANSACTION中。事务是为了能够回滚QUERY故障,而不是用于ALTERATION ...它会在事务中每次出错。

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

0

非常感谢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/>'; 
} 
?> 
0

这工作让我有样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());}  
}