In a development database, I have phpMyAdmin Tracking enabled on all tables. It logs all the changes I make to the tables' structures (in this case I'm not interested in data tracking.) So far so good.
What I want to do then is to take out a report, for ALL tracked tables, with the changes made from a specific version (or a date would even work,) so that I can run the resulting SQL on my production database, when upgrading to new versions, and make sure that the databases are identical, without the worry of the errors that come with manual handling of this.
However, there is no function that I can find that generates such a report. All the tracking reports are for individual tables, and if I have to click through all tables (20+) it takes away the benefit of this function. All tables don't change, but I don't want to keep track of what's changed, that's what I want phpMyAdmin to do for me.
I have tried to make my own query against the pma_tracking table where the changes are stored, and had partial success. The problem is that all changes for one version are stored as one BLOB, and with each new version a DROP TABLE / CREATE TABLE statement is made, and I can't drop tables on the production db since there is data there (I'm not recreating the database every time, only adding incremental changes). I just want to upgrade the structure, and the only time I want CREATE TABLE statements is when I actually create a new table in the database. So I thought I could filter those out with SQL, but then it's stored as a blog, and then I would have to parse and mess with the blob text which seems overly complicated.
So, as a summary, this is what I'm looking for:
An automated tracking system/workflow that logs all structure updates, and can create incremental SQL reports for the whole database from a version or point in time.
I'd prefer to not use any additional third party apps (I'd like to use phpMyAdmin or MySQL only), if possible
Also, I would love comments on the workflow, if someone has ideas of a better one. Any help appreciated.
The algorithm for parsing the BLOB field of the "pma_tracking" table is located in the getTrackedData method of the PMA_Tracker class, in the libraries/Tracker.class.php source file.
Starting from that code, I've written a simple PHP script to extract all the data definition statements (except the "DROP TABLE" statements) from the "pma_tracking" table.
For example, suppose that you want to get the list of all the changes of all the tables of the "test" database since version "1":
<?php
$link = mysqli_init();
// Adjust hostname, username, password and db name before use!
$db = mysqli_real_connect($link, "localhost", "myuser", "mypass", "phpmyadmin")
or die(mysqli_connect_error());
// Adjust also target db name and tracking version
$db_name = "test";
$version = "1";
$sql = "SELECT schema_sql FROM pma_tracking
WHERE db_name='{$db_name}' AND version>='{$version}'
ORDER BY version,date_created";
$result = mysqli_query($link, $sql) or die(mysqli_error($link));
while ($myrow = mysqli_fetch_assoc($result)) {
$log_schema_entries = explode('# log ', $myrow['schema_sql']);
foreach ($log_schema_entries as $log_entry) {
if (trim($log_entry) != '') {
$statement = trim(strstr($log_entry, "\n"));
if (substr($statement, 0, 11) != "DROP TABLE ") {
echo "{$statement}\n";
}
}
}
}
?>
By redirecting the script output on a file, you'll obtain a SQL commands file with (almost) all the statements needed to replicate the schema changes on the target (eg. production) database; this file must be executed by specifying the "-f" (force) MySQL option:
-f, --force Continue even if we get an SQL error.
By doing so, MySQL will ignore all the "Table already exists" error that will be thrown each time that a CREATE TABLE statement for an existing table is encountered, thus creating only the tables that still does'nt exist in the target database.
This kind of approach obviously has some drawbacks:
ALL the DROP TABLE commands will be ignored (not only those automatically inserted from phpMyAdmin) so, if you have deleted a table in the source database, that table won't be deleted in the target database.
ALL the script errors will be ignored, so it may not be 100% affordable.
A final word of advice: always do a full backup of your target database before proceeding!
I don't know how you could solve this problem using phpMyAdmin, but there are other tools that might help you achieve the effect your looking for. Liquibase is one of them. I've used it some times in the past and it was pretty good. It takes a little to get the hang of it, but I think it might help you.
I'm not too familiar with SQL tools, so I cannot recommend anything to help you out there, but I can try and help with a custom workflow...
Create a table called structure_log
Create a PHP script called print_stucture.php that prints whatever info you desire to a file on the server, saves the file as a timestamp (this will be your version number), and saves the name in the structure_log table
Create a crontab that runs print_structure.php however often you desire
Create a PHP script called delete_dups.php that grabs the last two records from your structure_log table, compares those two files, and if they are the same (representing no change to structures), deletes the one with the latest timestamp (filename) and removes that record from the structure_log table
Create a crontab that runs delete_dups.php half as often as the one that runs print_structure.php
This will make a versioning folder on your server. You can manually run the print_structure.php script whenever you desire and compare it against the latest version log you have in your server folder to see if your database you just ran it on, is the same as the last time the version check was ran.
I've had some success with MySQL Workbench:
Import (reverse engineer) your dev database into workbench. You can do this by either exporting your schema to an SQL file and loading it into workbench, or workbench will get the schema directly from the server.
Next, generate your diff file with the "Synchronise model" option. You select the production database, then which tables to sync, and workbench generates an SQL file you can run to sync both models.
A word of caution: the first time, there will likely be quite a few apparently uneeded changes while the DB is updated to workbench "style". For subsequent updates, the tool is rather reliable, though I would never let an automated tool have free range over my production DB ;-)
Always check the SQL file for errors, in some cases, dropping a column then adding another of the same name but different type will generate an alter column which will fail.
I don't have anything that creates an incremental diff between two databases but here's the script I use to compare two MySQL databases:
<?php
//------------------------------------------------------------------------------
// Define the variables we'll be using.
//------------------------------------------------------------------------------
$db1_con = NULL;
$db1_constraints = array();
$db1_dbname = 'db1';
$db1_host = 'localhost';
$db1_password = 'password1';
$db1_tables = array();
$db1_username = 'username1';
$db2_con = NULL;
$db2_constraints = array();
$db2_dbname = 'db2';
$db2_host = '123.123.123.123';
$db2_password = 'password2';
$db2_tables = array();
$db2_username = 'username2';
//------------------------------------------------------------------------------
// Connect to the databases.
//------------------------------------------------------------------------------
try{
$db1_con = new PDO("mysql:host=$db1_host;dbname=information_schema", $db1_username, $db1_password);
$db1_con->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE); // Try to use the driver's native prepared statements.
$db1_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Let's use exceptions so we can try/catch errors.
}catch(PDOException $e){
echo "<p>Connection failed for $db1_host: " . $e->getMessage() . '</p>';
exit;
}
try{
$db2_con = new PDO("mysql:host=$db2_host;dbname=information_schema", $db2_username, $db2_password);
$db2_con->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE); // Try to use the driver's native prepared statements.
$db2_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Let's use exceptions so we can try/catch errors.
}catch(PDOException $e){
echo "<p>Connection failed for $db2_host: " . $e->getMessage() . '</p>';
exit;
}
if (NULL !== $db1_con && NULL !== $db2_con){
echo "<h2>Column Analysis</h2>";
$sql = 'SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION';
$statement1 = $db1_con->prepare($sql);
$statement1->bindValue(1, $db1_dbname);
$statement2 = $db2_con->prepare($sql);
$statement2->bindValue(1, $db2_dbname);
if (TRUE === $statement1->execute()){
while ($row = $statement1->fetch(PDO::FETCH_ASSOC)){
$db1_tables[$row['TABLE_NAME']][$row['COLUMN_NAME']] = array();
foreach ($row AS $key => $value){
$db1_tables[$row['TABLE_NAME']][$row['COLUMN_NAME']][$key] = $value;
}
}
}
if (TRUE === $statement2->execute()){
while ($row = $statement2->fetch(PDO::FETCH_ASSOC)){
$db2_tables[$row['TABLE_NAME']][$row['COLUMN_NAME']] = array();
foreach ($row AS $key => $value){
$db2_tables[$row['TABLE_NAME']][$row['COLUMN_NAME']][$key] = $value;
}
}
}
foreach ($db1_tables AS $table => $info){
if (!isset($db2_tables[$table])){
echo "<p>Table <strong>$table</strong> does not exist in the SECOND database!</p>";
}else{
foreach ($info AS $column => $data){
if (!isset($db2_tables[$table][$column])){
echo "<p>Column <strong>$column</strong> does not exist in table <strong>$table</strong> in the SECOND database!</p>";
}else{
if (count($data)){
foreach ($data AS $key => $value){
if ($db1_tables[$table][$column][$key] !== $db2_tables[$table][$column][$key]){
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> has differing characteristics for <strong>$key</strong> (". $db1_tables[$table][$column][$key] ." vs. ". $db2_tables[$table][$column][$key] .")</p>";
}
}
}
}
}
}
}
foreach ($db2_tables AS $table => $info){
if (!isset($db1_tables[$table])){
echo "<p>Table <strong>$table</strong> does not exist in the FIRST database!</p>";
}else{
foreach ($info AS $column => $data){
if (!isset($db1_tables[$table][$column])){
echo "<p>Column <strong>$column</strong> does not exist in table <strong>$table</strong> in the FIRST database!</p>";
}else{
if (count($data)){
foreach ($data AS $key => $value){
if ($db2_tables[$table][$column][$key] !== $db1_tables[$table][$column][$key]){
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> has differing characteristics for <strong>$key</strong> (". $db2_tables[$table][$column][$key] ." vs. ". $db1_tables[$table][$column][$key] .")</p>";
}
}
}
}
}
}
}
echo "<h2>Constraint Analysis</h2>";
$sql = 'SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION';
$statement1 = $db1_con->prepare($sql);
$statement1->bindValue(1, $db1_dbname);
$statement2 = $db2_con->prepare($sql);
$statement2->bindValue(1, $db2_dbname);
if (TRUE === $statement1->execute()){
while ($row = $statement1->fetch(PDO::FETCH_ASSOC)){
foreach ($row AS $key => $value){
$db1_constraints[$row['TABLE_NAME']][$row['COLUMN_NAME']][$key] = $value;
}
}
}
if (TRUE === $statement2->execute()){
while ($row = $statement2->fetch(PDO::FETCH_ASSOC)){
foreach ($row AS $key => $value){
$db2_constraints[$row['TABLE_NAME']][$row['COLUMN_NAME']][$key] = $value;
}
}
}
foreach ($db1_constraints AS $table => $info){
foreach ($info AS $column => $data){
if (isset($db2_constraints[$table][$column])){
if (count($data)){
foreach ($data AS $key => $value){
if ('CONSTRAINT_NAME' !== $key && $db1_constraints[$table][$column][$key] !== $db2_constraints[$table][$column][$key]){
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> has differing characteristics for <strong>$key</strong> (". $db1_constraints[$table][$column][$key] ." vs. ". $db2_constraints[$table][$column][$key] .")</p>";
}
}
}
}else{
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> is missing a constraint in the SECOND database!</p>";
}
}
}
foreach ($db2_constraints AS $table => $info){
foreach ($info AS $column => $data){
if (isset($db1_constraints[$table][$column])){
if (count($data)){
foreach ($data AS $key => $value){
if ('CONSTRAINT_NAME' !== $key && $db2_constraints[$table][$column][$key] !== $db1_constraints[$table][$column][$key]){
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> has differing characteristics for <strong>$key</strong> (". $db2_constraints[$table][$column][$key] ." vs. ". $db1_constraints[$table][$column][$key] .")</p>";
}
}
}
}else{
echo "<p>Column <strong>$column</strong> in table <strong>$table</strong> is missing a constraint in the FIRST database!</p>";
}
}
}
}
?>
Edited to add code that shows differences in constraints as well.
Related
So, I have pretty limited knowledge when it comes to mysql. Usually when dealing with content on our site, I'm used to loading it from expressionengine, our cms, which I know fine. But recently I have to update this page that loads its data directly from our database. I took a course on mysql a while back, but I still don't really know how to use it.
The page doesn't need to use too much information, its basically just a list of awards presented to different businesses. I assume the table on the database just has a column for Business name, City, Year, and Type of award won. Stuff like that.
Now accessing the database doesn't seem like it would be too hard, and I feel like I could google around and find what I need. But to get started, I would just like to see the actual table! Why is it so complicated of a procedure to do?
The code on the file that I'm working on was set up like this to access the database:
$user_name = "xxxxxxxxxx";
$password = "xxxxxxxxxx";
$server = "xxxxxxxxxx";
$database = "xxxxxxxxxx";
$conni = new mysqli($server, $user_name, $password, $database);
if (mysqli_connect_errno()) {
printf("<center>
<strong>No connection to database possible!<br />
Please contact us!</strong>
</center>");
exit();
}
I figured out how to view all tables on the database, by doing this:
$result = mysql_query("show tables");
while($table = mysql_fetch_array($result)) {
echo($table[0] . "<BR>");
}
So I know the name of the table I'm dealing with. I found a way to see all the column names:
$query = "select * from my_tablename";
$result = mysql_query($query);
$numcolumn = mysql_num_fields($result);
for ( $i = 0; $i < $numcolumn; $i++ ) {
$columnnames = mysql_field_name($result, $i);
echo $columnnames . "<br>";
}
But I still can't find how to just display the table itself. I might be thinking about this wrong, or not have the full idea, but what I want is a simple way to display the entire table, like with an html table. How can that be done?
You can build the <thead> of a table with the column names you have above, however to display the results in a table format, use the mysql_fetch_row function on the $result of SELECT * FROM my_tablename. To reuse the $result after you've got the field names as in your last block, use mysql_data_seek:
mysql_data_seek($result, 0);
And then you can iterate through your results to get the contents of the table:
while ($row = mysql_fetch_row($result)) {
echo '<tr>';
foreach ($row as $value) {
echo '<td>' . $value . '</td>';
}
echo '</tr>';
}
mysql_fetch_row will get a numerically indexed array with where each value is the column value in MySQL, therefore by running foreach you get the value of each column. Put it inside of a <td>, wrap it all in a <tr> and you have yourself a table!
Just for good measure, you should switch to using mysqli in PHP as the mysql_ functions are deprecated in later versions. To switch over, use the PHP documentation to search for the mysql_ functions you're currently using, there will be a pink message which will direct you to the mysqli equivalents
So here is my scenario...
The bug_tracker table is in one server and task_traker is in another.
I want to show a combined result but can't since there are in two separate databases remotely.
So I am calling the task tracker first and then getting the bug details per iteration.
$task = oci_parse($task_conn, "select * from task_table where ....");
oci_execute($task);
while ($task_row = oci_fetch_array($task, OCI_ASSOC+OCI_RETURN_NULLS)) {
$bug = oci_parse($bug_conn, "select * from bug_table where id = " . $task_row['BUGID'] );
oci_execute($bug);
while ($task_row = oci_fetch_array($task, OCI_ASSOC+OCI_RETURN_NULLS)) {
... //output
}
... //output
}
But this entire process is making it very slow... since there are large number of records and columns.
Is there any way to make it even slightly faster? Note: I don't have access so can't setup oracle db links.
You could improve it using the IN statement:
<?php
$task = oci_parse($task_conn, "select * from task_table where ....");
oci_execute($task);
while ($task_row = oci_fetch_array($task, OCI_ASSOC+OCI_RETURN_NULLS)) {
$bugs[] = $task_row['BUGID'];
$users[] = $task_row['USER'];
$status[] = $task_row['TASK_STATUS'];
}
$bug = oci_parse($bug_conn, "select * from bug_table where id IN (" . implode(',', $bugs) . ");" );
oci_execute($bug);
while ($task_row = oci_fetch_array($task, OCI_ASSOC+OCI_RETURN_NULLS)) {
// ...
}
?>
On a sidenote, why are you not using PDO? I believe using it will already give you a performance boost.
PHP is not meant for this kind of operation, neither should you try to write your own join function.
One proper way of solving this issue is to dump the data from both databases into a local database, and there do the join.
You do not need anything fancy for the local database, an SQLite3 is probably enough.
Just dump the data from each database into a CSV files using a bash script that you put into cron. After the dump, (re)create each table in your SQLite3, and load the CSVs into these tables. After this you can do a join once and push the result into a new table which you then are free to query.
This is what in the datawarehouse world is often referred to as an ETL process, just in this case, very very simplified.
Does anyone have or can point to a good example of creating sqlite in-memory table using php pdo where the table columns formats are gathered directly from a PDO query result?
My use case is that I'd like to use SQLite3 to store multiple resultsets from a number of queries (all the same column order etc) that are returned from a number of different databases. The end goal is to use SQLite to "reduce" the data for finalization.
I understand I could write a custom function for each query result, but my goal is to implement a universal solution, not needing to know the table structure, passing x homogenous resultsets (PDO::FETCH_ASSOC array results for example) and return a temporary SQLite table name to be able to query the UNION of the resultset(s) with SQLite before discarding the data.
It seems like this would be out on the internet somewhere and the SQLite website even alludes to this being a use case, but all my searches point to basic SQLite howtos on creating and querying...thanks in advance!
Since nobody replied, here is a rough effort. This is based on the db handle being mySQL, but it may be possible to ignore types and let sqlite do some magic. If so, see this link:
https://www.sqlite.org/datatype3.html
try{
$link = connectToDB_PDO();
$strSQL="select * from website.customers";
$mySth=$link->prepare($strSQL);
$meta=array();
$mySth->execute();
foreach(range(0, $mySth->columnCount() - 1) as $column_index){
$meta[] = $mySth->getColumnMeta($column_index);
}
$result=$mySth->fetchAll(PDO::FETCH_ASSOC);
// Create new database in memory
$memdb = new PDO('sqlite::memory:');
$memdb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Set errormode to exceptions
$tablename='mytable';
$colnames=array(); // for the insert statement below
$tableSQL="CREATE TABLE $tablename ( ";
foreach($meta as $col){
$colnames[]=$col['name'];
$tableSQL.=" ".$col['name']. " ".$col['native_type']." ";
if(array_key_exists('flags',$col)){
foreach($col['flags'] as $flag){
switch($flag)
{
case 'not_null':
$tableSQL.=" NOT NULL ";
break;
case 'primary_key':
$tableSQL.=" PRIMARY KEY ";
break;
default:
} // end switch
} // end each flag
} // end if flags
$tableSQL.=", ";
} // end each column
$tableSQL=rtrim($tableSQL,", ");
$tableSQL.=")";
$memdb->exec($tableSQL);
$pragmaSQL="PRAGMA table_info($tablename)";
$st2=$memdb->prepare($pragmaSQL);
$st2->execute();
$pragres=$st2->fetchAll(PDO::FETCH_ASSOC);
$insert = "INSERT INTO $tablename (".implode(",",$colnames).") ".
"VALUES (:".implode(",:",$colnames).")";
$stmt = $memdb->prepare($insert);
foreach ($result as $row) {
$parms=array();
for($i=0;$i<count($colnames);$i++){
$parms[':'.$colnames[$i]]=$row[$colnames[$i]]; // Bind parameters to statement variables
}
$stmt->execute($parms);
}
$strSQL="SELECT sum(customers_id) FROM $tablename";
$sth=$memdb->prepare($strSQL);
$sth->execute();
$result2=$sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($result2 as $m) {
echo print_r($m,true);
}
$memdb->exec("DROP TABLE $tablename");
$memdb = null;
} catch(PDOException $e) {
echo $e->getMessage();
error_log($e->getMessage());
}
I'm not sure if this is the best answer, but its a start - anxious to see other's input!
I was wondering if you think this is possible:
Ok so I have a database storing usernames and I would like to echo the admins which are inside a file called admins.php IF they match the usernames inside the database so far I have got:
admins.php;
$admins = array("username","username2","username3");
and
$users="SELECT username from usrsys";
$query_users=mysql_query($users);
while loop here.
The while loop should hopefully echo the users which matches the admins.php file. I assume I should use something like (inarray()), but I am really not sure.
You should definitely use IN clause in your SQL to do this. Selecting everything from the table in order to determine in PHP if it contains the user names you're looking for makes no sense and is very wasteful. Can you imagine what would happen if you had a table of 1 million users and you needed to see if two of them were on that list? You would be asking your DBMS to return 1 million rows to PHP so that you can search through each of those names and then determine whether or not any of them are the ones you're looking for. You're asking your DBMS to do a lot of work (send over all the rows in the table), and you're also asking PHP to do a lot of work (store all those rows in memory and compute a match), unnecessarily.
There is a much more efficient and faster solution depending on what you want.
First, if you only need to know that all of those users exist in the table then use SELECT COUNT(username) instead and your database will return a single row with a value for how many rows were found in the table. That way you have an all or nothing approach (if that's what you're looking for). Either there were 3 rows found in the table and 3 elements in the array or there weren't. This also utilizes your table indexes (which you should have properly indexed) and means faster results.
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT COUNT(username) FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
if (false === $result = mysql_fetch_row($query_users)) {
echo "Huston we have a problme! " . mysql_error(); // Basic error handling (DEBUG ONLY)
}
if ($result[0] == count($admins)) {
echo "All admins found! We have {$result[0]} admins in the table... Mission complete. Returning to base, over...";
}
If you actually do want all the data then remove the COUNT from the SQL and you will simply get all the rows for those users (if any are found).
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT username FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
// Loop over the result set
while ($result = mysql_fetch_assoc($query_users)) {
echo "User name found: {$result['username']}\n";
}
However, I really urge you to reconsider using the old ext/mysql API to interface with your MySQL database in PHP since it is deprecated and has been discouraged from use for quite some time. I would really urge you to start using the new alternative APIs such as PDO or MySQLi and see the guide in the manual for help with choosing an API.
In PDO, for example this process would be quite simple with prepared statements and parameterized queries as you don't have to worry about all this escaping.
There's an example in the PDOStatement::Execute page (Example #5) that shows you just how to do use the IN clause that way with prepared statements... You can then reuse this statement in other places in your code and it offers a performance benefit as well as making it harder for you to inadvertently expose yourself to SQL injection vulnerabilities.
// Connect to your database
$pdo = new PDO("mysql:dbname=mydb;host=127.0.0.1", $username, $password);
// List of admins we want to find in the table
$admins = array("username","username2","username3");
// Create the place holders for your paratmers
$place_holders = implode(',', array_fill(0, count($admins), '?'));
// Create the prepared statement
$sth = $dbh->prepare("SELECT username FROM usrsys WHERE username IN ($place_holders)");
// Execute the statement
$sth->execute($admins);
// Iterate over the result set
foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) {
echo "We found the user name: {$row['username']}!\n";
}
Your PHP code even looks so much better with PDO :)
Just include admins.php file and use the next construction in your loop:
while ($row = mysql_fetch_array($users)) {
if (in_array($users[0], $admins))
echo $users[0];
}
Try this:
<?php
# include admins.php file that holds the admins array
include "admins.php";
# join all values in the admins array using "," as a separator (to use them in the sql statement)
$admins = join(",", $admins);
# execute the query
$result = mysql_query("
SELECT username
FROM usrsys
WHERE username IN ($admins)
");
if ($result) {
while ($row = mysql_fetch_array($result)) {
echo $row["username"] . "<br>";
}
}
?>
If your looking for syntax to pull in only the users from your $admins array then you could use something like:
$users="SELECT username FROM usrsys WHERE username IN ('".join("','",$admins)."')";
Where the php function JOIN will print username,username2,username3. Your resulting MySQL statement will look like:
SELECT username FROM usrsys WHERE username IN ('username','username2','username3')
Alternatively, if your looking to iterate through your $query_vars array and separate your admins from non-admins then you could use something like:
<?php
while($row = mysql_fetch_assoc($query_users)){
if(in_array($row['username'],$admins)){
//do admin stuff here
}else{
//do NON-admin stuff here
}
}?>
I have a time dependent script I am working on and used microtime() to find the bottle neck. I determined the time increase is caused by doing a check on 300+ values to see if they exist in a database one at a time at 0.04 seconds a query.
The background of the script is it is a caching script. I need to see if it exists in the DB so I need a true/false (obtained by a rowCount) but i also need a way to relate a false to a value so I can update it. I know using a WHERE tag IN (:ARRAY) would work faster than the individual calls, but I cant think of a way to apply an association of true/false to value in this method.
My current code is below:
//loop through all our values!
//prepare out reusuable statement
$stmt = $db->prepare("SELECT * from cache WHERE value=?");
foreach($values as $tempVal)
{
//find if its in the database
try
{
$stmt->execute(array($tempVal));
$valCount = $stmt->rowCount();
} catch(PDOException $ex) {
echo "PDO error send this to us: " . $ex->getMessage();
}
//update flag
$addToUpdate = 1;
//if its in the database
if($valCount > 0)
{
//get the tag data
$valRes= $stmt->fetch();
//check if cache expired
$addToUpdate = 0;
}
//add to update list
if($addToUpdate)
{
//needs updating
$updateList[] = $tempVal;
//add to not in DB list to minimize queries
if($tagTCount == 0)
{
$notInDB[$tempVal] = $tempVal;
}
}
Any suggestions? I can explain more if anything is not clear.
Thank you,
Nick
So you just issue your query with the complete array, using the IN (?,?,?,?,?...) list:
// abstract, use a PDO wrapper of your choosing
$query = db("SELECT * FROM cache WHERE value IN (??)", $values);
Then iterate over the result list. Only matched $values will return. So build your first list from that:
foreach ($query as $row) {
$updateList[] = $row["value"];
}
To get the list of absent entries, just diff that against your original array:
$notInDB = array_diff($values, $updateList);
You could of course use a second NOT IN query. But doing that differentiation in PHP is simpler.