MySQL Insert into multiple databases - issue - php

I have two DB real and backDB. I would like to copy everything from one to a other with SQL... it seems not that easy. If anyone could help me out. Here is my code:
$newdbsql="CREATE TABLE $newdb LIKE $actdbname.`$acttable`";
$newresult = mysql_query($newdbsql, $bckconn) or die(mysql_error());
// copy all the data
$query = "INSERT INTO $newdb SELECT * FROM $actdbname.$acttable WHERE $acttable.azon < $upto";
$result = mysql_query($query, $bckconn) or die(mysql_error());
I've been fighting with it but I can't get it right... thanks
Update:
I can connect both DB and I can do simple selects as well. But where I want to read from A and copy to BackupDb it always connect just to one DB.
Error message:
SELECT command denied to "backup"user on the real DB...
Important info: I am on shared host so it is not that easy:)

You just need to grant SELECT permissions to the backup database user to the regular database:
GRANT SELECT ON `$actdbname`.* TO `backup`#`localhost`;
For best security, it isn't recommended to grant anything other than SELECT, since no other permissions should be needed.

Warning:
Please, don't use mysql_* functions to write new code. They are no longer maintained and the community has begun the deprecation process. See the red box?
Instead, you should learn about prepared statements and use either PDO or MySQLi. This article should give some details about deciding which API to use. For PDO, here is a good tutorial.
To replicate the database without using MySQL's internal replication feature, you can use the CREATE TABLE foo LIKE bar; and INSERT INTO foo SELECT * FROM bar; statements.
The first line will create a new table named foo using the exact same structure what bar had originally, and the second line will help you copy the whole contents of bar into foo.
Edit:
The table names can be said as foo, it will mean the foo table in your current database. But you can say baz.foo, which will mean the foo table in your baz database. Of course, your users needs the required privileges to have on both databases. The following code works:
mysql_connect("localhost", "username", "password");
mysql_select_db("original");
mysql_query("CREATE TABLE backup.foo LIKE original.bar");
mysql_query("INSERT INTO backup.foo SELECT * FROM original.bar");
mysql_close();

Related

How to join two tables from different databases

How to join two tables from different databases. One database is localhost, the other is in online.
$connectA = mysql_connect('localhost','root','','abc');
$connectB = mysql_connect('xxx','yyy','zzz','xyz');
I want to join department_name from table department which is having database abc and xyz.
You cannot as long as by join you mean using SQL JOINS. It is, because SQL query is always sent to specific database or server.
You need to send two independent queries, one for each database and then provide some logic in PHP to join them either by array_merge (full join) or some more advanced scripting.
Can't help more without seeing some code of your own.
As already has been said, it is not possible.
I would save the database connections and switch between the databases.
Just a simple example (and with mysqli)
$db1 = mysqli_connect("localhost", "my_user", "my_password", "world");
$db2 = mysqli_connect("localhost2", "my_user2", "my_password2", "world2");
And then when you want to execute a query
mysqli_query($db1, "SELECT * ...");
or other database
mysqli_query($db2, "SELECT * ...");
Save the results from your query's in arrays and then use for example array_merge to join them.
http://php.net/manual/en/function.array-merge.php
If the MySQL user has access to both databases and they are on the same host (i.e. both DBs are accessible from the same connection) you could:
Keep one connection open and call mysql_select_db() to swap between as necessary. I am not sure this is a clean solution and you could end up querying the wrong database.
Specify the database name when you reference tables within your queries (e.g. SELECT * FROM database2.tablename). This is likely to be a pain to implement.
Also please read troelskn's answer because that is a better approach if you are able to use PDO rather than the older extensions.
Use can use database federation (data virtualization) technologies like Teiid http://teiid.io and join the tables across the databases or even data from files and web services.

SELECT FROM a database named from a value in a JOIN

