Here what I does
- extract my serialize array from databse
- deserialize it
- change the value
- after changing I serialize it
- then write it back to MYSQL database table.
But Im having trouble writing it back to MYSQL database table
$myarray = Array
(
[dogname] => Array
(
[0] => white
[1] => zeon
[2] => imao
)
[visit] => Array
(
[0] => once
[1] => twice
[2] => twice
)
}
I save it database with this way into my table serialize($myarray)
now I extract it and unserialize
$unserializearray = unserialize($myserialarray);
then search for array value to change and back to table
$keys = array_keys($unserializearray['dogname'], 'imao', true);
foreach($keys as $key)
{
// find dogname imao and change its visit to once
$unserializearray['visit'][$key] = "once";
$update = serialize($unserializearray);
//save the update
mysql_query("UPDATE dogdetails SET checkup = '$update'
WHERE dogid = '1'");
}
but it dont save right into mysql do I miss something in code?
First of all this can't work, if something in your array has a single quote in it, so you need to do
$update=mysql_real_escap_string(serialize($unserializearray),$dbhandle);
or friends.
More importantly, your database design seem heavily flawed to me: As has been said many, many times here, you should not store more than one value in a field, if you want to access them seperately. In your case, you store three dogs with their vists, but you want to access them seperately - this is what your code does.
As Eugen said, there are many things wrong with your code.
Except all that, does this code works any better:
$unserializearray = unserialize($myserialarray);
then search for array value to change and back to table
$keys = array_keys($unserializearray['dogname'], 'imao', true);
foreach($keys as $key)
{
// find dogname imao and change its visit to once
$unserializearray['visit'][$key] = "once";
}
$update = mysql_real_escap_string(serialize($unserializearray));
//save the update
mysql_query("UPDATE dogdetails SET checkup = '$update' WHERE dogid = '1'");
Related
In PHP I have a simple array called $allFiles like:
Array
(
[0] => test1.csv
[1] => test2.csv
[2] => test3.csv
)
In MySQL I have a table that has values like:
| ID | PROCESSED |
| 0 | test2.csv |
What is the easiest way (Using PDO as a connection method) to compare $allFiles to the table and return a new array $newFiles that contains:
Array
(
[0] => test1.csv
[1] => test3.csv
)
(these are the files that are not represented in the table in MySQL)
I've been through the manual but cannot seem to find anything that would relate exactly to this, I might have missed something though. Any input would be greatly appreciated, thanks!
There is no ready-made function to do this. Most of the time, you'll find that there is no out-of-the-box solution to your problem. You'll have to write the code yourself, which isn't too hard: query the DB getting all of the file names, create an array with the results, then get the diff between the array you have, and the query results.
A basic example would be:
$stmt = $pdo->prepare('SELECT PROCESSED FROM db.table WHERE PROCESSED IN (?,?,?)');
$stmt->execute($allFiles);
$existing = array();
while($row = $stmt->fetch(PDO::FETCH_OBJ))
$existing[] = $row->PROCESSED;//construct array containing existing values
$notFound = array_diff($allFiles, $existing);
var_dump($notFound);
You could make the query a tad more dynamic, by using the length of the $allFiles array, and add ? placeholders accordingly:
$allFiles = array_filter(array_unique($allFiles));//clean array
$placeholders = array_fill(0, count($allFiles), '?');
$stmt = $pdo->prepare(
'SELECT PROCESSED FROM db.table WHERE PROCESSED IN ('.implode(',', $placeholders).')'
);
//alternative:
$stmt = $pdo->prepare(
'SELECT PROCESSED FROM db.table WHERE PROCESSED IN ('.
substr(
str_repeat('?,',count($allFiles)),//repeat ?, as many times as there are values
0,-1//remove trailing ","
).')'
);
$stmt->execute(array_values($allFiles));//better safe than sorry
//rest is the same as before
That allows you to process any length of array.
PDO returns an array of values from your table. You can check if your results are already in the db array. You can check on array key, if your results are already in the PDO array, skip this result. If your result isn't in the PDO array build a new array with that value or values.
Note: PDO returns an nummeric and text key for one record. When you check if key exist you have to check if your key is a nummeric key. If nummeric, skip that one.
Just like the guys in the comments has said, there is no PDO function that does this outright. You'll have to gather your results first, put them in an array and use array_diff().
Rough example:
$allFiles = ['test1.csv', 'test2.csv', 'test3.csv'];
$con = new PDO('mysql:host=localhost;dbname=DATABASE', 'username', 'password');
$query = $con->query('SELECT PROCESSED FROM table_name');
$db_results = [];
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$db_results[] = $row['PROCESSED'];
}
$results = array_diff($allFiles, $db_results);
I am trying to select a certain numerical value that is separated by comma. The values are from a mysql db. I try to use explode the column but am not sure how to catch a certain value.
Any help would be appreciated.
Code
$query = mysql_query("SELECT id_array FROM values WHERE id='$id'");
while($result = mysql_fetch_assoc($query))
{
$get_id = $result['id_array'];
}
$exact = explode(",",$get_id);
Assuming you're storing a comma-separated list of values in column id_array, i.e.
12,17,44,13
After you've exploded the result you've got an array of the form
$exact is an array:
(
[0] => '12'
[1] => '17'
[2] => '44'
[3] => '13'
)
Now you want to know if 17 is an element of this array. Right? You can do it with in_array()
$check = in_array(17, $exact); // true, if found as in my example.
// Please note, that it's important not to search in strict mode.
// Test with 100, not in list
$check = in_array(100, $exact) // returns false
Maybe I misunderstood completely your problem. In this case please state with example data what your problem really is. What you've tried and where you got stuck.
PS: I wouldn't recommend storing comma separated lists in MySQL and it would be a great idea to drop the use of the mysql_* functions because they're deprecated. Use mysqli or PDO instead.
*MySQL will be upgraded later.
Preface: Authors can register in two languages and, for various additional reasons, that meant 2 databases. We realize that the setup appears odd in the use of multiple databases but it is more this abbreviated explanation that makes it seem so. So please ignore that oddity.
Situation:
My first query produces a recordset of authors who have cancelled their subscription. It finds them in the first database.
require_once('ConnString/FirstAuth.php');
mysql_select_db($xxxxx, $xxxxxx);
$query_Recordset1 = "SELECT auth_email FROM Authors WHERE Cancel = 'Cancel'";
$Recordset1 = mysql_query($query_Recordset1, $xxxxxx) or die(mysql_error());
$row_Recordset1 = mysql_fetch_assoc($Recordset1);
In the second db where they are also listed, (table and column names are identical) I want to update them because they cancelled. To select their records for updating, I want to take the first recordset, put it into an array, swap out the connStrings, then search using that array.
These also work.
$results = array();
do {
results[] = $row_Recordset1;
} while ($row_Recordset1 = mysql_fetch_assoc($Recordset1));
print_r($results);
gives me an array. Array ( [0] => Array ( [auth_email] => renault#autxxx.com ) [1] => Array ( [auth_email] => rinaldi#autxxx.com ) [2] => Array ( [auth_email] => hemingway#autxxx.com )) ...so I know it is finding the first set of data.
Here's the problem: The query of the second database looks for the author by auth_email if it is 'IN' the $results array, but it is not finding the authors in the 2nd database as I expected. Please note the different connString
require_once('ConnString/SecondAuth.php');
mysql_select_db($xxxxx, $xxxxxx);
$query_Recordset2 = "SELECT auth_email FROM Authors WHERE auth_email IN('$results')";
$Recordset2 = mysql_query($query_Recordset2, $xxxxxx) or die(mysql_error());
$row_Recordset2 = mysql_fetch_assoc($Recordset2);
The var_dump is 0 but I know that there are two records in there that should be found.
I've tried various combinations of IN like {$results}, but when I got to "'$results'", it was time to ask for help. I've checked all the available posts and none resolve my problem though I am now more familiar with the wild goose population.
I thought that since I swapped out the connection string, maybe $result was made null so I re-set it to the original connString and it still didn't find auth_email in $results in the same database where it certainly should have done.
Further, I've swapped out connStrings before with positive results, so... hmmm...
My goal, when working, is to echo the Recordset2 into a form with a do/while loop that will permit me to update their record in the 2nd db. Since the var_dump is 0, obviously this below isn't giving me a list of authors in the second table whose email addresses appear in the $results array, but I include it as example of what I want use to start the form in the page.
do {
$row_Recordset2['auth_email_addr '];
} while($row_Recordset2 = mysql_fetch_assoc($Recordset2));
As always, any pointer you can give are appreciated and correct answers are Accepted.
If you have a db user that has access to both databases and tables, just use a cross database query to do the update
UPDATE
mydb.Authors,
mydb2.Authors
SET
mydb.Authors.somefield = 'somevalue'
WHERE
mydb.Authors.auth_email = mydb2.Authors.auth_email AND
mydb2.Authors.Cancel= 'Cancel'
The IN clause excepts variables formated like this IN(var1,var2,var3)
You should use function to create a string, containing variables from this array.
//the simplest way to go
$string = '';
foreach($results as $r){
foreach($r as $r){
$string .= $r.",";
}
}
$string = substr($string,0,-1); //remove the ',' from the end of string
Its not tested, and obviously not the best way to go, but to show you the idea of your problem and how to handle it is this code quite relevant.
Now use $string instead of $results in query
I have an array with 30000 plus entries that need to go into a MySQL table.
What is the best practice? From here? Lets say [0], [1] and [2] in the database would be 'title', 'type' and 'customer'
Is it add key names matching the column names in the table and call som "magic" function? Or build the query manually...
Array
(
[0] => Array
(
[0] => 2140395946
[1] => 1SAP
[2] => 0041451463
)
[1] => Array
(
[0] => 2140411607
[1] => 2SAP
[2] => 0041411940
)
[2] => Array
(
[0] => 2140706194
[1] => 4SAP
[2] => 0041411943
)
etc. etc.
UPDATE - based on answers
Thanks for the answers.
The solution would normally be to manually create the SQL-string and all rows can be inserted as one:
INSERT INTO `tx_opengate_table` (`machine` ,`customer` ,`type`)
VALUES
('m123', 'dfkj45', 'A'),
('m137', 'kfkj49', 'A'), "repeat this line for each entry in the array"
... ... ...
('m654321', '34dgf456', 'C4') "end with out comma, or remove last comma"
;
Special for TYPO3
I happen to do this in the CMS TYPO3 and just came across a new function added not that long ago:
//Insert new rows
$table = 'tx_opengate_stuff';
$fields = array('machine','type','customer');
$lines = "array as given above"
$GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows($table,$fields,$lines);
I would say just build it yourself. You can set it up like this:
$query = "INSERT INTO x (a,b,c) VALUES ";
foreach ($arr as $item) {
$query .= "('".$item[0]."','".$item[1]."','".$item[2]."'),";
}
$query = rtrim($query,",");//remove the extra comma
//execute query
Don't forget to escape quotes if it's necessary.
Also, be careful that there's not too much data being sent at once. You may have to execute it in chunks instead of all at once.
Magic function? I'm guessing you mean some sort of DB abstraction layer? IMHO that would just double your work.
Just build the query manually looping through array[] INSERT'ing values as you go.
$statement = "INSERT INTO table (title, type, customer) VALUES ";
foreach( $data as $row) {
$statement .= ' ("' . implode($row, '","') . '")';
}
UPDATE: Changed explode to implode (I always get those confused).
You will have to build the query manually if you want the best performance during this operation. If you would iteratively add everything using PDO or some abstarction layer, you will have 30000+ insert queries.
Use foreach to iterate over the arraay, build one nested INSERT query that does all the work at once, and just send it to the server.
I am writing my own PDO wrapper to make my life easier and a fair amount safer.
A standard query looks like:
$user = $db->select('users')
->eq('twitter_id', $twitter_id)
->limit(1)
->prepare()
->exec();
Generates this query:
SELECT * FROM users WHERE twitter_id = :twitter_id LIMIT 1
This works perfectly fine as I, currently, want it. Where I am running into a problem is when I have a query to return multiple rows.
My apps stores some dynamic settings that I want to grab and use in one pass and I can do that by running a query like:
$share_datas = $db->select('settings', 'setting, value')
->prepare()
->exec();
Which generates:
SELECT setting, value FROM settings
Which returns:
Array
(
[0] => Array
(
[setting] => since_id
[value] => 17124357332
)
[1] => Array
(
[setting] => last_dm
[value] => 1271237111
)
)
The function prepare() puts the pieces together for the query and the function exec() binds the params and returns the array.
function exec()
{
// echo 'vars: <pre>'.print_r($this->sql_vars, true).'</pre>';
$stmt = $this->dbh->prepare($this->sql_last_query);
foreach($this->sql_vars as $key => $val)
{
if('date_time' === $key) continue;
$bind = $stmt->bindValue($key, $val);
}
$stmt->execute();
$this->sql_vars = array();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
Now to the question: Is there a way that I can change exec() or the query itself so that it can return an array that returns like below and avoids any additional loops?
Array
(
[since_id] => 17124357332
[last_dm] => 1271237111
)
No problem with some simple array functions.
$in = $db->exec();
$out = array();
foreach( $in as $row )
$out[ $row['setting'] ] = $row['value'];
If you need a more general function, you'll have to describe the transformation clearer.
The answer is likely going to be either:
Creating multiple versions of your exec method with different return behavior, or
Having exec simply perform the execution and store the statement handle, then have fetching the data be a separate method.
I've found the following convenience methods handy, in addition to your current array of hashes:
Query "one": The first column in the first row as a scalar (for things like SELECT COUNT(*))
Query "list": The first column of all rows as an indexed array (for things like SELECT id FROM ...))
Query "pairs": The first two columns of all rows as a hash (for your current problem)
Query "insert id": The last generated row id as a scalar (autoincrement in MySQL, sequence in Postgres, etc)
These are all occasionally convenient things that PDO (and most other database adapters) simply don't have built-in flags to handle.