Как я создаю перекрестный запрос базы данных в PHP?

В нашем последнем эпизоде (Как я создал перекрестный запрос базы данных в MySQL) я изучил, как создать перекрестный запрос базы данных в MySQL. Это работало отлично, но когда наш герой пытался использовать это новооткрытое знание в PHP, он нашел свой СБОЙ лучшего друга, ожидающий его.

Я смотрел на mysql_select_db для PHP. Это, кажется, подразумевает, что, если я хочу использовать MySQL с PHP, у меня есть несколько вариантов:

  1. Использовать mysql_select_db но застряньте только с использованием одного дб за один раз. Это - наша текущая установка и помещение базы данных, поскольку идентификатор пространства имен, кажется, не работает (это хорошо работает в оболочке MySQL, таким образом, я знаю, что это не проблема с нашей установкой сервера MySQL).

  2. Не использовать mysql_select_db. От некоторых примеров я видел, это, кажется, означает, что я должен указать дб для каждого запроса, который я делаю. Это имеет смысл, так как я не использовал mysql_select_db сказать PHP, к какому дб я хочу получить доступ. Это также делает печальным, так как я не хочу проходить весь свой код и предварительно ожидать имя дб к каждому запросу.

Есть ли что-то лучше, чем это? Существует ли способ для меня сделать перекрестный запрос MySQL дб в PHP, не имея необходимость к чему-то сумасшедшему как (2)?

РАЗЪЯСНЕНИЕ: Ни один из предложенных ответов на самом деле не позволил мне сделать перекрестный запрос дб. Вместо этого они позволяют мне получать доступ к двум другим DBS отдельно. Я хочу решение, которое позволяет мне делать что-то как SELECT foreign_db.login.username, firstname, lastname from foreign_db.login, user where ... НЕ только делают различные запросы к другому DBS. Если это имеет значение, (2) не работает на меня.

12
задан Community 23 May 2017 в 12:02
поделиться

9 ответов

Вам нужно, чтобы ваши базы данных работали на одном хосте.

Если это так, у вас должна быть возможность использовать mysql_select_db в вашей любимой базе данных / базе данных по умолчанию и вручную указать внешнюю базу данных.

$db = mysql_connect($hots, $user, $password);
mysql_select_db('my_most_used_db', $db);

