Combining SQL Insert and Delete - sql

Ok here is the question
I have three tables
events
- id
- name
questions
- id
- event_id
- name
answers
- id
- question_id
- description
While generating the add form, i can simply search for all the questions belonging to particular event, and show the questions in single HTML form.
But consider the edit scenario. An event manager can in due time add or delete some questions from an event. So in such case, when the user tries to edit already posted answer, I generate the HTML form with the new questions as blank field and existing answers are prefilled input boxes. How can I handle the submission of this form?
When the user submits, should i delete all past answers and do a INSERT on the answers table for all the answer values? or is it a good practice to UPDATE existing answers first and INSERT only new values?
The former obiviously being easier with DELETE followed by INSERT. While the later is somewhat tedious. The problem with former solution is that the id of the answers table will increase every time..

Some people favour the delete/insert approach because, like you say, it is simpler.
Personally I think the update/insert/delete approach, while more work, is more correct.
If you do updates you can then have an audit trail of changes to a particular item. With just insert/delete it's either much harder or plain impossible to have that kind of linkage and history.
As for how to handle the submission of the form, for fields that can be updated (ie they're existing records), you need to be able to identify the field somehow. Personally I just encode something like the primary key in the field name.
If you do this you must of course ensure that you don't have a security hole by validating that the ID supplied is valid and the edit allowed ie never trust the client.
This could take the form of:
<input type="text" name="name_117" value="Some value">
<input type="text" name="name_118" value="Some other value">
<input type="text" name="name_1243" value="Yet another value">
and you have to process all the input parameters, decode the identifier and act accordingly.
Lastly, another problem with insert/delete is that you can't do it (or it just gets really hard) if the items you're deleting/inserting relate to other tables in the database. If you have a question table and store the answers people give, normally you'll reference the question as a foreign key. You lose that association if you delete/insert instead of updating.

First, the ID shouldn't be being used for anything anyway, so disregarding the incrementation is a good reminder.
I would prefer to deal with the primary question, however, cnnceptually, everything else being equal. Is the user in fact establishing a different set of questions with their edits? Then save them as a new set. Or is the original set intended to retain its conceptual identity? Then update/delete/insert. Which seems to be more the case.
In terms of securing the integrity of the question/answer set, I think of sessions having that responsibility. You should consider validating the question set against that associated with the session.

Online quiz applications usually lock down a quiz once it is live. It is a messy problem to deal with completed answer sets versus a changing definition of questions. If your application can handle it, I would favor not allowing questions to change once an event is first published.

Agree with Cletus post, writing seperately for an extra reason and an idea:
The delete/insert approach has a concurrency issue, when your website gets some heavy traffic. Someone else could do an insert after your delete, and then you'll end up with multiple answer lists per user.
MySQL supports the ON DUPLICATE KEY UPDATE syntax. That might be an easy way to combine the insert and the update, if you have an appropriate primary key.

Related

Is there a way to create an virtual table that would be compared to one after editing?

I have a table [contractor c] in which only one field [tin] may be edited. If the user tries to change data in other field it shall not be updated. Was wondering if making a view of the c before editing and then comparing the view with edited table is a good idea. But that would require two scripts- before and after update.
I could also make a validation on every single field except tin, but there is 'a lot' of fields.
Looking for the best and most optimal way to approach this task.
This is too long for a comment. There are many ways to do what you describe. "Views" are not one of them. In SQL, a view is a stored query. It does not store values. That is definitely not going to help, because the view changes with the underlying tables.
If only one column can be updated, then one method is to implement a trigger that checks the before- and after- versions of the record and only allows updates when no other fields change.
You can start learning about triggers in the documentation.
An alternative mechanism is to make the table unupdatable except for update permissions on a single column. You can learn about permissions in the documentation.
If for some reason you wanted to do all the work in the application, then transactions might come into use. You would not commit the transaction until the update meets your requirement. Transactions are explained in the documentation.

Preferred method to update 'records' using hashid, id or some form of the above?

This is an overall general design question around data integrity. I have an app that takes in user data and stores it in a DB. It is then "processed" via SSIS (SQL Service Integration Services). From this point the results are returned to the user and each record now has a Parent HASHID and it's own ID associated to it.
At this stage the user can add additional details to these records (comments, status updates etc) via an HTML form.
My question is what is the 'standard' process for tracking such changes. Create a new table for 'comments', one for 'status updates' with hashid references to the original record? OR, Update the original records and append each update to the same record (messy in my eyes)?
In the long term the app could get more complex or simplified so having a good frame-work will definitely keep things manageable for major changes. Just looking to get some general guidance.
I'm happy to add more detail but want to keep it non-specific as my question is quite broad.
Thank you.

Is limiting the type and size of a field inside of the database enough for security?

MS SQL 2008: I tried searching for this but didn't really find an answer. I know that all user input should be sanitized and validated before being saved to the database, but I'm wondering if that is also necessary for fields that are limited in the database by size and type.
For example, I have several fields that are of BIT type and would only allow 1 character, or INT fields that have a foreign key designation, so only foreign keys can be saved into it.
So now, on a form where I have a user send a message to another user, I could have
Radio button BIT (contact me yes/no)
hidden field (send to #userid#) so this will place the ID of the user into the table
DateTime field (message sent on this date) Will be automatically populated by me, but I'm throwing it in here, let's say I let the user set the time.
VarChar (max size 2), this one I wonder about, I'm guessing even just being limited to 2, a person could inject something malicious into it?
Do I need to sanitize these fields before sending them to the database, or will the database handle and reject the input?
The reason I'm asking all of this, is to find out what is generally accepted and also for performance reasons.
Thanks.
You need to sanitize your inputs to prevent malicious users from modifying your SQL query through the data to do something bad. I don't think changing the type or size will contribute to the security of your system. Your DBMS will reject any inserts where the data is of the wrong size or type.
Datatypes are not the answer to security. Datatypes should be appropriate for your business requirements. For example, if you have a requirement to allow people to rich text paragraphs, such as I am doing right now, (see rich text), then a char(10) field with html stripped out might be secure, but useless.
You've already been briefed a bit on sql injection. You also have to take heed of malicious html and javascript. Just for fun, insert this:
<script>alert("oh dear");</script>
into your database. Then write a simple .net/php/coldfusion/whatever app that selects it and displays it on a web page. Dollars to donuts it executes.
Your question has already been answered. This is just more stuff to consider.

What is the database concept equivalent to "when deleting the user, delete all his posts"?

What is the database concept equivalent to "when deleting the user, delete all his posts"?
And is this a good thing?
Another example: if your website is a programming forum, you need to find and delete comments related to that topic before deleting the topic.
Should this be handled automatically in the database layer?
cascading deletes
I would hesitate to recommend real deletion - instead using a soft deletion which marks a record as deleted - in this case, you might use cascading updates (or not, since the original topic has already been marked as deleted).
Cascading updates, usually used in conjunction with foreign key references. Different DBMS offer varying levels of support.
In the specific case of a forum or similar web site, I'd suggest using "soft" deletion - flag the rows in the databases as being deleted, which will prevent them from being viewed or returned in lists or search results, but don't remove them completely. This facilitates undeletion, etc. to counter shoddy or biased moderation.
In addition, I'd suggest that automatically deleting a user's posts when you delete their user account may not be the best behaviour in all cases - certainly, when dealing with troll/spam accounts, you may want to remove junk posts, but you don't necessarily want to blast away all the information in other cases, particularly as it introduces issues with broken references (e.g. external references, cross-linking from other posts, etc.)
The answer to your question is cascading deletes. For the record, I hate user deletion as a forum feature. If people want to leave, great ... I want to see the history of what they did while they were there.
Not sure if this is what you wanted to find out, but in MySQL the type of thing (I think) you're asking about is called a trigger. It's basically an SQL statement that you associate with a table and an action on that table; for example, you can set a statement that will execute whenever a user's record is deleted which will delete all comments/posts/whatever associated with that user.
see http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html and links therein (that's for MySQL, of course... other DBs may differ)

override constraint from no action to cascading at runtime

I feel like I have a very basic/stupid question, yet I never saw/read/heard anything in this direction.
Say I have a table users(userId, name) and a table preferences(id, userId, language). The example is trivial but could be extended to a situation with multi-level relations and way more tables..
When my UI requests to delete a user I first want to show a warning stating that also its preferences will be deleted. If at some point the database gets extended with more tables and relationships, but the software isn't adapted accordingly (the client didn't update) a generic message should be shown.
How can I implement this? The UI cannot know about the whole data structure and should not be bothered to walk down all the relations to manually delete all the depending records.
I would think this would be with constraints.
The constraint would be no action at first so the constraint will throw an error that can be caught by the UI. After the UI receives a confirmation, the constraint should become a cascade.
Somehow I'm feeling like I'm getting this all wrong..
What I would do is this:
The constraint is CASCADE
The application checks if preferences exist.
If they do, show the warning.
If no preferences exist, or the warning is accepted, delete the client.
Changing database relationships on the fly is not going to be a good idea!!
Cheers,
RB.
If you are worried about the user not realising the full impact of their delete, you might want to consider not actually deleting the data - instead you could simply set a flag on a column called say "marked_for_deletion". (the entries could then be deleted a safe time later)
The downside is that you need to remember to filter out the marked rows in other queries. This can be mitigated by creating a view on the table with the marked rows filtered out, and then always using the view in your queries.