PHP: copy MySQL database tables into new database table with additional columns - php

I am looking for a way to copy an existing database with multiple tables into a new database with the same tables and columns + some additional columns. So far so good. If I just copy the database to a new database with the same amount of tables and columns I am doing it like this:
+---------+---------+---------+
| TABLE 1 | | |
+---------+---------+---------+
| Col1 | Col2 | Col3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
+---------+---------+---------+
copy to:
+---------+---------+---------+
| TABLE 2 | | |
+---------+---------+---------+
| Col1 | Col2 | Col3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
+---------+---------+---------+
Code:
public function loadDB($db1,$db2){
$this->db->prepare("use ".$db1."");
$sqlshow = "SHOW TABLES ";
$statement = $this->db->prepare($sqlshow);
$statement->execute();
$tables = $statement->fetchAll(PDO::FETCH_NUM);
foreach($tables as $table){
$sql[] = "INSERT INTO ".$db2.".".$table[0]." SELECT * FROM ".$db1.".".$table[0]."; ";
}
$sqlState = implode(' ', $sql);
$insertStatement = $this->db->exec($sqlState);
return $insertStatement?$insertStatement:false;
}
This code works and my database is copied successfully with all my tables and values inside my tables. What I need now is a working example of how am I able to copy the database to a new database where all tables have four additional columns like this:
+---------+---------+---------+
| TABLE 1 | | |
+---------+---------+---------+
| Col1 | Col2 | Col3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
| Value 1 | Value 2 | Value 3 |
+---------+---------+---------+
copying to:
+---------+---------+---------+-----------+-----------+-----------+-----------+
| TABLE 2 | | | | | | |
+---------+---------+---------+-----------+-----------+-----------+-----------+
| Col1 | Col2 | Col3 | Counter | LoadDay | User | UserNew |
| Value 1 | Value 2 | Value 3 | NEW VALUE | NEW VALUE | NEW VALUE | NEW VALUE |
| Value 1 | Value 2 | Value 3 | NEW VALUE | NEW VALUE | NEW VALUE | NEW VALUE |
| Value 1 | Value 2 | Value 3 | NEW VALUE | NEW VALUE | NEW VALUE | NEW VALUE |
+---------+---------+---------+-----------+-----------+-----------+-----------+
Code (what I´ve tried so far):
public function loadDB($db1,$db2,$condition){
$this->db->prepare("use ".$db1."");
$sqlshow = "SHOW TABLES ";
$statement = $this->db->prepare($sqlshow);
$statement->execute();
$tables = $statement->fetchAll(PDO::FETCH_NUM);
foreach($tables as $table){
$sqlshow2 = "SHOW COLUMNS FROM ".$table[0]." ";
$statement = $this->db->prepare($sqlshow2);
$statement->execute();
$columns = $statement->fetchAll(PDO::FETCH_NUM);
foreach($columns as $column){
$sql[] = "INSERT INTO ".$db2.".".$table[0]." SELECT ".$column[0]." FROM ".$db1.".".$table[0]."; ";
}
$sql[] .= "INSERT INTO ".$db2.".".$table[0]." (`Counter`, `LoadDay`, `User`, `UserNew`) VALUES ('1', '".date("Y-m-d H:i:s")."', '".$condition."', '".$condition."')";
}
$sqlState = implode(' ', $sql);
var_dump($sqlState);
$insertStatement = $this->db->exec($sqlState);
return $insertStatement?$insertStatement:false;
}
The creation of the databases are working (not visible in my posted code here). I only get no values copied to my new tables inside my new database. What am I doing wrong here?

Your final SQL query comes out wrong. I suggest changing your code to somthing like this:
foreach($tables as $table){
$sqlshow2 = "SHOW COLUMNS FROM ".$table[0]." ";
$statement = $this->db->prepare($sqlshow2);
$statement->execute();
$columns = $statement->fetchAll(PDO::FETCH_NUM);
$sql[] = "INSERT INTO ".$db2.".".$table[0]." SELECT * , '1', '".date("Y-m-d H:i:s")."', '".$condition."', '".$condition."'" . " FROM ".$db1.".".$table[0]."; ";
}

Related

MySQL issue on INSERT ... SELECT ON DUPLICATE KEY UPDATE and LAST_INSERT_ID()

In MySQL, I have INSERT ... SELECT ON DUPLICATE KEY UPDATE query as below:
$sql = "INSERT INTO user ( name
, mobile
, email
, sex
, username
, password
)
SELECT u.name
, u.mobile
, u.email
, u.sex
, u.username
, u.password
FROM import_user u
WHERE u.name <> '' AND u.mobile <> ''
ON DUPLICATE KEY UPDATE
user_id = LAST_INSERT_ID(user_id),
name = VALUES (name),
mobile = VALUES (mobile),
email = VALUES (email),
sex = VALUES (sex)";
UPDATE:
This is the result from above query.
select user_id, role_id, name,sex, mobile from user;
+---------+---------------------------+--------+-------------+
| user_id | name | sex | mobile |
+---------+---------------------------+--------+-------------+
| 131 | Name 1 | Male | 435345345 |
| 132 | Name 2 | Male | 43543534 |
| 133 | Name 3 | Male | 45645644 |
| 134 | Name 4 | Male | 5345 |
| 135 | Name 5 | Male | 5465475 |
| 136 | Name 6 | Male | 56456546 |
+---------+---------------------------+--------+-------------+
Now I want to create an array of the user_id of either the insert or the update the records.
So, my expecting array should be
$uid = [131,132,133,134,135,136]
I tried it something like this, but it doesn't work for me. That mean I can get only one id.
$stmt = $pdo->prepare($sql);
$stmt->execute();
$uids[] = $pdo->lastInsertId();
So, May I know Is there a way to create an array from the effected user ID of the above query running?
DEMO:
CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY,
category INT,
value INT,
UNIQUE (category, value) );
CREATE TRIGGER tr_ai
AFTER INSERT ON test
FOR EACH ROW
SET #ids_array := CONCAT_WS(',', #ids_array, NEW.id);
CREATE TRIGGER tr_au
AFTER UPDATE ON test
FOR EACH ROW
SET #ids_array := CONCAT_WS(',', #ids_array, NEW.id);
SET #ids_array := NULL;
INSERT INTO test (category, value)
VALUES (1,11), (2,22);
SELECT * FROM test;
SELECT #ids_array;
id | category | value
-: | -------: | ----:
1 | 1 | 11
2 | 2 | 22
| #ids_array |
| :--------- |
| 1,2 |
SET #ids_array := NULL;
INSERT INTO test (category, value)
VALUES (1,111), (2,22)
ON DUPLICATE KEY
UPDATE value = NULL;
SELECT * FROM test;
SELECT #ids_array;
id | category | value
-: | -------: | ----:
1 | 1 | 11
3 | 1 | 111
2 | 2 | null
| #ids_array |
| :--------- |
| 3,2 |
-- do not reset #ids_array
INSERT INTO test (id, category, value)
VALUES (1,4,44), (22,2,22)
ON DUPLICATE KEY
UPDATE value = NULL;
SELECT * FROM test;
SELECT #ids_array;
id | category | value
-: | -------: | ----:
1 | 1 | null
3 | 1 | 111
2 | 2 | null
22 | 2 | 22
| #ids_array |
| :--------- |
| 3,2,1,22 |
db<>fiddle here

The Best Way For Two Sequential SELECT Table

Hello I have two tables to send consecutive queries.
For example, table A yields 1,2,3 ..
Then, look for data in table B of query 1,2,3 ..
tableA
_____________________
| uid | rate |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 4 |
tableB
_________________________
| rate | text |
| 1 | ONE |
| 2 | TWO |
| 3 | THREE |
| 4 | FOUR |
===
<?php
$sql = $con->query("SELECT * FROM tableA WHERE uid=1");
$user = $sql->fetch_array();
$ratings = $user['rate']; //1,2,3
$sql2 = $con->query("SELECT * FROM tableB WHERE rate IN('".$ratings."')");
$text = $sql2->fetch_array();
$results = $text['text']; //ONE, TWO, THREE
?>
How best to do that?
You can use this query:
Select tableA.*,tableB.*
from tableA
join tableB on tableA.rate=tableB.rate
where tableA.uid=1

create a sequence for rows with similar ids using php

i have a datastructure similar to this
+---------+---------+
| id | value |
+---------+---------+
| 1 | value |
1 | value |
| 1 | value |
| 1 | value |
| 1 | value |
| 2 | value |
| 2 | value |
| 2 | value |
| 3 | value |
| 3 | value |
| 3 | value |
| | |
+---------+---------+
I am trying to update this table to look something like this
+---------+---------+
| id | value |
+---------+---------+
| 1 | value 0 |
1 | value 1 |
| 1 | value 2 |
| 1 | value 3 |
| 1 | value 4 |
| 2 | value 0 |
| 2 | value 1 |
| 2 | value 2 |
| 3 | value 0 |
| 3 | value 1 |
| 3 | value 2 |
| | |
+---------+---------+
To achieve this, i have written php script that looks like this
$query = "select count(*) as count,id, value from foo group by id";
$sql=$con->prepare($query);
$sql->execute();
$sql->setFetchMode(PDO::FETCH_ASSOC);
while($row=$sql->fetch()){
$id[] = $row['id'];
$count[] = $row['count'];
$value[] = $row['value'];
echo "<pre>";
}
$c=array_combine($id, $count);
foreach ($c as $key=>$value){
for($i=0;$i<=$value;$i++){
$postid = $key;
if($i==0){
$multiple = "multiple";
$newvalue= $value;
}
else{
$x=$i-1;
$multiple = "multiple_".$x;
echo $multiple . "<br>";
$query2 = "update foo set value = :multiple";
$sql2=$con->prepare($query2);
$sql2->bindValue(':multiple', $multiple);
$sql2->execute();
}
}
}
The problem is that the code returns the following results
+---------+---------+
| id | value |
+---------+---------+
| 1 | value_1 |
1 | value_1 |
| 1 | value_1 |
| 1 | value_1 |
| 1 | value_1 |
| 2 | value_1 |
| 2 | value_1 |
| 2 | value_1 |
| 3 | value_1 |
| 3 | value_1 |
| 3 | value_1 |
| | |
+---------+---------+
What can i be possibly be doing wrong?
Thanks #Shadow
Your query runs fine but returns the following results
+------+-----------------------------------------------+
| id | value |
+------+-----------------------------------------------+
| 1 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 1 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 1 | multiple_1_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2 |
| 1 | multiple_1_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3 |
| 2 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 2 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 2 | multiple_1_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2 |
| 2 | multiple_1_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3 |
| 3 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 3 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 3 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
+------+-----------------------------------------------+
You can do the update iterating and creating data in such a way:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $pdo->prepare("SELECT * FROM foo");
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
$response = array();
foreach ($data as $dataIndex => $dataValue) {
if (!isset($response[$dataValue["id"]]["count"])) {
$response[$dataValue["id"]]["count"] = 0;
} else {
$response[$dataValue["id"]]["count"] ++;
}
$response[$dataValue["id"]]["values"][$dataValue["pid"]] = "value_" . $response[$dataValue["id"]]["count"];
$sth = $pdo->prepare("UPDATE foo SET value = '{$response[$dataValue["id"]]["values"][$dataValue["pid"]]}' WHERE pid = {$dataValue["pid"]}");
$sth->execute();
}
?>
But try to do an update using the least iteration not to create as many database queries , example:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $pdo->prepare("SELECT * FROM foo");
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
$response = array();
$update = array();
foreach ($data as $dataIndex => $dataValue) {
$response[$dataValue["id"]]["id"] = $dataValue["id"];
if (!isset($response[$dataValue["id"]]["count"])) {
$response[$dataValue["id"]]["count"] = 0;
} else {
$response[$dataValue["id"]]["count"] ++;
}
$response[$dataValue["id"]]["values"][$dataValue["pid"]] = "value_" . $response[$dataValue["id"]]["count"];
$update[] = "UPDATE foo SET value = '{$response[$dataValue["id"]]["values"][$dataValue["pid"]]}' WHERE pid = {$dataValue["pid"]};";
}
$update = implode("",$update);
$sth = $pdo->prepare($update);
$sth->execute();
?>
Your update query
$query2 = "update foo set value = :multiple";
does not contain any where criteria, each time you call this query it updates the value field's value in all records.
Honestly, I would not really involve php in this update, would do it purely in sql using user defined variables and multi-table join syntax in the update:
update foo inner join (select #i:=0, #previd:=-1) as a
set foo.value=concat(foo.value,'_',#i:=if(id=#previd,#i+1,0),if(#previd:=id,'',''))
The subquery in the inner join initialises #i and #previd user defined variables. The 3rd parameter of the concat function determines the value #i to be concatenated to the value field. The 4th parameter of concat sets the #previd variable and returns an empty string not to affect the overall concatenation. Unfortunately, I do not have access to MySQL to test the query, but it should be a good starting point anyway.
UPDATE
The OP claims in the updated question that the query I provided creates the below resultset:
+------+-----------------------------------------------+
| id | value |
+------+-----------------------------------------------+
| 1 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 1 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 1 | multiple_1_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2 |
| 1 | multiple_1_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3 |
| 2 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 2 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 2 | multiple_1_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2 |
| 2 | multiple_1_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3_3 |
| 3 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
| 3 | multiple_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1 |
| 3 | multiple_1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0 |
+------+-----------------------------------------------+
Tested my solution in sqlfiddle. I had to remove the order by clause, otherwise the query produced the results in line with the requirements stated in the question. See sqlfiddle for details.
The results in the updated question are likely the result of running the query in a loop multiple times. In simple words: you just copy pasted the query into your code and did not remove the loop, even when I pointed out, that this may be the reason of the results you received.

Count same values in different column mysql

I need to count how many times in ripeted the same values in different columns for the same id..
I'll try to clarify with an example:
TABLE:
+-----+-----+-----+-----+-----+
| id | d01 | d02 | d03 | d04 |
+=====+=====+=====+=====+=====+
| 1 | A | A | B | B |
+-----+-----+-----+-----+-----+
| 2 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 3 | B | B | A | A |
+-----+-----+-----+-----+-----+
| 4 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 5 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 6 | B | A | A | A |
+-----+-----+-----+-----+-----+
I need to know how many times the value "B" is repeating for any person (ID)..
Is that possible to do that? RESULTS
+-----+-----+-----+
| id | count B |
+=====+=====+=====+
| 1 | 2 |
+-----+-----+-----+
| 2 | 0 |
+-----+-----+-----+
| 3 | 2 |
+-----+-----+-----+
I was thinking to use the function "SUM" but I have no idea how to display just the single ID.
Thanks in advance, hope the question is clear enough!
If there are only four columns:
SELECT id, (d01 = 'B') + (d02 = 'B') + (d03 = 'B') + (d04 = 'B')
FROM tablename
No there are 31 columns
That's a problem which you can solve in two ways:
Repeat the condition for the other 27 columns :)
Normalize your structure so that each value is dependent on both the id and a numeric value that represents a calendar.
The PHP way
You can also fetch all columns and let PHP solve this for you:
$res = $db->query('SELECT * FROM tablename');
foreach ($res->fetchAll(PDO::FETCH_ASSOC) as $row) {
$id = $row['id'];
unset($row['id']); // don't count the id column
$count = count(array_keys($row, 'B', true));
printf("ID %d: %d\n", $id, $count);
}
Since you seem to be using mysql_*:
// SHOW COLUMNS returns all the columns and constrains of the defined table
// We only need the column names so we will be later calling it by 'Field'
$sql = mysql_query("SHOW COLUMNS FROM table"); //your table name here
$val_to_count = 'B'; //value to count here
$id = 1; //id to search for
$new_sql = 'SELECT id, ';
// In this loop we will construct our SELECT query using the columns returned
// from the above query
while($row=mysql_fetch_array($sql)){
if($row['Field']!='id'){
$new_sql .= ' ('.$row['Field'].' = "'.$val_to_count.'") + ';
}
}
//Removing the last "+ " produced in the select query
$new_sql = rtrim($new_sql,"+ ");
$new_sql .= ' as count FROM table WHERE id = '.$id; //table name here again
// so $new_sql now has an output like:
// SELECT ID, (d01 = 'B') + (d02 = 'B') ... WHERE id = 1
$sql2 = mysql_query($new_sql);
//executing the constructed query with the output below
while($row2=mysql_fetch_array($sql2)){
echo 'ID - '.$row2['id']."<br>";
echo 'Count - '.$row2['count']."<br>";
}
Note:
mysql_* is deprecated, please consider to migrate to mysqli_*

php retrieve multiple data from mysql

I insert multiple id from my checkbox to MySQL database using php post form. In example I insert id (checkbox value table test) to mysql. Now I need a function to retrieve data from MySQL and print to my page with my example output (print horizontal list name of table test where data = userid)
My checkbox value (table name is test):
id | name
----+-------
1 | test1
2 | test2
3 | test3
4 | test4
5 | test5
6 | test6
7 | test7
9 | test9
MySQL data insert (name of table usertest):
id | data | userid
----+---------+--------
1 | 1:4:6:9 | 2
2 | 1:2:3:4 | 5
3 | 1:2 | 7
Example outout :( print horizontal list name of table test where data = userid )
user id 2 choise : test1 - test4 - test6 - test9
Thanks
Assuming your usertest table has only the three columns listed in your example you should replace it with the following -
CREATE TABLE usertest (
data INTEGER NOT NULL,
userid INTEGER NOT NULL,
PRIMARY KEY (data, userid)
);
Then your data will look like -
+------+--------+
| data | userid |
+------+--------+
| 1 | 2 |
| 4 | 2 |
| 6 | 2 |
| 9 | 2 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 4 | 5 |
| 1 | 7 |
| 2 | 7 |
+------+--------+
Querying this data then becomes trivial -
SELECT usertest.userid, GROUP_CONCAT(test.name SEPARATOR ' - ')
FROM usertest
INNER JOIN test
ON usertest.data = test.id
GROUP BY usertest.userid
You can read more about GROUP_CONCAT here
You could use a PHP solution and store the possible checkbox values in an array indexed by their ids. Something like -
<?php
$db = new PDO('mysql:dbname=test;host=127.0.0.1', 'user', 'pass');
$sql = 'SELECT id, name FROM test';
$stmt = $db->prepare($sql);
$stmt->execute();
$array = array();
while ($row = $stmt->fetchObject()) {
$array[$row->id] = $row->name;
}
$sql = 'SELECT userid, data FROM usertest';
$stmt = $db->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetchObject()) {
$data = explode(':', $row->data);
foreach($data as $key => $val) {
$data[$key] = $array[$val];
}
print "user id {$row->userid} choise : " . implode(' - ', $data) . "<br/>\n";
}

Categories