应使用 CREATE DATABASE IF NOT EXISTS dbname 代替裸 CREATE DATABASE,避免“Database already exists”错误;建库后需显式 USE 或用全限定名,否则后续操作报错。

PHP 创建数据库时提示 “Database already exists” 怎么办
直接原因是 CREATE DATABASE 语句没加判断,而目标库名在 MySQL 中已存在。PHP 本身不校验库是否存在,它只是把 SQL 发给 MySQL 执行,MySQL 拒绝重复建库并抛出错误(如 1007: Can't create database 'xxx'; database exists)。
解决思路不是“绕过报错”,而是让 SQL 主动避开冲突:
- 用
CREATE DATABASE IF NOT EXISTS `dbname`替代裸CREATE DATABASE `dbname` - 确保数据库名用反引号包裹(尤其含短横线、数字开头等非法标识符时)
- 执行前不依赖 PHP 的
mysqli_query()返回值做“是否成功”的粗暴判断——它返回false只代表语法或权限错误,IF NOT EXISTS成功“跳过”时也返回true
mysqli 和 PDO 两种方式下如何安全建库
两者核心都是把带 IF NOT EXISTS 的 SQL 交给 MySQL,但连接与错误处理习惯不同:
mysqli 方式(面向过程):
立即学习“PHP免费学习笔记(深入)”;
$conn = mysqli_connect('localhost', 'user', 'pass');
if (!$conn) die('连接失败');
$result = mysqli_query($conn, "CREATE DATABASE IF NOT EXISTS `my_app_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
if ($result === false) {
// 注意:这里只捕获真正失败(如权限不足),不是“库已存在”
trigger_error('建库失败:' . mysqli_error($conn), E_USER_ERROR);
}
PDO 方式(推荐):
try {
$pdo = new PDO('mysql:host=localhost', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("CREATE DATABASE IF NOT EXISTS `my_app_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
} catch (PDOException $e) {
// $e->getCode() == 1007 表示“库已存在”,可忽略;其他码需处理
if ($e->getCode() != 1007) {
throw $e;
}
}
为什么不能先用 SHOW DATABASES 查一遍再建
看似合理,实则引入竞态条件(race condition):两次查询之间,另一个进程可能已建好同名库,导致第二次 CREATE 仍报错。这不是 PHP 或 MySQL 的缺陷,而是任何“检查-执行”两步操作在并发下的通病。
更关键的是:IF NOT EXISTS 是原子操作,MySQL 内部一步完成判断+创建(或跳过),彻底规避该问题。
- 不要写
SHOW DATABASES LIKE 'mydb'+if (!empty($row)) { CREATE ... } - 也不要用
mysqli_select_db()是否成功来反推库是否存在——它只说明能否切换,不等于库一定存在(比如权限不足也会失败)
建库后自动选中并执行建表语句的常见陷阱
很多人建完库立刻 mysqli_select_db() 或 $pdo->exec("USE mydb"),但容易忽略两点:
-
CREATE DATABASE IF NOT EXISTS成功(包括“跳过”情况)后,当前连接默认**不会自动切换到该库**,必须显式USE或在后续查询中用db_name.table_name全限定名 - 如果库是刚新建的(非跳过),且你紧接着执行
CREATE TABLE user(...),但没USE或指定库名,MySQL 会报ERROR 1046: No database selected
稳妥做法是:无论建库是否“新创建”,都补一句 USE `my_app_db`,或所有 DDL 都带上库前缀,例如 CREATE TABLE `my_app_db`.`user` (...)。
真正麻烦的从来不是“怎么建库”,而是建库之后那几行没写全的 USE 或没加的反引号——它们让错误出现在下游,排查时反而回头怀疑建库逻辑。











