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. Ho开发者_如何转开发wever 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
)
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.
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
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.
精彩评论