【发布时间】:2010-12-15 14:33:52
【问题描述】:
我想检查我使用 PHP 和 PDO 连接的数据库中是否存在具有特定名称的表。
它必须适用于所有数据库后端,如 MySQL、SQLite 等。
【问题讨论】:
我想检查我使用 PHP 和 PDO 连接的数据库中是否存在具有特定名称的表。
它必须适用于所有数据库后端,如 MySQL、SQLite 等。
【问题讨论】:
这是一个检查表是否存在的完整函数。
/**
* Check if a table exists in the current database.
*
* @param PDO $pdo PDO instance connected to a database.
* @param string $table Table to search for.
* @return bool TRUE if table exists, FALSE if no table found.
*/
function tableExists($pdo, $table) {
// Try a select statement against the table
// Run it in try-catch in case PDO is in ERRMODE_EXCEPTION.
try {
$result = $pdo->query("SELECT 1 FROM {$table} LIMIT 1");
} catch (Exception $e) {
// We got an exception (table not found)
return FALSE;
}
// Result is either boolean FALSE (no table found) or PDOStatement Object (table found)
return $result !== FALSE;
}
注意:只有在被告知时,PDO 才会抛出异常,默认情况下它是静默的并且不抛出异常。这就是为什么我们也需要检查结果。 See PDO error handling at php.net
【讨论】:
$table = preg_replace('/[^\da-z_]/i', '', $table);
我建议您使用 DESCRIBE
示例查询:
DESCRIBE `users`
示例 php&pdo:
$tblname = 'users'; //table name
$x = $db->prepare("DESCRIBE `$tblname`");
$x->execute();
$row = $x->fetch();
if ($row) {
print 1; //table exists
}else{
print 0; //table not exists
}
【讨论】:
如果您在同一语句中还有其他主要操作要做,可以使用 e->errorInfo
try{
//Your major statements here
}
catch(PDOException $e){
if($e->errorInfo[1] == 1146){
//when table doesn't exist
}
}
【讨论】:
$e->getCode()
起初,我使用的是公认的答案,但后来我注意到它因空表而失败。这是我现在使用的代码:
function DB_table_exists($db, $table){
GLOBAL $db;
try{
$db->query("SELECT 1 FROM $db.$table");
} catch (PDOException $e){
return false;
}
return true;
}
此代码是我的 PDO 扩展类的摘录。如果表不存在,它将产生错误(并返回 false),但如果表存在和/或为空,则会成功。
【讨论】:
这似乎至少适用于 SQLite3,没有例外等:
$select =
"SELECT CASE WHEN EXISTS (SELECT * FROM SQLITE_MASTER WHERE TYPE = 'table' AND NAME = :tableName) THEN 1 ELSE 0 END AS TABLE_EXISTS;";
【讨论】:
SQLITE_MASTER 表......顾名思义?OP要求数据库- 独立解决方案...
如果表不存在,请执行查询,要求数据库创建表:
$string = "CREATE TABLE IF NOT EXISTS " .$table_name . " int(11) NOT NULL AUTO_INCREMENT,
`id` int(3) NOT NULL,
`blabla` int(2) NOT NULL,
`blabla1` int(2) NOT NULL,
`blabla3` varchar(3) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
AUTO_INCREMENT=1 ";
$sql = $conection->prepare($string);
$sql->execute();
【讨论】:
create table 在计算上肯定比简单的select 更昂贵?此外,OP 想要一个适用于所有后端的解决方案——您的解决方案仅适用于 MySQL/MariaDB。
作为项目的一部分,创建一个架构视图。
对于 Oracle,它会是这样的
SELECT TABLE_NAME FROM ALL_TABLES
对于Mysql:
SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'mydbname'
ETC..
然后在代码中针对视图运行查询。
【讨论】:
this is how you do it with PDO 的答案,不是吗?
这对我有用。这是几个答案的组合:
$table_name = 'your_table_here';
$test = "SELECT 1 FROM " . $table_name . " LIMIT 1";
$test = $db->query($test); //$db needs to be PDO instance
if($test)
{
return 1; //Table exists
}
else
{
return 0; //No table in database
}
【讨论】:
这个完整的功能与 esbite 的答案非常相似,但包含防止 SQL 注入的代码。此外,当相关表格为空时,您可能无法从接受的答案中获得一致的结果。
/**
* This function checks if the table exists in the passed PDO database connection
* @param PDO $pdo - connection to PDO database table
* @param type $tableName
* @return boolean - true if table was found, false if not
*/
function tableExists(PDO $pdo, $tableName) {
$mrSql = "SHOW TABLES LIKE :table_name";
$mrStmt = $pdo->prepare($mrSql);
//protect from injection attacks
$mrStmt->bindParam(":table_name", $tableName, PDO::PARAM_STR);
$sqlResult = $mrStmt->execute();
if ($sqlResult) {
$row = $mrStmt->fetch(PDO::FETCH_NUM);
if ($row[0]) {
//table was found
return true;
} else {
//table was not found
return false;
}
} else {
//some PDO error occurred
echo("Could not check if table exists, Error: ".var_export($pdo->errorInfo(), true));
return false;
}
}
【讨论】:
通过 PDO 处理数据库后,您可以这样做:
$tableExists = gettype($dbh->exec("SELECT count(*) FROM $table")) == 'integer';
或者将其包装在一个函数中。
一开始我尝试过使用try/catch,但即使该表不存在,也没有例外。最后检查了 dbh exec 调用返回值的数据类型。如果选择计数匹配,则为整数(即使计数为 0,如果没有结果,则为 false 的布尔值。
我认为这应该适用于 PDO 支持的所有数据库类型,因为语法非常简单。
【讨论】:
在我继续之前,我确实意识到这是一个特定于 MySQL 的解决方案。
虽然这里提到的所有解决方案都可能有效,但我(个人)喜欢防止 PDO 引发异常(个人偏好,仅此而已)。
因此,我使用以下方法来测试表创建:
SHOW TABLES LIKE 'some_table_of_mine';
如果表不存在,则不会生成错误状态,您只需得到一个零结果集。对我来说工作快速且始终如一。
【讨论】:
您可以通过使用“SHOW TABLES LIKE 'your_table'”行中的查询然后计算行数来避免依赖错误。我已经在 MySQL 和 PDO 上成功使用了这种方法,但还没有在其他 DB 上进行测试
【讨论】:
SHOW TABLES 等效)。
我在我的 Web 应用程序中使用 CodeIgniter 做了一些事情来检查数据库是否存在(并且有用),其中任何一个都可以工作:
@$this->load->database();
$v = @$this->db->version()
$tables = @$this->db->list_tables();
如果您在 PHP 设置中启用了 @,则添加 @ 将抑制错误,并检查 version() 和 list_tables() 的结果不仅可用于确定您的数据库是否存在(但它是理智的也)。
【讨论】:
做:
select 1 from your_table
然后捕获错误。如果您没有收到任何错误,但结果集中有一列包含“1”,则该表存在。
【讨论】: