如何在PHP中使用PDO选择MySQL数据库?

46

在创建了一个PHP PDO对象之后,我想选择一个MySQL数据库来使用。我该如何做?

// create PDO object and connect to MySQL
$dbh = new PDO( 'mysql:host=localhost;', 'name', 'pass' );

// create a database named 'database_name'

// select the database we just created ( this does not work )
$dbh->select_db( 'database_name' );

是否有一个与mysqli :: select_db相当的PDO方法?

也许我正在错误地使用PDO?请帮忙解决或者解释一下。

编辑

我是否不应该使用PDO来创建新的数据库?我理解使用PDO的大部分好处在于一个不像CREATE DATABASE那样不插入数据的很少使用的操作上被浪费了,但是必须使用另一个连接来创建数据库,然后创建一个PDO连接进行其他调用似乎有些奇怪。


你可能需要创建一个新的PDO对象来连接另一个数据库。 - Ignas
3
假设您连接的用户ID对其他数据库/表具有适当的权限,则可以使用select table.field from database.table语句。 - Marc B
创建一个新对象有什么问题吗?一旦您运行了像“CREATE DATABASE”这样的查询,就可以轻松销毁它并继续使用新连接工作。我真的没有看出有什么问题。 - Ignas
1
这似乎是一件很傻的事情,通常意味着我做错了其他事情。也许这只是一个边缘案例。PDO可能不经常用于创建新数据库。 - T. Brian Jones
@Ignas:在我的测试中,打开与数据库的连接(实例化PDO)大约需要23毫秒。我有成百上千个数据库;这使得我的脚本比使用“use”语句慢了4倍。 - mpen
是的,我明白你的意思(我使用了两个连接,因为我每50行代码就必须切换数据库,所以那23毫秒的初始开销与许多使用数据库语句相比微不足道 :) 我可能会将"use database"语句包装在一个方法中,并像$this->Db()->query("")一样使用它。将最后选择的数据库名称存储在一个变量中,如果传递给Db方法的参数不同,只需切换数据库 :) - Ignas
4个回答

60

通常,连接时会在DSN中指定数据库。但是如果要创建一个新数据库,显然在创建之前无法在DSN中指定该数据库。

您可以使用USE语句更改默认数据库:

$dbh = new PDO("mysql:host=...;dbname=mysql", ...);

$dbh->query("create database newdatabase");

$dbh->query("use newdatabase");

接下来的CREATE TABLE语句将在你的新数据库中创建。


@Mike 的评论:

当你像那样切换数据库时,它似乎会强制PDO模拟预处理语句。将PDO::ATTR_EMULATE_PREPARES设置为false,然后尝试使用另一个数据库将失败。

我进行了一些测试,但我没有看到这种情况发生。更改数据库只会在服务器上发生,并不会改变客户端中PDO的配置。这里是一个示例:

<?php

// connect to database
try {
    $pdo = new PDO('mysql:host=huey;dbname=test', 'root', 'root');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $err) {
    die($err->getMessage());
}

$stmt = $pdo->prepare("select * from foo WHERE i = :i");
$result = $stmt->execute(array("i"=>123));
print_r($stmt->fetchAll(PDO::FETCH_ASSOC));

$pdo->exec("use test2");

$stmt = $pdo->prepare("select * from foo2 WHERE i = :i AND i = :i");
$result = $stmt->execute(array("i"=>456));
print_r($stmt->fetchAll(PDO::FETCH_ASSOC));
如果你所说的是真的,那么这个应该可以无错运行。PDO 只有在 PDO::ATTR_EMULATE_PREPARES 设置为 true 时才能多次使用特定命名参数。所以,如果你说这个属性是由于更改数据库而被设置为 true 的副作用,那么它应该可以工作。
但它并不起作用——它会得到一个错误“Invalid parameter number”,这表明非模拟准备语句仍然生效。

2
真的吗?查询?我很确定你要找的是exec。 - Tom van der Woerdt
3
@TomvanderWoerdt:我测试了query()和exec(),它们都可以使用。query()返回的是PDOStatement对象,而exec()返回受影响的行数(创建为1,使用为0)。对于这些语句,返回值几乎没有什么意义。 - Bill Karwin
2
重点是在打开的数据库句柄上更改默认数据库非常容易;无需打开第二个数据库连接。 - Bill Karwin
1
@Mike,我觉得你弄错了。请看上面的测试案例。 - Bill Karwin
6
PDO::query() 内部会执行 prepare() 然后是 execute()。并非所有 MySQL 语句都可以使用 prepare。请参见 http://dev.mysql.com/doc/refman/5.6/en/sql-syntax-prepared-statements.html,在“SQL Syntax Allowed in Prepared Statements”一节中查看。 - Bill Karwin
显示剩余5条评论

0

在创建PDO对象时,您应该设置数据库。以下是一个示例(来自这里

<?php
$hostname = "localhost";
$username = "your_username";
$password = "your_password";

try {
    $dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
    echo "Connected to database"; // check for connection
    }
catch(PDOException $e)
    {
    echo $e->getMessage();
    }
?>

0

或者,您可以在创建PHP PDO对象后选择要使用的MySQL数据库,如下所示:

使用USE语句。但请记住,这里的USE语句是MySQL命令。

try
{
    $conn = new PDO("mysql:host=$servername;", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $conn->exec("use databasename");
    //application logic
}
catch(PDOException $e)
{
    echo $sql . "<br>" . $e->getMessage();
}

$conn = null;

我希望我的代码可以对你的请求有所帮助


1
你只是在重复5年前别人说过的话。 - BenMorel

-1
据我所知,每个连接都需要创建一个新的对象。您可以通过扩展PDO类并添加一个连接多个数据库的方法来实现。然后您可以根据需要使用它:
public function pickDatabase($db) {
  if($db == 'main') {
    return $this->db['main']; //instance of PDO object
  else
    return $this->db['secondary']; //another instance of PDO object
}

并像这样使用:$yourclass->pickDatabase('main')->fetchAll('your stuff');


为什么在 PDO 创建对象时必须设置它,而在 MySQLi 中不必这样做? - T. Brian Jones
我无法回答这个问题,因为这是PHP开发人员的做法 :) - Ignas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接