Sorry guys, I'm no master of MySQL and I've only just begun learning this but the first thing getting me frustrated right now is adding a field that is a "Longtext" and it automatically goes PRIMARY and INDEXED and also UNIQUE.
That field I'm talking about is for storing huge amount of characters, basically it is where I plan to store 1 page of texts which is why I need it to be "Longtext". Problem is no matter what I do I can't remove Unique or Indexed or Primary from fields that are "Longtext". I do not want to remove it through queries, I am trying to remove it through PHPMyAdmin since I don't want to do the SQL query for this task only. I keep clicking on the fields and clicking Index or Primary or Unique but it never changes, I'm getting so frustrated :(
Sounds like the problem is with PHPMyAdmin, rather than MySQL, because what you describe does not sound like any behavior of MySQL. (To find out if it's a MySQL problem, we'd really need to see the actual SQL statements being run, what is recorded in the information_schema tables/views, etc.)
I understand you don't want to run the SQL statements that are actually required by MySQL.
It sounds as if the developers of PHPMyAdmin didn't want to run them either.
Related
Please I am creating a database system for a group,using mysql and php.I am faced with some challenges,these are
1.I want to make the database system dynamic - thus where an administrator using the system would be able to add columns to a specific table from the front end without having to know something about mysql and php.
2.Also,I want the administrator who is ignorant of mysql and php, to be able to add tables to the database through the front end (PHP page).
3.With the aforementioned problems in (1 and 2), how would I make the columns added by the administrator appear on a form (php page) from the database, and how do I check for errors on the form.
Please these are instances to clarify what I have said.
a.What should I do to make a client add columns to an existing table in the database without any assistance from the technical team?
b.What should I do to make a client add tables to an existing database without help from technical team?
c.How do I output columns added by an administrator to a form and also check for errors on the form (php page) .
Any help is welcomed.Thank You
Well basically you can just write queries like ALTER TABLE xxx ADD column VARCHAR(100) etc. filling in the desired values from a form. This is, however, strongly discouraged. Not only would this mean your script would be able to execute queries which normally can only be executed by (mysql) users with administrator rights, it is also very susceptible to security problems.
Reading your question immediately starts me to think of an EAV-like1 database system, although it is a highly controversial scheme to use in a relational database system like mysql, to use on any system actually...
A few problems that come to mind (most points apply to EAV too btw)
You will lose any logical structure
As any type of data can be linked to any type of entity, so - in your database at least - there is no logical relation between your attributes (or columns in your case) and your entities (tables in your case), other then just being present.
Very, very hard to maintain
If your tables grow, what columns should be indexed? How would you prevent from someone ignorant - and as you say they are by default - adding 200 columns to a table? Numerous other problems can be summed up here...
What about restrictions?
How are you gonna decide who is allowed to add/delete/edit what columns? And how are you force them to choose the right column-type? Or when a table is added: what should be the (coumpound) primary key? Remember: your administrators are ignorant. I guess this would rise the need for meta-tables, holding this kind of information. Are you sure you want to write all the logic for this? And are you sure you are wanting to keep track of bugs etc, bugs which will most probably allow your system to collapse like a card-house?
It smells like an excel sheet...
Without functions that is, but still. So why not send your administrators a link to google docs? ;)
No really, it sounds like a very bad idea...
Please post your full user-case, I'm quite sure we can think of a better solution then adding columns and adding tables to a database.
I have just been tasked with recovering/rebuilding an extremely large and complex website that had no backups and was fully lost. I have a complete (hopefully) copy of all the PHP files however I have absolutely no clue what the database structure looked like (other than it is certainly at least 50 or so tables...so fairly complex). All data has been lost and the original developer was fired about a year ago in a fiery feud (so I am told). I have been a PHP developer for quite a while and am plenty comfortable trying to sort through everything and get the application/site back up and running...but the lack of a database will be a huge struggle. So...is there any way to simulate a MySQL connection to some software that will capture all incoming queries and attempt to use the requested field and table names to rebuild the structure?
It seems to me that if i start clicking through the application and it passes a query for
SELECT name, email, phone from contact_table WHERE
contact_id='1'
...there should be a way to capture that info and assume there was a table called "contact_table" that had at least 4 fields with those names... If I can do that repetitively, each time adding some sample data to the discovered fields and then moving on to another page, then eventually I should have a rough copy of most of the database structure (at least all public-facing parts). This would be MUCH easier than manually reading all the code and pulling out every reference, reading all the joins and subqueries, and sorting through it all manually.
Anyone ever tried this before? Any other ideas for reverse-engineering the database structure from PHP code?
mysql> SET GLOBAL general_log=1;
With this configuration enabled, the MySQL server writes every query to a log file (datadir/hostname.log by default), even those queries that have errors because the tables and columns don't exist yet.
http://dev.mysql.com/doc/refman/5.6/en/query-log.html says:
The general query log can be very useful when you suspect an error in a client and want to know exactly what the client sent to mysqld.
As you click around in the application, it should generate SQL queries, and you can have a terminal window open running tail -f on the general query log. As you see queries run by that reference tables or columns that don't exist yet, create those tables and columns. Then repeat clicking around in the app.
A number of things may make this task even harder:
If the queries use SELECT *, you can't infer the names of columns or even how many columns there are. You'll have to inspect the application code to see what column names are used after the query result is returned.
If INSERT statements omit the list of column names, you can't know what columns there are or how many. On the other hand, if INSERT statements do specify a list of column names, you can't know if there are more columns that were intended to take on their default values.
Data types of columns won't be apparent from their names, nor string lengths, nor character sets, nor default values.
Constraints, indexes, primary keys, foreign keys won't be apparent from the queries.
Some tables may exist (for example, lookup tables), even though they are never mentioned by name by the queries you find in the app.
Speaking of lookup tables, many databases have sets of initial values stored in tables, such as all possible user types and so on. Without the knowledge of the data for such lookup tables, it'll be hard or impossible to get the app working.
There may have been triggers and stored procedures. Procedures may be referenced by CALL statements in the app, but you can't guess what the code inside triggers or stored procedures was intended to be.
This project is bound to be very laborious, time-consuming, and involve a lot of guesswork. The fact that the employer had a big feud with the developer might be a warning flag. Be careful to set the expectations so the employer understands it will take a lot of work to do this.
PS: I'm assuming you are using a recent version of MySQL, such as 5.1 or later. If you use MySQL 5.0 or earlier, you should just add log=1 to your /etc/my.cnf and restart mysqld.
Crazy task. Is the code such that the DB queries are at all abstracted? Could you replace the query functions with something which would log the tables, columns and keys, and/or actually create the tables or alter them as needed, before firing off the real query?
Alternatively, it might be easier to do some text processing, regex matching, grep/sort/uniq on the queries in all of the PHP files. The goal would be to get it down to a manageable list of all tables and columns in those tables.
I once had a similar task, fortunately I was able to find an old backup.
If you could find a way to extract the queries, like say, regex match all of the occurrences of mysql_query or whatever extension was used to query the database, you could then use something like php-sql-parser to parse the queries and hopefully from that you would be able to get a list of most tables and columns. However, that is only half the battle. The other half is determining the data types for every single column and that would be rather impossible to do autmatically from PHP. It would basically require you inspect it line by line. There are best practices, but who's to say that the old dev followed them? Determining whether a column called "date" should be stored in DATE, DATETIME, INT, or VARCHAR(50) with some sort of manual ugly string thing can only be determined by looking at the actual code.
Good luck!
You could build some triggers with the BEFORE action time, but unfortunately this will only work for INSERT, UPDATE, or DELETE commands.
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
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.
The server is a shared Windows hosting server with Hostgator. We are allowed "unlimited" MS SQL databases and each is allowed "unlimited" space. I'm writing the website in PHP. The data (not the DB schema, but the data) needs to be versioned such that (ideally) my client can select the DB version he wants from a select box when he logs in to the website, and then (roughly once a month) tag the current data, also through a simple form on the website. I've thought of several theoretical ways to do this and I'm not excited about any of them.
1) Put a VersionNumber column on every table; have a master Version table that lists all versions for the select box at login. When tagged, every row without a version number in every table in the db would be duplicated, and the original would be given a version number.
This seems like the easiest idea for both me and my client, but I'm concerned the db would be awfully slow in just a few months, since every table will grow by (at least) its original size every month. There's not a whole lot of data, and there probably never will be, in any one version. But multiplying versions in the same table just scares me.
2) Duplicate the DB every time we tag.
It looks like this would have to be done manually by my client since the server is shared, so I already dislike the idea. But in addition, the old DBs would have to be able to work with the current website code, and as changes are made to the DB structure over time (which is inevitable) the old DBs will no longer work with the new website code.
3) Create duplicate tables (with the version in their name) inside the same database every time we tag. Like [v27_Employee].
The benefit here over idea (1) would be that no table would get humongous in size, allowing the queries to keep up their speed, and over idea (2) it could theoretically be done easily through the simple website tag form rather than manually by my client. The problems are that the queries in my PHP code are going to get all discombobulated as I try to explain which Employee table is joining with which Address table depending upon which version is selected, since they all have the same name, but different; and also that as the code changes, the old DB tables no longer match, same problem as (2).
So, finally, does anyone have any good recommendations? Best practices? Things they did that worked in the past?
Thanks guys.
Option 1 is the most obvious solution because it has the lowest maintenance overhead and it's the easiest to work with: you can view any version at any time simply by adding #VersionNumber to your queries. If you want or need to, this means you could also implement option 3 at the same time by creating views for each version number instead of real tables. If your application only queries one version at a time, consider making the VersionNumber the first column of a clustered primary key, so that all the data for one version is physically stored together.
And it isn't clear how much data you have anyway. You say it's "not a whole lot", but that means nothing. If you really have a lot of data (say, into hundreds of millions of rows) and if you have Enterprise Edition (you didn't say what edition you're using), you can use table partitioning to 'split' very large tables for better performance.
My conclusion would be to do the simplest, easiest thing to maintain right now. If it works fine then you're done. If it doesn't, you will at least be able to rework your design from a simple, stable starting point. If you do something more complicated now, you will have much more work to do if you ever need to redesign it.
You could copy your versionable tables into a new database every month. If you need to do a join between a versionable table and a non-versionable table, you'd need to do a cross-schema join - which is supported in SQL Server. This approach is a bit cleaner than duplicating tables in a single schema, since your database explorer will start getting unwieldy with all the old tables.
What I finally wound up doing was creating a new schema for each version and duplicating the tables and triggers and keys each time the DB is versioned. So, for example, I had this table:
[dbo].[TableWithData]
And I duplicated it into this table in the same DB:
[v1].[TableWithData]
Then, when the user wants to view old tables, they select which version and my code automatically changes every instance of [dbo] in every query to [v1]. It's conceptually fairly simple and the user doesn't have to do anything complicated to version -- just type in "v1" to a form and hit a submit button. My PHP and SQL does the rest.
I did find that some tables had to remain separate -- I made a different schema called [ctrl] into which I put tables that will not be versioned, like the username / password table for example. That way I just duplicate the [dbo] tables.
Its been operational for a year or so and seems to work well at the moment. They've only versioned maybe 4 times so far. The only problem I seem to have consistently that I can't figure out is that triggers seem to get lost somehow. That's probably a problem with my very complex PHP rather than the DB versioning concept itself though.
Alright, I've got a question, not really an issue.
I've got a table in my database, fairly small, only 3 columns but potential to grow. I've got two solutions to my problem, but not sure why to use one or the other.
I've got a piece of data, which might or might not already be in the database. Two ways to solve this. I've got the unique ID, so it is easy to check.
Check if the records exists in the database, and if not, INSERT INTO database
Use REPLACE INTO, because I've got the ID already.
My question now is. Which one is better to use. What are the pros and cons in using either of the 2 results. Or is there a better result?
A note, the data is exactly the same, so there is no chance the record gets updated with a newer value. Thus the REPLACE INTO will insert data which is already there.
REPLACE INTO is not recommended here - you don't really need to replace anything. It does DELETE followed by INSERT, with all the consequences. For example all indexes have to be updated, which leads to unnecessary work and index fragmenting if you use it frequently.
On the other hand there is ON DUPLICATE KEY UPDATE, which is used mainly for counters, but you are not updating your row with increments or any other value changes, so you would have to use weird syntax like SET id=id or something similar.
Checking if the record exists in the database would be the best solution for you, but instead of using another query let mysql do that check for you and use:
`INSERT IGNORE INTO ...`
This way if you try to insert any row with duplicated unique or primary key it simply won't be inserted without generating any error. Note the side effect of possibly missing other error messages, but if you know exactly what you insert you should be fine.