How to design parametric tables and their consumers? [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this questionI'm being doubtful for a long time about how to design parametric tables...
- Do you think is a bad practice to let the html contain the pks of a web app? I think it is, and I propose to use guids instead pks.
- Do you know any pattern related to te design of parametric tables? Usually I find a table for a kind of parametric data (i.e. a table for gender, a table for countries... etc.) on some database designs. I do prefer only one table with all parameters and a co开发者_运维百科lumn with keys to reference them from upper layers.
- What do you think about having a source file with the same information as the parametric tables? I've seen some projecs having source code with every pk related to a parameters... is this a good practice?
- Do you think it is relevant to create a caching scheme to keep parameter data?
Thanks!
Note: This question extends this.
It's hard to understand what you are describing without seeing an example. But it sounds like you're talking about a database design antipattern that's often called One True Lookup Table.
CREATE TABLE Parameters (
key VARCHAR(20) PRIMARY KEY,
value VARCHAR(255) NOT NULL,
);
The problems with this design include:
You can't use the SQL data type that fits best, because the
value
column must accommodate integers, dates, strings -- all values for all possible parameter types.You can't use constraints to limit the values for a given parameter type. For example you might want a CHECK constraint that makes sure postal codes fit a certain pattern. But you can't, because then all parameters of all types would have to conform to the same pattern.
You can't use this table as a lookup table to constrain other tables. For example, if you want a
country
column in another table to reference the list of countries and permit no other value. By storing all lookup data in the same column, yourcountry
column could reference any value of any parameter type. There are no countries'M'
or'F'
but your database would permitcountry
to reference it.You can't create a real
FOREIGN KEY
constraint anyway, unless theParameters.value
column has aUNIQUE
constraint on it, which it couldn't because'M'
could be either "male" or "medium shirt size" and therefore appear twice in the Parameters table.You can't guarantee that a given key exists at all, because there's no way to force a table to contain a row with a certain primary key. This is what
NOT NULL
is for in a conventional database design, where parameters belong in columns, not rows.The table may grow large, so that it becomes inefficient to look up values that rightly belong in a small set. Your list of application configuration parameters is stored with lists of countries and postal codes and so on.
Despite what Richard Harrison wrote in his answer to your other question, he's wrong. OTLT is a bad design and you'll regret using it.
See also OTLT and EAV: the two big design mistakes all beginners make
Regarding your specific questions:
Do you think is a bad practice to let the html contain the pks of a web app? I think it is, and I propose to use guids instead pks.
The most common warning about revealing pks in the user-visible layer of a web app is that it can give attackers information about how to address parts of your data. It sounds like you're still showing the pk values in your web app, but you've simply traded GUIDs for integers. I don't see how this is better.
update: To be clear, if your code allows users to do something illicit by knowing the PK value, then it would also allow the same illicit action if the user knows some surrogate value that maps to a PK value. You haven't added any protection by using a surrogate value.
Is then necessary to "take the risk"? what can be done instead?
Defensive programming. Don't assume that users will only click on links provided for them, they could edit the link to specify some other pk value and submit that. Attackers are adept at this sort of thing.
For example:
http://www.example.com/change-password.php?account_id=12345&new-password=xyzzy
Your PHP script should check that the current user's session is logged into an account that has privilege to change the password for account 12345. Don't just assume that it's okay because the web app wouldn't have shown the user a link to do something they don't have privilege to do. Even if the app is correct, an attacker can change the values to anything they want, and submit that.
You must write code in your app to check that the user has privilege to use the data they request, assuming they can request data even if they don't have privilege to see it. If you can do this, you reduce the risk of exposing pk values.
update: Hiding PK values is security by obscurity, which is not an effective security strategy. Your code needs to check that the user has privilege to see or change the records for that PK. If you do this correctly, an attacker should get an "access denied" error if they try to do something they shouldn't.
If you have programmers who make mistakes, then structure your application to assume a user has no privileges, and require the programmer to write code to establish authorization before every type of action.
Also, use code tests to verify that a user can invoke a given task only when they have the right privileges, and a non-privileged user cannot invoke that task, and that they receive an appropriate error message. Require programmers to write tests for any functionality they touch.
I do prefer only one table with all parameters and a column with keys to reference them from upper layers.
No. OTLT is a bad design. See above.
What do you think about having a source file with the same information as the parametric tables? I´ve seen some projecs having source code with every pk related to a parameters... is this a good practice?
No. The point of storing parameters in the database is so that you can update them by accessing the database, and they'll automatically take effect in other pages that use the data. If you have to update your code anyway to work with new values, then there's no advantage to having stored the parameters in a database. If that's true, you might as well store the values only in the code.
About the source code with parameter data: how then to reference specific prm from client code? suppose I have in bussiness layer some logic regarding gender that uses prm data to work... how to relate both data (I used to create constant tables)? I think I need at least a key hard-coded at BL...
I'm guessing you use a surrogate key for everything...
Do you know how to use JOINs in SQL? You can join your table to the lookup table and search for the value instead of its surrogate key.
SELECT ... FROM People JOIN Genders USING (gender_id) WHERE gender = 'M'
For lookup tables, I like to use natural keys. Then you can search on the value 'M'
instead of the surrogate key for that value.
SELECT ... FROM People WHERE gender = 'M'
Do you think it is relevant to create a caching scheme to keep parameter data?
Yes. Parameter data probably changes infrequently, and your performance can benefit from reducing the number of queries your app uses to fetch them. When you update the values, invalidate the respective entry in the cache.
精彩评论