Let me illustrate this question with a simplified example. Assume I am building a project using python with a PostgreSQL relational database. In my database I have two tables "parent" and "child" which are N to M related through the table "parent_child". I want to be able to retrieve some data about a specific child owned by a specific parent in a secure way, which the following query lets me do (X, Y, and Z are literals supplied by the user):
SELECT child.age FROM parent, parent_child, child
WHERE child.id = parent_child.child_id AND parent_child.id = X
AND parent_child.parent_id = parent.id AND parent.id = Y
AND parent.password = Z;
Say a user comes along and types in the wrong value for either X, Y, or Z, the query would return an empty set, which could be detected and a message passed on to the user that there was an error. The problem of course is that I am unable to determine which value is causing problems and hence can not supply the user with specific information about what they mis-entered?
The simplest solution to this is to break up the query into several parts. First, verifying that the parent.id exists.
SELECT parent.id FROM parent WHERE parent.id = Y;
Second, checking if the password is correct.
SELECT parent.id FROM parent WHERE parent.id = Y and parent.password = Z;
Third, checking if the child exists.
SELECT child.id FROM child WHERE child.id = X;
Fourth, checking that the child is owned by the parent and returning the information we need.
SELECT child.age FROM child, parent_child WHERE parent_child.child_id = child.id AND parent_child.parent_id = Y AND parent_child.child_id = X;
These four queries will allow us to check specific things about the user supplied information and report specific problems as they occur. Obviously there is a lot of additional overhead in four queries verses a single query and I find four queries less readable than a single one. So is there anyway to have the best of both worlds? A single query and detailed error messages?