I have a SQL statement that has to pull information from two databases, one is a constant and known database, and the other is dynamically found in the first database. The databases structure looks like this:
(database) lookup
(table) test
(fields) key, database_name
(row sample) "foo", "database_foo"
(database) database_foo
(table) bar
(fields) important1, important2
(row sample) "silly", "test"
So my SQL statement looks like this:
SELECT
test.key as key,
test.database_name as database_name,
bar.important1 as important1,
bar.importnat2 as important2,
FROM
lookup.test as test,
(database_name).bar as bar, # this, obviously, doesn't work
WHERE
key = 'foo'
LIMIT 1;
Is there a way I can make this work, or is it better for me to just do two separate SQL statements, one for the lookup, and one for the database?
If you must do it this way then you need to use dynamic sql and a two statements.
You have your query built as a string and then you run an EXEC on the query once it's constructed.
In this case you would have a string variable for the db name, then you would create a query from this variable and your literal query, then you would simply execute it.
Be aware, though, this makes you vulnerable to SQL Injection if you don't control the input parameters.
Erland Sommarskog has a great primer on using dynamic SQL:
http://www.sommarskog.se/dynamic_sql.html
EDIT: From #BryanMoyle comment below, you will likely need to do both a separate query and dynamic sql. You need to extract the value in order to determine the other DB name... Since you cannot use the DB name as a variable otherwise, you'll need to SELECT this information first, then stick it into the subsequent query.
I personally go for 2 separate statements; it would make it easier to control for errors such as the the lookup provides a row, that the row provides a valid database, etc.
As Matthew pointed out, beware of SQLIA and sanitize all user input. I like to MD5 hash inputs and compare to the hash of the value looked up.
I'd go for two separate queries, mediated by php: It's simpler, more robust, and will keep you sane and productive. Write one query to find out which database you should be talking to. Use php (not SQL) to direct your query to that database:
$row = $lookup->prepare("SELECT database_name WHERE key = 'foo'")->execute()->fetch();
$db = $row[0];
Then you contact $db and ask for the row with key foo. Use PHP code to select the right open connection, or switch databases inside the connection with USE:
$query2 = "USE " . $db . "; SELECT * FROM bar where key == 'foo'"

How to connect 2 databases in php and mysql?

I have 2 databases. Users database and purchases database. Each database has different user and password.
If i want to execute a query to call both databases. How do I connect the databases?
$db = mysql_select_db(??????);
You don't have to care which db you select since you are giving to MySQL the database name in the queries.
i.e
SELECT * FROM db.table, db2.table
So whatever database you have selected it won't change a thing.
$db1 = mysql_connect($host1, $user1, $pass1);
mysql_select_db($db1, 'database1');
$db2 = mysql_connect($host2, $user2, $pass1);
mysql_select_db($db2, 'database2');
$query = "SELECT * FROM test";
mysql_query($db1, $query);
mysql_query($db2, $query);
EDIT: Ok, now I understand the problem (reading the comments to the other answers):
If you don't have the permission, you will not be able to do a statement which connects 2 databases.
If you have a user, which has permission to select from both databases, it should be possible by
SELECT * FROM db1.table, db2.table
call mysql_connect() twice and store the result in a variable. that variable can then be sent to just about every mysql_* call in php to tell you which one you are referring two.
Look at the second argument of mysql_select_db() and you will understand.
Edit: This way, you will of course not be able to use them both in the same query but unless your database users have granted access to both, I think it is your only option.

How do I construct a cross database query in PHP?

In our last episode (How I constructed a cross database query in MySQL) I learned how to construct a cross database query in MySQL. This worked great but when our hero tried to use this newfound knowledge in PHP he found his best friend FAIL waiting for him.
I took a look at mysql_select_db for PHP. This seems to imply that if I want to use MySQL with PHP, I have a couple of choices:
Use mysql_select_db but be stuck with only using one db at a time. This is our current setup and putting a database as a namespace identifier doesn't seem to work (it works fine in the MySQL shell so I know it's not a problem with our MySQL server setup).
Don't use mysql_select_db. From some of the examples I've seen, this seems to mean that I have to specify the db for every query that I make. This makes sense since I haven't used mysql_select_db to tell PHP what db I want to access. This also makes sad since I don't want to go through all my code and prepend a db name to every query.
Is there something better than this? Is there a way for me to do a cross db MySQL query in PHP without having to something crazy like (2)?
CLARIFICATION: None of the proposed answers actually let me do a cross db query. Instead, they allow me to access two different DBs separately. I want a solution that allows me to do something like SELECT foreign_db.login.username, firstname, lastname from foreign_db.login, user where ... NOT just make different queries to different DBs. For what it's worth, (2) doesn't work for me.
You will need your databases to run on the same host.
If so, you should be able to use mysql_select_db on your favourite/default db and manually specify a foreign database.
$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
");
If your databases run on a different host, you won't be able to join directly. But you can then make 2 queries.
$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);
After reading your clarification, I am under the impression that you actually want to query tables residing in two separate MySQL server instances. At least, your clarification text:
SELECT foreign_db.login.username, firstname, lastname from foreign_db.login, user where
suggests that you want to run one query while being logged in as two users (which may or may not reside on the same mysql server instance).
In your question, you said you wanted to query data from two different databases, but it is important to realize that one MySQL instance can have many, many databases. For multiple databases managed by the same mysql instance, the solution proposed in the question you linked to simply works: just prefix the table name with the name of the databases, separating database and table names with a dot: <db-name>.<table-name>.
But, like i pointed out, this only works if:
all databases you access in one query reside on the same server - that is, are managed by the same MySQL instance
the user that is connected to the database has the right privileges to access both tables.
Scenario1: databases on same host: grant appopriate privileges and qualify table names
So if the tables actually reside on the same mysql instance, there is no need for a second login or connection - simply grant the database user you use to connect to the datbase the appropriate privileges to select from all tables you need. You can do that with the GRANT syntax, documented here: http://dev.mysql.com/doc/refman/5.1/en/grant.html
For example, GRANT SELECT ON sakila.film TO 'test'#'%' will allow the user test#% to select data from the film table in the sakila database. After doing that, said user can refer to this table using sakila.film (so-called qualified table name), or if the current database is set to sakila, simply as film
Scenario2: databases managed by different MySQL instances: FEDERATED engine
If the tables you want to access are actually managed by two different MySQL instances, there is one trick that may or may not work, depending on your configuration. Since MySQL 5.0 mysql supports the FEDERATED storage engine. This lets you create a table that is not actually a table, but a peephole to a table on a remote server. This engine is documented here: http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html
For example, if you know there is this table in the misc database on the remote host:
CREATE TABLE t (
id int not null primary key
, name varchar(10) not null unique
)
you can make a local 'pointer' to that remote table using this:
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';
Unfortunately, the FEDERATED engine is not always available, so you have to check first if you can even use that. But suppose it is, then you can simply use the local table t in your queries, just like any other table, and MySQL will communicate with the remote server and perform the appropriate operations on the physical table on the other side.
Caveat: there are several optimization issues with FEDERATED tables. You should find out if and to what extent these apply to you. For instance, applying a WHERE to a federated table can in many cases result in the entire table contents being pullled over the wire to your local server, where the actual filtering will be appplied. Another issue is with table creation: you have to be very sure that the definitions of the federated table and the table it is pointing to match exacty, except for the ENGINE clause (and CONNECTION). If you have for example a different character set, the data may arrive completely garbled after travelling over the wire.
If you want to use FEDERATED tables, do read this article http://oreilly.com/pub/a/databases/2006/08/10/mysql-federated-tables.html to decide if its right for your particular use case.
If you think you do need it, I have a utility to create federated tables here: http://forge.mysql.com/tools/tool.php?id=54
Scenario3: can't use FEDERATED, but tables on different MySQL instances
Finally, if you have tables on different MySQL instances, but cannot for some reason use the federated table engine, your a out of luck I'm afraid. You are simply going to have to execute queries to both MySQL instances, receive the results and do something intelligent with it in PHP. depending on your exact requirements, this may be a perfectly viable solution
I guess you need to decide for yourself which part of my answer best appeals to your problem, and add a comment in case you need more help. TIA Roland.
A solution might be to :
use mysql_select_db to select the "default" (i.e. most used) database
and specify the DB name only in queries that have to work with the "second" (i.e. least used) database.
But this is only a viable solution if you have one DB that's more used than the other...
Out of curiosity : did you try establishing several connections to your DB server -- i.e. one for each database ?
You might be able to :
connect to the first DB with mysql_connect, and, then, select the first DB with mysql_select_db
and, then, connect to the second DB, passing true for the new_link parameter of mysql_connect if necessary, and, then, selecting the second DB with mysql_select_db
Then, work with the connection identifier returned by the first, or second, call to mysql_connect, depending on which DB you want to issue queries.
As a sidenote : the "best" / "cleanest" solution would be not using mysql_* functions directly, but working with some kind of ORM framework, that would have the ability to work with several DB connections at the same time (not sure, but maybe Doctrine can do that -- it's a real good ORM)
I set up tables in separate test databases as follows:
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;
I ran the following PHP script with MySQL 5.1.41 and PHP 5.3.1 on 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);
}
This test succeeds. The result is the join between the two tables in separate databases.
You should always be able to select from table(s) qualified by their respective database names in SQL. The mysql API in PHP does not restrict you to querying one database.
You should always be able to omit the database qualifier for the "current" database, which you declare with mysql_select_db().
Maybe this is the code that you want
//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);
Note that we didn't do a mysql_select_db between queries , and we didn't use the database name in the query either.
Whenever you are SELECTing from multiple tables you have to sepcify an alias. So it's pretty simple from there:
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'
As others on this page have mentioned, the database must be on the same host and instance. You cannot query a database from another server with this syntax.
The less verbose option you have is provided by the MySQL Manual itself:
The following example accesses the
author table from the db1 database and
the editor table from the db2
database:
USE db1;
SELECT author_name, editor_name FROM author, db2.editor
WHERE author.editor_id = db2.editor.editor_id;
You can use option two: "Don't use mysql_select_db" and then use mysql_db_query instead of mysql_query ... which is a simple find and replace.
Best of luck!
I've just tried this simple code in my computer and it works perfectly:
<?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);
}
?>
(Of course, the query itself is meaningless, it's just an example.)
So I can't really see what your exact problem is. If you want a syntax that's simpler that this, you'll have to provide an example of what kind of SQL you want to write.

Postgresql and PHP: is the currval a efficent way to retrieve the last row inserted id, in a multiuser application?

Im wondering if the way i use to retrieve the id of the last row inserted in a postgresql table is efficent..
It works, obviously, but referencing on the serial sequence currval value could be problematic when i have many users adding rows in the same table at the same time.
My actual way is:
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
pg_close($pgConnection);
Well, its just a test atm.
But anyway, i can see 3 issues with this way:
Referencing on the customer_id_seq, if two user do the same thing in the same time, could happen that them both get the same id from that way... or not?
I have to know the table's sequence name. Becose pg_get_serial_sequence dont works for me (im newbie on postgresql, probably is a configuration issue)
Any suggestion/better ways?
p.s: i can't use the PDO, becose seem lack a bit with the transaction savepoint; I wont use zend and, in the end, i'll prefer to use the php pg_* functions (maybe i'll build up my classes in the end)
EDIT:
#SpliFF(thet deleted his answer): this would works better?
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
pg_query("BEGIN");
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
//do somethings with the new customer id
pg_query("COMMIT");
pg_close($pgConnection);
If you use a newer version of PostgreSQL (> 8.1) you should use the RETURNING clause of INSERT (and UPDATE) command.
OTOH if you insist on using one of the sequence manipulation functions, please read the fine manual. A pointer: "Notice that because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did."
Insert and check curval(seq) inside one transaction. Before commiting transaction you'll see curval(seq) for your query and no matter who else inserted at the same time.
Don't remember the syntax exactly - read in manual (last used pgsql about 3 years ago), but in common it looks like this:
BEGIN TRANSACTION;
INSERT ...;
SELECT curval(seq);
COMMIT;
ex. minsert into log (desc,user_id) values ('drop her mind',6) returning id

Categories