Jak łączysz się z wieloma bazami danych MySQL na jednej stronie?

179

Mam informacje rozłożone w kilku bazach danych i chcę umieścić wszystkie informacje na jednej stronie za pomocą PHP. Zastanawiałem się, jak mogę połączyć się z wieloma bazami danych na jednej stronie PHP.

Wiem, jak połączyć się z jedną bazą danych, używając:

$dbh = mysql_connect($hostname, $username, $password) 
        or die("Unable to connect to MySQL");

Jednak czy mogę po prostu użyć wielu poleceń „mysql_connect”, aby otworzyć inne bazy danych, i skąd PHP wiedziałby, z której bazy danych chcę pobrać informacje, jeśli mam podłączone wiele baz danych.

JoshFinnie
źródło

Odpowiedzi:

335

Ostrzeżenie: mysql_xx funkcje są przestarzałe od wersji php 5.5 i usunięte od wersji php 7.0 (patrz http://php.net/manual/intro.mysql.php ), użyj mysqli_xxfunkcji lub zobacz odpowiedź poniżej z @Troelskn


Możesz wykonać wiele wywołań mysql_connect(), ale jeśli parametry są takie same, musisz przekazać wartość true dla parametru „ $new_link” (czwarty), w przeciwnym razie to samo połączenie zostanie ponownie użyte. Na przykład:

$dbh1 = mysql_connect($hostname, $username, $password); 
$dbh2 = mysql_connect($hostname, $username, $password, true); 

mysql_select_db('database1', $dbh1);
mysql_select_db('database2', $dbh2);

Następnie do zapytania bazy danych 1 przekaż pierwszy identyfikator linku:

mysql_query('select * from tablename', $dbh1);

a dla bazy danych 2 przekaż drugi:

mysql_query('select * from tablename', $dbh2);

Jeśli nie podasz identyfikatora łącza, zostanie użyte ostatnie utworzone połączenie (w tym przypadku reprezentowane przez $dbh2), np .:

mysql_query('select * from tablename');

Inne opcje

Jeśli użytkownik MySQL ma dostęp do obu baz danych i znajdują się na tym samym hoście (tzn. Oba DB są dostępne z tego samego połączenia), możesz:

  • Pozostaw jedno połączenie otwarte i zadzwoń, mysql_select_db()aby przełączać się między nimi w razie potrzeby. Nie jestem pewien, czy jest to czyste rozwiązanie i możesz w końcu zapytać o niewłaściwą bazę danych.
  • Podaj nazwę bazy danych, odwołując się do tabel w zapytaniach (np SELECT * FROM database2.tablename.). Może to być trudny do wdrożenia.

Przeczytaj również odpowiedź troelskn, ponieważ jest to lepsze podejście, jeśli możesz używać PDO zamiast starszych rozszerzeń.

Tom Haigh
źródło
2
+1 To rozwiązanie działało dla mnie. Po dwóch dniach debugowania, dlaczego moje niestandardowe szablony WordPress traciły dostęp do obiektu $ WP_Query po wywołaniu drugiego połączenia z bazą danych ...
Eddie B
czy możliwe jest ustawienie jednego z nich jako domyślnego i dodawanie $dbh2drugiego tylko w razie potrzeby? Konieczność zmiany wszystkich zapytań dotyczących tego podejścia do pracy prawdopodobnie zajęłaby dni po prostu znalezienie wszystkich ...
ThomasK
@ThomasK, możesz zawinąć mysql_query w funkcję z domyślnym parametrem, powiedzmy, db_query($query,$db='db1')a następnie masowo zaktualizować wszystkie stare zapytania, db_query($query)a następnie niestandardowo zaktualizować niestandardowe dodb_query($query,'db2')
joshuahedlund
Które połączenie zostanie użyte za pomocą Twojej metody, jeśli zdefiniuję dwa połączenia, ale nie określę, którego połączenia użyć w zapytaniu?
Peter
1
@Peter: zgodnie z php.net/manual/en/function.mysql-query.php :If the link identifier is not specified, the last link opened by mysql_connect() is assumed.
Tom Haigh
97

Jeśli używasz PHP5 (i powinieneś, biorąc pod uwagę, że PHP4 jest przestarzałe), powinieneś używać PDO , ponieważ powoli staje się on nowym standardem. Jedną (bardzo) ważną zaletą PDO jest to, że obsługuje parametry powiązane, co sprawia, że ​​kod jest znacznie bezpieczniejszy.

Łączyłbyś się przez PDO, tak jak to:

try {
  $db = new PDO('mysql:dbname=databasename;host=127.0.0.1', 'username', 'password');
} catch (PDOException $ex) {
  echo 'Connection failed: ' . $ex->getMessage();
}

(Oczywiście zastąp nazwę bazy danych, nazwę użytkownika i hasło powyżej)

Następnie możesz wykonać zapytanie do bazy danych w następujący sposób:

$result = $db->query("select * from tablename");
foreach ($result as $row) {
  echo $row['foo'] . "\n";
}

Lub, jeśli masz zmienne:

$stmt = $db->prepare("select * from tablename where id = :id");
$stmt->execute(array(':id' => 42));
$row = $stmt->fetch();

Jeśli potrzebujesz wielu połączeń otwartych jednocześnie, możesz po prostu utworzyć wiele wystąpień PDO:

try {
  $db1 = new PDO('mysql:dbname=databas1;host=127.0.0.1', 'username', 'password');
  $db2 = new PDO('mysql:dbname=databas2;host=127.0.0.1', 'username', 'password');
} catch (PDOException $ex) {
  echo 'Connection failed: ' . $ex->getMessage();
}
troelskn
źródło
5
Dlaczego ta odpowiedź nie jest na górze ?! To jest właściwy sposób, aby to zrobić.
Aditya, poseł
10
@aditya menon moim zdaniem właściwy sposób robienia czegoś często nie jest właściwą odpowiedzią na pytanie. Pytający nie używał PDO w swoim pytaniu, ale natywne funkcje phys mysql, więc uważam, że najodpowiedniejsza odpowiedź będzie zgodna z kodem pytającego.
Jonathan dos Santos
2
@adityamenon, pod czyim zwierzchnictwem? Pamiętaj, że użytkownik ma zawsze rację ... PDO jest najlepszym sposobem, ale oba sposoby są właściwym sposobem rozwiązania problemu z użytkownikiem. Zwróć uwagę na różnicę między tym, co właściwe, a tym, co najlepsze. Tak ... Nudzę się, więc musiałem złożyć oświadczenie.
JustinKaz,
Czy $ db1 i $ db2 reprezentują wiele połączeń mysql? Jeśli tak, to nie jest dobrze. Czy jest jakiś sposób, aby pomieścić wiele baz danych za pomocą tylko jednego połączenia?
datasn.io
@kavoir Dlaczego tego chcesz? W razie potrzeby możesz zmienić bazę danych na bieżącym połączeniu use DATABASENAME, ale nie widzę sensu?
troelskn
9

Właśnie ułatwiłem moje życie:

CREATE VIEW another_table AS SELECT * FROM another_database.another_table;

mam nadzieję, że to jest pomocne ... na zdrowie ...

Ihsan Kusasi
źródło
1
Jest to najłatwiejsze rozwiązanie, jeśli nie masz tabel o tej samej nazwie w obu bazach danych. Robisz to raz, a potem nie musisz się już martwić o wiele baz danych.
Erel Segal-Halevi
@ ErelSegal-Halevi, o ile potrzebujesz dostępu tylko do odczytu do danych z drugiej bazy danych, prawda?
Buttle Butkus
6

Zamiast mysql_connect użyj mysqli_connect .

mysqli zapewnia funkcję łączenia wielu baz danych jednocześnie.

$Db1 = new mysqli($hostname,$username,$password,$db_name1); 
// this is connection 1 for DB 1

$Db2 = new mysqli($hostname,$username,$password,$db_name2); 
// this is connection 2 for DB 2
kaushik
źródło
1
$ nazwa_hosta = „Twoja nazwa_Hosta DB”; $ nazwa_użytkownika = „Twoja nazwa_Użytkownika DB”; $ hasło = „Twoje hasło DB”; $ db_name1 = „Twoje hasło DB 1”; $ db_name2 = 'Your DB_Name 2';
kaushik,
Po prostu źle, że to nie zadziałamysql_connect
Nico Haase,
4

Wypróbuj poniższy kod:

    $conn = mysql_connect("hostname","username","password");
    mysql_select_db("db1",$conn);
    mysql_select_db("db2",$conn);

    $query1 = "SELECT * FROM db1.table";
    $query2 = "SELECT * FROM db2.table";

Możesz pobrać dane powyższego zapytania z obu baz danych, jak poniżej

$rs = mysql_query($query1);
while($row = mysql_fetch_assoc($rs)) {
    $data1[] = $row;
}

$rs = mysql_query($query2);
while($row = mysql_fetch_assoc($rs)) {
    $data2[] = $row;
}

print_r($data1);
print_r($data2);
Paks
źródło
Podane dwa zapytania działałyby w ten sam sposób, mysql_select_dbnawet nie dzwoniąc ani razu - także dwukrotne wywołanie go bez niczego innego w środku jest bezużyteczne
Nico Haase
4
$dbh1 = mysql_connect($hostname, $username, $password);  
$dbh2 = mysql_connect($hostname, $username, $password, true); 

mysql_select_db('database1', $dbh1); 
mysql_select_db('database2',$dbh2); 

mysql_query('select * from tablename', $dbh1);
mysql_query('select * from tablename', $dbh2);

Jest to najbardziej oczywiste rozwiązanie, którego używam, ale pamiętaj tylko, że jeśli nazwa użytkownika / hasło dla obu baz danych jest dokładnie taka sama na tym samym hoście, to rozwiązanie zawsze będzie korzystało z pierwszego połączenia. Nie mylcie się więc, że to nie działa w takim przypadku. To, co musisz zrobić, to utworzyć 2 różnych użytkowników dla 2 baz danych i będzie działać.

Leniwy facet
źródło
3

Jeśli naprawdę nie potrzebujesz w grze więcej niż jednej instancji obiektu PDO, rozważ następujące kwestie:

$con = new PDO('mysql:host=localhost', $username, $password, 
      array(PDO::ATTR_PERSISTENT => true));

Zwróć uwagę na brak dbname=argumentów konstrukcyjnych.

Gdy łączysz się z MySQL za pomocą terminala lub innego narzędzia, nazwa bazy danych nie jest potrzebna od samego początku. Możesz przełączać się między bazami danych, używając USE dbnameinstrukcji za pomocą PDO::exec()metody.

$con->exec("USE someDatabase");
$con->exec("USE anotherDatabase");

Oczywiście możesz zawinąć to w instrukcję catch try.

Michael Ratcliffe
źródło
Dla tych, którzy wypróbują powyższe podejście, spójrz na to przed stackoverflow.com/a/14933070/1623579
TheFrost
Uwielbiam to rozwiązanie! Mogę obejść się bez trwałych ustawień, ale tworzenie instancji PDO jest świetnym rozwiązaniem. Otrzymujesz domyślne połączenie bez połączenia z określoną bazą danych.
Chuck Burgess,
2

Możesz być w stanie użyć składni MySQLi, co pozwoli ci lepiej sobie z tym poradzić.

Zdefiniuj połączenia z bazą danych, a następnie za każdym razem, gdy chcesz wykonać zapytanie do jednej z bazy danych, określ właściwe połączenie.

Na przykład:

$Db1 = new mysqli('$DB_HOST','USERNAME','PASSWORD'); // 1st database connection 
$Db2 = new mysqli('$DB_HOST','USERNAME','PASSWORD'); // 2nd database connection

Następnie, aby wyszukać je na tej samej stronie, użyj czegoś takiego:

$query = $Db1->query("select * from tablename")
$query2 = $Db2->query("select * from tablename")
die("$Db1->error");

Przejście na MySQLi w ten sposób pomoże.

użytkownik3857891
źródło
Popraw swoją składnię (to nie jest sms) i sformatuj kod za pomocą narzędzi (na przykład Ctrl + K).
fedorqui „SO przestań szkodzić”
2

Tak naprawdę nie potrzebujesz select_db. Możesz wysłać zapytanie do dwóch baz danych jednocześnie. Najpierw przekaż dotację DB1do wyboru DB2przez GRANT select ON DB2.* TO DB1@localhost;. Potem FLUSH PRIVILEGES;. Wreszcie możesz wykonać „zapytanie do wielu baz danych”, takie jak SELECT DB1.TABLE1.id, DB2.TABLE1.username FROM DB1,DB2itp. (Nie zapomnij, że potrzebujesz dostępu do „root”, aby użyć polecenia grant

Nagibaba
źródło
1

jeśli używasz mysqli i masz dwa pliki db_connection. jak pierwszy jest

define('HOST','localhost');
define('USER','user');
define('PASS','passs');
define('**DB1**','database_name1');

$connMitra = new mysqli(HOST, USER, PASS, **DB1**);

drugi to

    define('HOST','localhost');
    define('USER','user');
    define('PASS','passs');
    define(**'DB2**','database_name1');

    $connMitra = new mysqli(HOST, USER, PASS, **DB2**);

Więc po prostu zmień nazwę parametru pass w mysqli, takich jak DB1 i DB2. jeśli przekażesz ten sam parametr w mysqli, załóżmy, że DB1 w obu plikach, to druga baza danych już się nie połączy. Więc pamiętaj, kiedy używasz dwóch lub więcej połączeń, podaj inną nazwę parametru w funkcji mysqli

Kamal Bunkar
źródło
-1
<?php
    // Sapan Mohanty
    // Skype:sapan.mohannty
    //***********************************
    $oldData = mysql_connect('localhost', 'DBUSER', 'DBPASS');
    echo mysql_error();
    $NewData = mysql_connect('localhost', 'DBUSER', 'DBPASS');
    echo mysql_error();
    mysql_select_db('OLDDBNAME', $oldData );
    mysql_select_db('NEWDBNAME', $NewData );
    $getAllTablesName    = "SELECT table_name FROM information_schema.tables WHERE table_type = 'base table'";
    $getAllTablesNameExe = mysql_query($getAllTablesName);
    //echo mysql_error();
    while ($dataTableName = mysql_fetch_object($getAllTablesNameExe)) {

        $oldDataCount       = mysql_query('select count(*) as noOfRecord from ' . $dataTableName->table_name, $oldData);
        $oldDataCountResult = mysql_fetch_object($oldDataCount);


        $newDataCount       = mysql_query('select count(*) as noOfRecord from ' . $dataTableName->table_name, $NewData);
        $newDataCountResult = mysql_fetch_object($newDataCount);

        if ( $oldDataCountResult->noOfRecord != $newDataCountResult->noOfRecord ) {
            echo "<br/><b>" . $dataTableName->table_name . "</b>";
            echo " | Old: " . $oldDataCountResult->noOfRecord;
            echo " | New: " . $newDataCountResult->noOfRecord;

            if ($oldDataCountResult->noOfRecord < $newDataCountResult->noOfRecord) {
                echo " | <font color='green'>*</font>";

            } else {
                echo " | <font color='red'>*</font>";
            }

            echo "<br/>----------------------------------------";

        }     

    }
    ?>
Sapan Mohanty
źródło
Więcej informacji można znaleźć na stronie github.com/sapankumarmohanty/CountRecordsAtMigrationFinalSync
htngapi