How to execute PDO statement when there are two da

2019-02-25 11:47发布

问题:

I need to execute this SQL query:

SELECT DISTINCT
    logger.hcp_id,
    logger.rep_id,
    logger.type,
    session_brand_presentation.ID,
    session_brand_presentation.brand_id,
    session_brand_presentation.createdAt,
    session_brand_presentation.modifiedAt
FROM
    archive_pfizer.logger
        JOIN
    pdone_legacy.session_brand_presentation ON logger.session_id = session_brand_presentation.local_session_id

WHERE
    logger.type = 'email_sent';

As you may already notice I am querying to different databases: archive_pfizer and pdone_legacy. I know that DSN needs a DB name for create the PDO object then as title say: How do I execute a PDO statement when there are two databases involve in the same query?

Very important I am asking how to achieve this from PHP using PDO, I was able to execute the query successfully from MySQL/MariaDB command line and/or using any GUI.

UPDATE

Here is the code I was working on based on @RyanVincent answer:

$config = parse_ini_file('config.ini', true);
define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '<br />');
$DBASE = $config['database']['DBASE'][0];
$pdo = setupDB($config, $DBASE);

$sql = 'SELECT DISTINCT logger.hcp_id, logger.rep_id, logger.type, session_brand_presentation.ID, session_brand_presentation.brand_id, session_brand_presentation.createdAt, session_brand_presentation.modifiedAt FROM archive_pfizer.logger JOIN pdone_legacy.session_brand_presentation ON logger.session_id = session_brand_presentation.local_session_id WHERE logger.type = "email_sent"';

foreach($pdo->query($sql) as $row) {
    var_export($row);
    echo EOL;
}

But I got this error:

PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pdone_legacy.session_brand_presentation' doesn't exist'

Apparently it's taking pdone_legacy.session_brand_presentation as a table when it's a database, in the example provided is the same as testmysql, any advice?

UPDATE 2

Trying the same SQL query but using aliases didn't work either:

$sql = 'SELECT DISTINCT
            lg.hcp_id,
            lg.rep_id,
            lg.type,
            sbp.ID,
            sbp.brand_id,
            sbp.createdAt,
            sbp.modifiedAt
        FROM
            archive_pfizer.logger AS lg
                JOIN
            pdone_legacy.session_brand_presentation AS sbp ON lg.session_id = sbp.local_session_id

        WHERE
            lg.type = "email_sent"';

Got exactly the same issue as before.

UPDATE 3

Ok, perhaps I will got killed after say this but was my bad all the time. I was connecting to a server where DB pdone_legacy exists but that DB in fact hasn't session_brand_presentation table and that is what PDO was saying all the time. Anyway thanks to anyone here and both queries are valid.

回答1:

Here is the code to join from two separate mysql databases using PDO.

Pastebin: Tested code

Limitations:

  • Both mysql databases must be on the same server
  • Only one connection is used.
  • The database user must have the necessary privileges on both databases

Query using archive_pfizer (logger) and pdone_legacy (session_brand_presentation)

$sqlBoth = 'SELECT DISTINCT
                logger.hcp_id,
                logger.rep_id,
                logger.type,
                session_brand_presentation.ID,
                session_brand_presentation.brand_id,
                session_brand_presentation.createdAt,
                session_brand_presentation.modifiedAt
            FROM
                archive_pfizer.logger
            JOIN
                pdone_legacy.session_brand_presentation
                   ON logger.session_id = session_brand_presentation.local_session_id

            WHERE
                logger.type = :lg_type';

$stmt = $dbTest->prepare($sqlBoth);
$stmt->bindValue(':lg_type', 'email_sent', PDO::PARAM_STR);
$stmt->execute();

$resultBoth = $stmt->fetchAll();
$stmt->closeCursor();

Output:

pdone_legacy and archive_pfizer

Array
(
    [0] => Array
        (
            [hcp_id] => hcp_id_01
            [rep_id] => rep_od_01
            [type] => email_sent
            [ID] => ID_01
            [brand_id] => brand_id_01
            [createdAt] => 2015-09-24 01:42:51
            [modifiedAt] => 
        )
)

Database Connection:

/**
 * must have access rights to both db's
 */
// db connection to archive_pfizer and pdone_legacy
$dsn = 'mysql:host=localhost;dbname=pdone_legacy';
$username = 'pfizer';
$password = 'pfizer';
$options = array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
$dbTest = new PDO($dsn, $username, $password, $options);
$dbTest->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Test that we can access the separate databases...

1) archive_pfizer (logger)

/* ----------------------------------------------------------
 *   Query archive_pfizer (logger)
 */
$sqlArchive = 'SELECT  hcp_id, rep_id, type, session_id, createdAt, modifiedAt
FROM archive_pfizer.logger
WHERE session_id = :a_session_id';

$stmt = $dbTest->prepare($sqlArchive);
$stmt->bindValue(':a_session_id', 'session_id_01', PDO::PARAM_STR);
$stmt->execute();

$resultArchive = $stmt->fetchAll();
$stmt->closeCursor();

echo '<br />', 'archive_pfizer.logger', '<br />';
echo '<pre>';
print_r($resultArchive);
echo '</pre>';

2) pdone_legacy (session_brand_presentation)

/* --------------------------------------------------
 *  Query pdone_legacy (session_brand_presentation)
 */
$sqlPDone = 'SELECT ID,
                    local_session_id,
                    brand_id,
                    createdAt,
                    modifiedAt
FROM pdone_legacy.session_brand_presentation
WHERE local_session_id = :sbp_session_id';

$stmt = $dbTest->prepare($sqlPDone);
$stmt->bindValue(':sbp_session_id', 'session_id_01', PDO::PARAM_STR);
$stmt->execute();

$resultPDone = $stmt->fetchAll();
$stmt->closeCursor();
echo '<br />', 'pdone_legacy.session_brand_presentation', '<br />';
echo '<pre>';
print_r($resultPDone);
echo '</pre>';


回答2:

You won't be able to do it directly with PDO. PDO is just an abstraction for your database connection.

If one of your two databases is a PostgreSQL one you could setup a Foreign Data Wrapper. With MySQL you should check the Federated storage engine.



标签: php pdo mariadb