Question

Is it possible to do cross database joins in drupal?

Say you have two databases, drupal and old_data_source. You want to join drupal.node to old_data_source.page.

db_set_active() can be called to use multiple databases. However can't find anything about cross database table joins!

(I'm looking into this as part of a migration script and will be removing old_data_source)

Was it helpful?

Solution

Drupal doesn't support having more than one active database at a time. Main reason is probably that this is a mysql specific feature.

You can do this with php and skip the Drupal database layer. Since it's only for a migration script that should be run once, it'll be fine to make the code database specific. Just us mysql_ connect etc. Probably be a good idea to end using db_set_active

OTHER TIPS

There is a little-known trick to accomplish this, which relies on a feature called table prefixing. You can configure your settings.php to prefix certain tables in your queries with the name of another database, so you can do cross-database joins.

Have a look at the examples in the comments of the default.settings.php (similar syntax applies in Drupal 6) to see how to set this up. In the case of the original question, you'd have a prefix array on your default $databases entry that looks like:

'prefix' => array('page' => 'old_data_source.'),

And then build a query with something like:

db_query("SELECT * FROM {node} n LEFT JOIN {page} p on n.nid=p.nid");

The Drupal DB abstraction layer will interpret the {page} and convert it to SQL like:

SELECT * FROM node n LEFT JOIN old_data_source.page p on n.nid=p.nid;

The only other thing to make sure of is that the database user associated with your default Drupal database has privileges to access both databases, or this trick won't work.

I would just like to add to this answer, because I confronted this problem myself recently. The easiest solution by far and away (in my case) was to create a mysql view that did the join behind the scenes. That eliminates the need for the cross database join within drupal itself.

In addition to using the prefix in settings.php trick noted before me, you can also hardcode the prefix in the query string that you pass to db_query() (similar to what you did in your question).

So in this case you'd have

drupal.node inner join old_data_source.page on blablabla

Tested on d7.

Of course the user you're using in the db_set_active argument has to have access to both databases.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top