$q = mysql_query("
    SELECT *
    FROM   table_on_default_db a, `another_db`.`table_on_another_db` b
    WHERE  a.id = b.fk_id
");

Если ваши базы данных работают на другом хосте, вы не сможете подключиться напрямую. Но тогда вы можете сделать 2 запроса.

$db1 = mysql_connect($host1, $user1, $password1);
$db2 = mysql_connect($host2, $user2, $password2);

$q1 = mysql_query("
    SELECT id
    FROM   table
    WHERE  [..your criteria for db1 here..]
", $db1);
$tmp = array();
while($val = mysql_fetch_array($q1))
    $tmp[] = $val['id'];

$q2 = mysql_query("
    SELECT *
    FROM   table2
    WHERE  fk_id in (".implode(', ', $tmp).")
", $db2);
21
ответ дан 2 December 2019 в 05:03
поделиться

Решение могло бы заключаться в следующем :

  • использовать mysql_select_db для выбора "по умолчанию" базы данных (т.е. наиболее используемой)
  • и указывать имя БД только в запросах, которые должны работать с "вторым" (т.е. наименее используемой) БД.

Но это жизнеспособное решение только в том случае, если у вас одна БД используется больше, чем другая...


Из любопытства: вы пытались установить несколько соединений с сервером БД -- т.е. по одному для каждой БД?

Возможно, вы сможете :

  • подключиться к первой БД с помощью mysql_connect, а затем выбрать первую БД с помощью mysql_select_db
  • , а затем подключиться ко второй БД, передав true для параметра new_link параметра mysql_connect, если это необходимо, и, затем, выбрав вторую БД с помощью mysql_select_db

, работать с идентификатором соединения, возвращаемым первым, или вторым вызовом на mysql_connect, в зависимости от того, на какую БД вы хотите отправлять запросы.


В качестве побочной надписи : лучшим" / "чистейшим" решением было бы не прямое использование функций mysql_*, а работа с каким-то ORM фреймворком, который имел бы возможность работать с несколькими соединениями БД одновременно (не уверен), но, возможно, Doctrine сможет это сделать - это действительно хороший ORM)

3
ответ дан 2 December 2019 в 05:03
поделиться

Может быть, это тот код, который вам нужен


//create links
$link1 = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$link2 = mysql_connect('localhost', 'mysql_user', 'mysql_password');

//set db on every link
mysql_select_db('foo', $link1);
mysql_select_db('bar', $link2);

//do query with specified link
$result1 = mysql_query($query1,$link1);
$result2 = mysql_query($query2,$link2);

Обратите внимание, что мы не делали mysql_select_db между запросами, и в запросе мы также не использовали имя базы данных.

0
ответ дан 2 December 2019 в 05:03
поделиться

Всякий раз, когда вы выбираете из нескольких таблиц, вы должны выделить псевдоним. Отсюда все довольно просто:

SELECT
    a.id, a.name, a.phone,
    b.service, b.provider

FROM
    `people` AS a,

LEFT JOIN
    `other_database`.`providers` AS b ON a.id = b.userid

WHERE
    a.username = 'sirlancelot'

Как упоминали другие на этой странице, база данных должна быть на том же хосте и на том же экземпляре. Вы не можете опрашивать БД с другого сервера с таким синтаксисом.

0
ответ дан 2 December 2019 в 05:03
поделиться

Вы можете использовать опцию «Двое»: «Не используйте MySQL_SELECT_DB », а затем используйте mysql_db_query вместо mysql_query ... что простой находку и заменить.

удачи!

0
ответ дан 2 December 2019 в 05:03
поделиться

Я настроил таблицы в отдельных тестовых базах данных следующим образом:

mysql> use test;
mysql> create table foo as select 42 as id from dual;
mysql> create database test2;
mysql> use test2;
mysql> create table bar as select 42 as id from dual;

Я запустил следующий сценарий PHP с MySQL 5.1.41 и PHP 5.3.1 на Mac OS X:

<?php

$link = mysql_connect('localhost', 'root', 'XXXX')
 or die('There was a problem connecting to the database.');
mysql_select_db('test');

$sql = "SELECT * FROM foo JOIN test2.bar USING (id)";
if (($result = mysql_query($sql)) === FALSE) {
  die(mysql_error());
}

while ($row = mysql_fetch_array($result)) {
  print_r($row);
}

Этот тест прошел успешно. Результатом является соединение двух таблиц в отдельных базах данных.

Вы всегда должны иметь возможность выбирать из таблиц, определенных соответствующими именами баз данных в SQL. API mysql в PHP не ограничивает вас запросом одной базы данных.

Вы всегда должны иметь возможность опустить квалификатор базы данных для «текущей» базы данных, которую вы объявляете с помощью mysql_select_db () .

1
ответ дан 2 December 2019 в 05:03
поделиться

Я только что попробовал этот простой код на моем компьютере И это работает отлично:

<?php

$conn = mysql_connect('localhost', 'root', '....');
mysql_select_db('aliro');

$sql = 'select * ' .
    'from aliro_permissions a ' .
    'left join cmsmadesimple.cms_permissions b on a.id=b.permission_id ';

$res = mysql_query($sql)
    or die(mysql_error());
while($row = mysql_fetch_assoc($res)){
    print_r($row);
}

?>

(конечно, сам запрос бессмысленны, это просто пример.)

Так что я не могу видеть, какова ваша точная проблема. Если вы хотите синтаксис, который проще, что это придется предоставить пример того, какой SQL вы хотите написать.

0
ответ дан 2 December 2019 в 05:03
поделиться

Малый вариант Verbose, который вы предоставляете руководством MySQL сама:

В следующем примере обращается Авторская таблица из базы данных DB1 и таблица редактора от DB2 База данных:

USE db1;
SELECT author_name, editor_name FROM author, db2.editor
WHERE author.editor_id = db2.editor.editor_id;
0
ответ дан 2 December 2019 в 05:03
поделиться

То, что я делаю, это то, что мой контроллер вида настраивает вид прокрутки:

[scrollView setCanCancelContentTouches:NO];
[scrollView setDelaysContentTouches:NO];

И в моем дочернем виде у меня есть таймер, потому что двухпальцевые касания обычно начинаются как один палец, за которым быстро следуют два пальца.:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    // Hand tool or two or more touches means a pan or zoom gesture.
    if ((selectedTool == kHandToolIndex) || (event.allTouches.count > 1)) {
        [[self parentScrollView] setCanCancelContentTouches:YES];
        [firstTouchTimer invalidate];
        firstTouchTimer = nil;
        return;
    }

    // Use a timer to delay first touch because two-finger touches usually start with one touch followed by a second touch.
    [[self parentScrollView] setCanCancelContentTouches:NO];
    anchorPoint = [[touches anyObject] locationInView:self];
    firstTouchTimer = [NSTimer scheduledTimerWithTimeInterval:kFirstTouchTimeInterval target:self selector:@selector(firstTouchTimerFired:) userInfo:nil repeats:NO];
    firstTouchTimeStamp = event.timestamp;
}

Если второй касание начинается: событие приходит с более чем одним пальцем, вид прокрутки позволяет отменить касания. Таким образом, если пользователь выполняет панорамирование с использованием двух пальцев, в этом представлении появится сообщение touchesCanced: .

-121--1151870-

Только без < input type = «file» > путем встраивания прозрачного флэш-фильма над дива. затем можно использовать сгенерированное пользователем событие click (соответствующее новым правилам безопасности Flash 10), чтобы вызвать вызов flash FileReference.browse .

Он предлагает дополнительную зависимость от quirksmode пути , но взамен вы получаете больше событий (например, встроенных событий).

-121--775342-

После прочтения вашего разъяснения у меня сложилось впечатление, что вы действительно хотите запросить таблицы, находящиеся в двух отдельных экземплярах MySQL сервера. По крайней мере, ваш текст пояснения:

SELECT foreign_db.login.username, firstname, lastname от foreign_db.login, user где

предлагает выполнить один запрос при входе в систему как два пользователя (которые могут находиться или не находиться на одном экземпляре сервера mysql).

В вашем вопросе вы сказали, что хотите запросить данные из двух разных баз данных, но важно понимать, что один экземпляр MySQL может иметь много баз данных. Для нескольких баз данных, управляемых одним экземпляром mysql, решение, предложенное в вопросе, на который вы ссылаетесь, просто работает: просто префиксируйте имя таблицы с именем баз данных, разделяя имена базы данных и таблицы точкой: < имя _ базы _ данных >. < имя _ таблицы > .

Но, как я уже отмечал, это работает только в том случае, если:

  1. все базы данных, к которым вы обращаетесь в одном запросе, находятся на одном сервере, то есть управляются одним и тем же экземпляром MySQL
  2. , пользователь, подключенный к базе данных, имеет право доступа к обеим таблицам.

Scenario1: базы данных на одном хосте: предоставить соответствующие привилегии и квалифицировать имена таблиц

Поэтому, если таблицы фактически находятся в одном экземпляре mysql, нет необходимости во втором входе или подключении - просто предоставьте пользователю базы данных, который используется для подключения к базе данных, соответствующие привилегии для выбора из всех необходимых таблиц. Это можно сделать с помощью синтаксиса GRANT , описанного здесь: http://dev.mysql.com/doc/refman/5.1/en/grant.html

Например, GRANT SELECT ON sakila.film TO 'test' @ '%' позволит пользователю test @% выбрать данные из таблицы film в базе данных sakila . После этого пользователь может обратиться к этой таблице, используя sakila.film (так называемое квалифицированное имя таблицы), или если в текущей базе данных установлено значение sakila , просто как фильм

Scenario2:базы данных, управляемые различными экземплярами MySQL: FEDERATED engine

Если таблицы, к которым вы хотите получить доступ, фактически управляются двумя различными экземплярами MySQL, есть один трюк, который может работать или не работать, в зависимости от вашей конфигурации. Поскольку MySQL 5,0 mysql поддерживает механизм FEDERATED места хранения. Это позволяет создать таблицу, которая фактически является не таблицей, а peephole к таблице на удаленном сервере. Этот механизм документирован здесь: http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html

Например, если вы знаете, что в базе данных misc на удаленном хосте есть эта таблица:

CREATE TABLE t (
    id int not null primary key
,   name varchar(10) not null unique
)

вы можете сделать локальный «указатель» на эту удаленную таблицу, используя эту:

CREATE TABLE t (
    id int not null primary key
,   name varchar(10) not null unique
)
ENGINE = FEDERATED
CONNECTION='mysql://<user>@<remote-server>:<remote-port>/misc/t';

К сожалению, механизм FEDERATED не всегда доступен, поэтому вам необходимо сначала проверить, можно ли даже использовать ее. Но предположим, что это так, тогда вы можете просто использовать локальную таблицу t в своих запросах, как и любую другую таблицу, и MySQL будет взаимодействовать с удаленным сервером и выполнять соответствующие операции с физической таблицей на другой стороне.

Предупреждение: имеется несколько проблем оптимизации с таблицами FEDERATED. Вы должны выяснить, если и в какой степени они применимы к вам. Например, применение WHERE к федеративной таблице во многих случаях может привести к тому, что все содержимое таблицы будет перенесено по проводу на локальный сервер, где будет применена фактическая фильтрация. Другая проблема связана с созданием таблицы: необходимо быть очень уверенным, что определения федеративной таблицы и таблицы, на которую она указывает, совпадают точно, за исключением предложения ENGINE (и CONNECTION). Если, например, имеется другой набор символов, данные могут поступать полностью искаженными после прохождения по проводу.

Если требуется использовать таблицы FEDERATED , прочтите эту статью http://oreilly.com/pub/a/databases/2006/08/10/mysql-federated-tables.html , чтобы определить, подходит ли она для конкретного варианта использования.

Если вы думаете, что вам это нужно, у меня есть утилита для создания федеративных таблиц здесь: http://forge.mysql.com/tools/tool.php?id=54

Scenario3: не может использовать ФЕДЕРАТИВНЫЕ, но таблицы на разных экземплярах MySQL

Наконец, если у вас есть таблицы на разных экземплярах MySQL, но не может по какой-то причине использовать федеративный обработчик таблиц, вашей удачи я боюсь. Вам просто придется выполнять запросы к обоим экземплярам MySQL, получать результаты и делать что-то интеллектуальное с ним в PHP. В зависимости от ваших точных требований, это может быть вполне жизнеспособным решением

Я думаю, вам нужно решить для себя, какая часть моего ответа лучше всего взывает к вашей проблеме, и добавить комментарий на случай, если вам понадобится дополнительная помощь. ТИА Роланд.

5
ответ дан 2 December 2019 в 05:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: