how to insert data into fields created at run time in mysql? - php

it is possible to create column at run time in mysql table using add column in php.
but how to insert data at run time into the newly created field(s) (i.e.column(s))?
thanks in advance
EDIT:
some said that why i need to create a new column at run time as i know before hand that the column will be necessary. No, columns quite unknown at the beginning may be needed to be created Just take the problem as a programming issue.
PLZ GIVE THE EXPLANATION OF -VE RATING
i donno why my post was rated -ve ly. uff where is the solution to the prob that someone needs to create columns in a mysql table beforehand and the thing is quite unpredictable. Suppose a site admin needs to add column to a membership club table from time to time. Can't this be any real situation? Why is there no explanation of -ve rating , plz?

Oh that,
You know you need to create the address column already. Then what you need to do is do a 2 step registration.
You need to check whether this column is empty when the student logs in. If it is empty then you ask the student to put in their address. When they have typed in the address the just update the column and change it from blank to the address provided by the student. You dont need the dynamic columns as that would be slow and complex operation.
Check database for the address of the student or check if the user is loggin in the first time
If the users address is empty or the user is logging in the first time
Then
Ask the user for their address
If the address is given then
Update the address column with the provided address
Endif
Endif
Done

Yes, you can execute a MySQL command in PHP code to add a column, create a table, alter a table and more.

Use a function that alters your table and which returns true, if the altering was successfull. If you get this, you can use normal UPDATE functions.
But you should never, never, never design your application this way. Think about all the ibformations, that you will get now and in the future. Then design your tables referring to this informations.
In your special case you already know, that you will aks for the address informations, so implement this NOW in your code. user658911 showed you how to do this.
In the future it might be neccessary to add more columns or tables to your system, because the requirements will change. If so, you can realize those changes on your development system, test them with your current database content and after all deploy it to your production system.
Altering a table during runtime should never be an option.

Related

What do you think of this approach for logging changes in mysql and have some kind of audit trail

I've been reading through several topics now and did some research about logging changes to a mysql table. First let me explain my situation:
I've a ticket system with a table: 'ticket'
As of now I've created triggers which will enter a duplicate entry in my table: 'ticket_history' which has "action" "user" and "timestamp" as additional columns. After some weeks and testing I'm somewhat not happy with that build since every change is creating a full copy of my row in the history table. I do understand that disk space is cheap and I should not worry about it but in order to retrieve some kind of log or nice looking history for the user is painful, at least for me. Also with the trigger I've written I get a new row in the history even if there is no change. But this is just a design flaw of my trigger!
Here my trigger:
BEFORE UPDATE ON ticket FOR EACH ROW
BEGIN
INSERT INTO ticket_history
SET
idticket = NEW.idticket,
time_arrival = NEW.time_arrival,
idticket_status = NEW.idticket_status,
tmp_user = NEW.tmp_user,
action = 'update',
timestamp = NOW();
END
My new approach in order to avoid having triggers
After spening some time on this topic I came up with an approach I would like to discuss and implement. But first I would have some questions about that:
My idea is to create a new table:
id sql_fwd sql_bwd keys values user timestamp
-------------------------------------------------------------------------
1 UPDATE... UPDATE... status 5 14 12345678
2 UPDATE... UPDATE... status 4 7 12345678
The flow would look like this in my mind:
At first I would select something or more from the DB:
SELECT keys FROM ticket;
Then I display the data in 2 input fields:
<input name="key" value="value" />
<input type="hidden" name="key" value="value" />
Hit submit and give it to my function:
I would start with a SELECT again: SELECT * FROM ticket;
and make sure that the hidden input field == the value from the latest select. If so I can proceed and know that no other user has changed something in the meanwhile. If the hidden field does not match I bring the user back to the form and display a message.
Next I would build the SQL Queries for the action and also the query to undo those changes.
$sql_fwd = "UPDATE ticket
SET idticket_status = 1
WHERE idticket = '".$c_get['id']."';";
$sql_bwd = "UPDATE ticket
SET idticket_status = 0
WHERE idticket = '".$c_get['id']."';";
Having that I run the UPDATE on ticket and insert a new entry in my new table for logging.
With that I can try to catch possible overwrites while two users are editing the same ticket in the same time and for my history I could simply look up the keys and values and generate some kind of list. Also having the SQL_BWD I simply can undo changes.
My questions to that would be:
Would it be noticeable doing an additional select everytime I want to update something?
Do I lose some benefits I would have with triggers?
Are there any big disadvantages
Are there any functions on my mysql server or with php which already do something like that?
Or is there might be a much easier way to do something like that
Is maybe a slight change to my trigger I've now already enough?
If I understad this right MySQL is only performing an update if the value has changed but the trigger is executed anyways right?
If I'm able to change the trigger, can I still prevent somehow the overwriting of data while 2 users try to edit the ticket the same time on the mysql server or would I do this anyways with PHP?
Thank you for the help already
Another approach...
When a worker starts to make a change...
Store the time and worker_id in the row.
Proceed to do the tasks.
When the worker finishes, fetch the last worker_id that touched the record; if it is himself, all is well. Clear the time and worker_id.
If, on the other hand, another worker slips in, then some resolution is needed. This gets into your concept that some things can proceed in parallel.
Comments could be added to a different table, hence no conflict.
Changing the priority may not be an issue by itself.
Other things may be messier.
It may be better to have another table for the time & worker_ids (& ticket_id). This would allow for flagging that multiple workers are currently touching a single record.
As for History versus Current, I (usually) like to have 2 tables:
History -- blow-by-blow list of what changes were made, when, and by whom. This is table is only INSERTed into.
Current -- the current status of the ticket. This table is mostly UPDATEd.
Also, I prefer to write the History directly from the "database layer" of the app, not via Triggers. This gives me much better control over the details of what goes into each table and when. Plus the 'transactions' are clear. This gives me confidence that I am keeping the two tables in sync:
BEGIN; INSERT INTO History...; UPDATE Current...; COMMIT;
I've answered a similar question before. You'll see some good alternatives in that question.
In your case, I think you're merging several concerns - one is "storing an audit trail", and the other is "managing the case where many clients may want to update a single row".
Firstly, I don't like triggers. They are a side effect of some other action, and for non-trivial cases, they make debugging much harder. A poorly designed trigger or audit table can really slow down your application, and you have to make sure that your trigger logic is coordinated between lots of developers. I realize this is personal preference and bias.
Secondly, in my experience, the requirement is rarely "show the status of this one table over time" - it's nearly always "allow me to see what happened to the system over time", and if that requirement exists at all, it's usually fairly high priority. With a ticketing system, for instance, you probably want the name and email address of the users who created, and changed the ticket status; the name of the category/classification, perhaps the name of the project etc. All of those attributes are likely to be foreign keys on to other tables. And when something does happen that requires audit, the requirement is likely "let me see immediately", not "get a database developer to spend hours trying to piece together the picture from 8 different history tables. In a ticketing system, it's likely a requirement for the ticket detail screen to show this.
If all that is true, then I don't think history tables populated by triggers are a good idea - you have to build all the business logic into two sets of code, one to show the "regular" application, and one to show the "audit trail".
Instead, you might want to build "time" into your data model (that was the point of my answer to the other question).
Since then, a new style of data architecture has come along, known as CQRS. This requires a very different way of looking at application design, but it is explicitly designed for reactive applications; these offer much nicer ways of dealing with the "what happens if someone edits the record while the current user is completing the form" question. Stack Overflow is an example - we can see, whilst typing our comments or answers, whether the question was updated, or other answers or comments are posted. There's a reactive library for PHP.
I do understand that disk space is cheap and I should not worry about it but in order to retrieve some kind of log or nice looking history for the user is painful, at least for me.
A large history table is not necessarily a problem. Huge tables only use disk space, which is cheap. They slow things down only when making queries on them. Fortunately, the history is not something you'd use all the time, most likely it is only used to solve problems or for auditing.
It is useful to partition the history table, for example by month or week. This allows you to simply drop very old records, and more important, since the history of the previous months has already been backed up, your daily backup schedule only needs to backup the current month. This means a huge history table will not slow down your backups.
With that I can try to catch possible overwrites while two users are editing the same ticket in the same time
There is a simple solution:
Add a column "version_number".
When you select with intent to modify, you grab this version_number.
Then, when the user submits new data, you do:
UPDATE ...
SET all modified columns,
version_number=version_number+1
WHERE ticket_id=...
AND version_number = (the value you got)
If someone came in-between and modified it, then they will have incremented the version number, so the WHERE will not find the row. The query will return a row count of 0. Thus you know it was modified. You can then SELECT it, compare the values, and offer conflict resolution options to the user.
You can also add columns like who modified it last, and when, and present this information to the user.
If you want the user who opens the modification page to lock out other users, it can be done too, but this needs a timeout (in case they leave the window open and go home, for example). So this is more complex.
Now, about history:
You don't want to have, say, one large TEXT column called "comments" where everyone enters stuff, because it will need to be copied into the history every time someone adds even a single letter.
It is much better to view it like a forum: each ticket is like a topic, which can have a string of comments (like posts), stored in another table, with the info about who wrote it, when, etc. You can also historize that.
The drawback of using a trigger is that the trigger does not know about the user who is logged in, only the MySQL user. So if you want to record who did what, you will have to add a column with the user_id as I proposed above. You can also use Rick James' solution. Both would work.
Remember though that MySQL triggers don't fire on foreign key cascade deletes... so if the row is deleted in this way, it won't work. In this case doing it in the application is better.

Merging mySQL database with PHP while maintaining field

Background: A group of students including me are creating a website for a merit system for our school. We basically had no experience in html, css, php or sql databases at the start. I will say we've managed decently.
However, we've run into a problem with updating the database. Every week, we need to merge the table for students from a csv, which is updated with classes and all from a department of education system. So there are thousands of students and each of them have certain details that when updated can change but others that need to stay the same. For example, we have the number of merits which needs to stay the same when we update but details such as their year group or classes can change. The thing is, is that this update is done of a csv file which may also have new students that need to be updated to the database and the csv is not in any order. So we are trying to find a solution which allows one field to be the same but allow others to change.
So we've tried LOAD DATA INFILE with a unique key but the problem we found was that while it preserved the merits, it ignored the other details and just added new students.
EDIT: So the students have a class field which contains the classes of the student. When we import, we need to be able to change that but still maintain the merit field which will not be in the csv file. We understand that we could just manually import it but suspect that will take a long time to run.
Our code will be in PHP by the way.
tl;dr
Need to find out how to merge/import databases from csv, changing only specific fields of existing students and also adding new students
Thanks in advance for your help and sorry for the long post. This is my first post so do forgive me if I make any mistakes.
You will need a php script which reads the contents of the file, line by line preferably since it is a CSV. You will then need to use the primary key unique identifier from each CSV line to check whether a record with that primary key value already exists in the database. If a record with that primary key exists in the database, use the UPDATE query to update the merits only. If a record cannot be found with that primary key, use the INSERT statement to add that new record to the database.
NOTE: Bolded bits are steps required, in chronological order.

Create Table Just Once?

I have a few nagging questions about creating tables:
If I use PHP to create a MySQL function to create a table, I know it works the first time (to create a database for usernames and passwords) but what about the following times when the database sees the code to "create table". It seems to ignore it on my virtual server, but I was just wondering if this is wrong. Does it keep trying to create a new table each time? Is it okay to leave that code in?
Another question I have is, let's say I go into PHPMyAdmin and add a column called "role" (to define the user's role). The sign in page will crash since I added a column in PHPMyAdmin, but if add the column using PHP/MySQL it is perfectly fine. Why is that?
CREATE TABLE is executed each time you run the function. It's better to replace the syntax with CREATE TABLE IF NOT EXISTS.
The keywords IF NOT EXISTS prevent an error from occurring if the
table exists.
If you does not add IF NOT EXISTS it will throw the error.
Reference: http://dev.mysql.com/doc/refman/5.7/en/create-table.html
Please post your code in question to help you with second query.
1.) It depends on the purpose of the table.
If you need to create tables dynamically then your code should check each time
if the table exists:
CREATE TABLE IF NOT EXISTS 'yourTable'
However if you create the table only ones, there is no need to check for existence over and over again, so the code to create these table(s) should execute one time only.
2.) You need to update the function that does the insert or read after adding a column via PHPMyAdmin. It's difficult to answer your second question as I don't know what your functions do.
Do not keep your CREATE TABLE ... statements in your PHP code so that they execute every single time on every single page load. It's unnecessary and error prone. The statements are not being ignored, very likely they are run and are producing errors, and you're simply not checking for errors.
Database creation is a deployment step, meaning when you upload your code to your server, that's the one and only time when you create or modify databases. There are entire toolchains available around managing this process; learn something about automated deployment processes and database schema versioning at some point.
No idea without seeing your code and the exact error message.

insert update only modified fields over 2 servers mysql

I have 2 sql servers on 2 diferent locations.
One is a web server and the other a crm system.
People update and register on web, when they do changes i need to insert or update the changes to my crm server.
I have a view on web server where i can select from but i need to
insert into on duplicate update only fields that changed and then in a description
show
wich fields were updated?
I have no clue how to start.
You can not determine the differences on fields after changing them.
You can however select and store the contents prior to the update and then compare it with the new contents.
The question then becomes: Do you need the differences per column?
If yes: Pre-select and do the difference yourself (in the
application).
If no: Use the method described by #Ogelami (and accept his answer :)
On a side note: The Pre-Select thing won't work as well, when you start using several mysql servers, since you might run into issues with drifting data (ie one server is behind in inserted data). When this occurs, the method will get a bit more complex.
Perhaps something like this?
INSERT INTO table ON DUPLICATE UPDATE table SET field = value WHERE field != 'value'
and you might want to look into this to see if there are Affected rows.

Dynamically-naming databases with PHP/SQL

Hey there guys and gals. I'm very new to php and am following various tutorials, reading books, watching videos etc.
The reason I'm learning is to create one specific web application, as well as to make that jump from simple geek to proper nerd, of course.
So far I've managed to learn most of what I need to create this web app.
The key part that has thus far eluded me is creating a dynamically-named, pre-defined(structure) database.
Essentially the application is a giant booking system. When a user registers I want the system to create a new database and link it to their account.
Whilst I know that I could easily have a php file that could run some SQL to create a database with all the right tables and columns, I don't know how to give that new database a unique name.
That name also needs to be written into the main users table so that whenever a user name connected to that client's account logs in, it uses that database name in the connection string and pulls up their data. Though, I'm sure that part wouldn't be as complicated.
If it matters, I'm using MySQL. Any help would be greatly-appreciated.
Edit: I should've made clear why I need more than one database in the first place, my apologies.
Essentially, it's going to be a private calendar(of sorts) system for businesses. Because of that, there will be an 'owner' of each database and all employees of that person will be utilising their employer's database.
If you need to create a new database for each user, I'd suggest radically rethinking your approach to the problem.
Very few problems require going that far.
For a booking system, for instance, I would imagine you would need one database with the following tables:
A user table with the user information for each user
A hotel table (if it's hotel booking, substitute what you need) with information on the hotels-
A booking table that links each booking to a user, a hotel and a time.
Edit:
An example of a problem for which it would be suited would be a meta-booking system; as in a system where you could set up a booking system for your own site or whatever.
If that is what you need, ignore this.
Find something unique about the user, like its username, and prefix the new database name with it. You can concatenate the number of databases already assigned to that user when creating a new one, so for example my first database would be inerte_0, my second one, inerte_1. Don't forget to sanitize whatever you'll use to prefix the database name to check if it's actually composed of allowed characters in Mysql's database names!
This is certainly possible. You could, for example, call uniqid() and then check for an existing database by that name in case you happen upon a duplicate (though that's unlikely).
However, I'm extremely wary of your overall approach. In general, you should not have to create tables (excluding TEMPORARY tables) at runtime. Instead, you could put data for all organizations in a single database, but with a simple column to distinguish which records are associated with which users.
It sounds like you're using a centralized database to store some of the information - the database wherein the "main users table" you mention resides. You also mention that you can identify which client a user is associated with, which implies a clients table in that centralized database.
That clients table very likely has a primary key field. There is your unique identifier for each client's database. You can use that, or you can generate a hash of some sort using a combination of information from that row, something like:
$unique = md5( $client_id . $client_name . $date_created );
You can also make sure that the column holding the client database names is set to be unique.

Categories