This seems to be a simple problem, but after a while of searching I can't figure out the answer.
I currently have a MySQL table in my local database used by a webapp, and them same table on a database in a remote server. Right now, I'm using the CREATE TABLE IF NOT EXISTS command through PHP to create the table on the databases:
CREATE TABLE IF NOT EXISTS users (
`id` int(10) NOT NULL AUTO_INCREMENT,
`username` varchar(18) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
However, let's say I make a modification to the local database, adding a collumn, for example. It would be really annoying to have to go and change the remote database every time I change the local one. Is there an easier way to run code to create a table if it doesn't exist, and if it does exist, make sure it's structure matches that of the create table structure?
Here's an example, to make what I'm trying to convey a little clearer. Let's say on the local database I have a users table, and I decide that in my webapp I want to have another collumn, password. So I go to the local database and add a password collumn. Is there PHP/MySQL code I can run to check if the users table exists, and if it does, make sure it has a password collumn, and if not, add it?
What you are actually looking for are Migrations, e.g. you are looking for a Schema Management Tool that lets you manage your Database structure in versioned code diffs.
For instance, for your described scenario you would first create a script to create the table, e.g. 001_create_user_table.sql. Then you'd use the schema manager to connect and deploy these changes to your databases.
When you want to change or add something, you just write another script, for instance, 002_Add_Password_Column_To_User_Table.sql. Fill in just the code to do that change. Then run the schema manager again.
Typically, you tell the Schema Manager to go through all existing migrations files. On each run, the Schema manager will update a changelog table in the database, so when you run it, it will know which of your scripts it should apply.
The good thing is, you can add these migrations to your regular VCS, so you will always know which database schema you had at which version of your application. And you will have a proper changelog for them.
To directly answer your question you can create temporary procedures to detect field existence like using a query like this:
SHOW COLUMNS FROM table_name LIKE 'column_name';
However in the real world, database changes are general rolled into three scripts. A create script and two deltas one up and one down. Then the database is versioned so that you know at what state the database is in at any given time.
To specifically check for a password column you can use DESCRIBE:
$colExists = false;
$res = mysql_query('DESCRIBE `users`');
while ($row = mysql_fetch_assoc($res)) {
if ($row['Field'] == 'password') {
$colExists = true;
break;
}
}
if (!$colExists) {
// create column
}
However, you should check into replication or some other automated tool to see if they would be a better solution for you.
Follow these steps (you can easily implement this in PHP, I assumed that the name of the table is Foo)
1.) Run the following code:
desc Foo
2.) Based on the result of the first step you can make your create table command (and you should)
3.) Store your data from the existing table which will be replaced in a variable (Optional, you only need this if you can potentially use data from the old table)
4.) Modify the extracted rows from step 3.) so they will be compatible with your new definition (Optional, you only need this if you can potentially use data from the old table)
5.) Get the rows from your new Foo table
6.) Merge the results got in steps 4.) an 5.) (Optional, you only need this if you can potentially use data from the old table)
7.) Run a drop table for the old table
8.) Generate a replace into command to insert all your rows into the newly created Foo table (you can read more about this here)
After these steps, as a result, you will have the new version of the table. If your tables are too large, you can do a CREATE TABLE IF NOT EXISTS command and if that was not successful, run the alter command.
Also, you can make a library to do these steps and will use that in the future instead of solving the same problem several times.
EDIT:
You can connect the database using this function: mysql-connect (documentation here)
You can run a query using this function: mysql-query (documentation here)
Based on the first step you will get the field names (let's assume you store it in a variable called $bar) and you can use your result to generate your select command (connecting to the database where you have important data. It may be both):
$field_list = "1";
foreach ($bar as $key => $value)
$field_list.= ",".$bar[$key];
mysql_connect(/*connection data*/);
mysql_query("select ".$field_list." from Foo");
You can use your new resource to build up an insert command to insert all your important data after deletion recreation (about resources read more here, about how you can generate your insert you can read here, but I suggest that you should use replace into instead of insert which works like the insert, except that it replaces the row if it already exists, it's better here than an insert, read more here)
So, use mysql_connect and mysql_query, and the resource returned by the mysql_query function can be used for replace into later (I've linked now the URL's for everything you need, so I'm pretty sure you'll solve the problem.), apologies for being not specific enough before.
Related
I am new with PHP development and just wondering if theres a existing function on PHP than duplicate the copy command on phpmyadmin, i know that the query sequence is below, but this is like a long query/code since the table has alot of columns. i mean if phpmyadmin has this feature maybe its calling a build in function?
SELECT * FROM table where id = X
INSERT INTO table (XXX)VALUES(XXX)
Where the information is based from the SELECT query
Note: The id is primary and auto increment.
Here is the copy command on phpmyadmin
i mean if phpmyadmin has this feature maybe its calling a build in function?
There is no built-in functionality in MySQL to duplicate a row other than an INSERT statement of the form: INSERT INTO tableName ( columns-specification ) SELECT columns-specification FROM tableName WHERE primaryKeyColumns = primaryKeyValue.
The problem is you need to know the names of the columns beforehand, you also need to exclude auto_increment columns, as well as primary-key columns, and know how to come up with "smart defaults" for non-auto_increment primary key columns, especially composite keys. You'll also need to consider if any triggers should be executed too - and how to handle any constraints and indexes that may be designed to prevent duplicate values that a "copy" operation might introduce.
You can still do it in PHP, or even pure-MySQL (inside a sproc, using Dynamic SQL) but you'll need to query information_schema to get metadata about your database - which may be more trouble than it's worth.
I`m creating a simple data mapping system with PHP, PDO and Mysql.
One of its premises is to map arrays to entities by creating tertiary tables (not sure if the name is correct).
So, when I map an Array, I create the table with a works-for-all statement that uses the class name and method name passed, something like this:
"create table if not exists ".$tablename." (id_".$firstName." int unsigned not null, ".$secondName." ".$type.", constraint fk_".$tablename." foreign key (id_".$firstName.") references ".$firstName."(id) ".$secondReference.");"
The code is not the problem here.
What I wanted to know is if its a bad idea to TRY to create a table (if not exists) in every iteration (it does only create it for real in the first iteration of each element).
EDIT (explaining): As stated, creating inumerous tables is not the worry (wont happen), for this process is automated according to the classes (models) I`m using. The worry is if it is too costy memory and trafic-wise to check if the table exists at every iteration (this way for each item I would access the database twice, once for checking if the table exists and then again for inserting the new element into the table).
Another option would be to check if the table exists trough a select statement first, but it doesn`t seem much better.
One important information is that these methods used for mapping will olny be accessed through the objects DAO referencing each entity.
Edit: The link for the GitHub with the project is https://github.com/Sirsirious/SPDMap
to me it doesn't sound ideal to create a table each time. Might be better to reuse the same table (with an additional column as identifier between your current 'tables'
if you do create the table, don't see anything wrong with create table if not exist. this is a safe and good programming
I'd also consider using temp tables for this thing. if you create the table each time, it sounds like they are one-time usage as well. so if you don't need the data forever, temp can be a good way to go
At our company we have a business solution which includes CMS, CRM and several other systems.
These are installed in several domains, for each of our clients.
The systems are still in development, so new tables and fields are added to the database.
Each time we want to release a new version to our clients, i have to go through their database and insert the new fields and tables manually.
Is there a way that this could be done automatically(a script maybe that detects the new fields and tables and inserts them?)
We are using php and mysql.
We would like to avoid backing up the clients data, dropping the database tables, running the sql query to insert all the database tables(including the new ones) and then re-inserting the customers data. Is this possible?
Toad for MySQL
DB Extract, Compare-and-Search Utility — Lets you compare two MySQL databases, view the differences, and create the script to update the target.
What you are looking for is
ALTER TABLE 'xyz' ADD 'new_colum' INT(10) DEFAULT '0' NOT NULL;
or if you want to get rid of a colum
ALTER TABLE 'xyz' DROP 'new_colum';
Put all table edits into an update.php file and the either call and delete it once manually or try to select "new_colum" once and update the database when it's not present.
OR what I do: "I have a settingsfield "software version" and use this as a trigger to update my tables.
But since you have to install the new scripts anyways you can just call it manually.
So basically what I am trying to do is when a user of my site creates a new account on our register page, I'd like the primary key from the newly created row on the User table (basic info table, email, password, etc.) to be inserted into a new row on the Profile table (more descriptive info, about me, display name, etc.)
I'd like to do this in PHP and any help would be appreciated.
if you are using mysqli look at:
http://www.php.net/manual/en/mysqli.insert-id.php
Get the id after your first insert and then use this in your next insert.
If doing it "in php" isn't really a requirement, then you can use MySQL's built in Trigger mechanism to do this update.
Triggers cause something to happen AFTER or BEFORE an event(INSERT, UPDATE,DELETE)
So your trigger would be:
CREATE TRIGGER thistrigger AFTER INSERT
ON User FOR EACH ROW
UPDATE PROFILE SET "whatever"
On Triggers: http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
I think there isn't a really elegant way in MySQL, basically because INSERT doesn't return anything. PostgreSQL does allow for an INSERT ... RETURNING clause, but that's an extension.
That said, if you're using the mysql_* functions in PHP, you can use mysql_insert_id, which might suffice for your needs (i.e. if your primary key is an AUTO INCREMENT integer).
If you are using a mysql database, you could alternatively do another query call from php with the following query:
"SELECT LAST_INSERT_ID();"
More info about it here: http://www.jpgtutorials.com/mysql-last_insert_id-function
It is connection specific. Concurrent inserts from different connections won't affect the current connection.
How to reset the database after 3 hrs & make it behave as a new database through php script
Possibly the easiest way would be to have a cron job that executes every three hours and calls mysql with "clean" database set up. The crontab set up would be something along the lines of:
* */03 * * * mysql -u XXX -pXXX < clean_database.sql
However, the "clean_database.sql" file would need to use "DROP TABLE IF EXISTS ..." for each of the tables you want to reset. That said, you can simply use mysqldump with a "known good" version of the database to create this file. (You'll need to add a "use <database name>;" statement at the top that said.)
The easiest way is to drop the database and recreate it using your create scripts. If you don't have create scripts you can get them by making a dump of your database.
To delete the data in each table without dropping the tables you can use the TRUNCATE TABLE tablename command on each table.
If you don't have permission to use TRUNCATE you can use DELETE FROM tablename without a WHERE clause.
Note that if you have foreign key constraints you may have to run the statements in a specific order to avoid violating these constraints.
To get a list of all tables you can use SHOW TABLES.
steps to do:
connect to database server
select database
mysql_query("SHOW TABLES");
read in array or object
foreach($tables as $tableName) of the item mysql_query("TRUNCATE TABLE $tableName")
I hope the principle is clean to you ;-)
mysql_query('DROP DATABASE yourdatabase');
mysql_query('CREATE DATABASE yourdatabase');
mysql_query('CREATE TABLE yourdatabase.sometable ...'); // etc.
This will drop the database, and create it anew. You can then use the CREATE TABLE syntax to recreate the tables - note that as this script has significant powers, you should consider creating a special mySQL user for it, one that's not used during normal operations.