I have a requirement where I need to create A database where a user can have multiple payment methods and against those multiple payment methods multiple transactions can be processed.
I have created the following schema
WHY THESE TABLES:
user: This table contains information about the user. Ex: First Name, Last Name, Email etc
user_payment_method: Since a single user can have multiple payment methods I created a table to identify all the payment methods he has so that i can reference them in the transactions table and could know on exactly which payment method the transaction was made on.
transaction: This table contains all the data about all the transactions. Ex: Time, user_id, user_method_id, amount etc
payment_method: This table acts as a junction table(pivot table) to reference all the payment methods that could exist. Since all payment methods have different details I cannot make a single table for this.
specific payment method tables: Tables like bank_transfer and paypal contain the specific details the user has about that payment method. Ex: paypal keys or bank account numbers
THE PROBLEM
I am stuck at creating a relationship between payment_method and specific payment method tables.
How do I reference different payment methods within a single column in the payment_method table. Do i create a junction(pivot) table for each specific payment method?
EDIT: If anyone has a simpler different approach please let me know too I am open to all ideas.
I would probably simplify the schema as follows:
user <- transaction -> payment method
The payment method would include your PayPal and Bank Transfer, which should not be different tables.
Generally, you should think of your payment method as a type of transaction.
When constructing a database, you look for the tables where the real action is. In this case it’s the transaction table. You can recognise it from an entity diagram as the one with the foreign keys pointing outward. In this case, you can say that a transaction belongs to a user and is of a certain type.
The transaction table would have the actual payment details, such as the date, amount, transaction number etc.
You could also have a table of preferred payment details. That would give you something like this:
user <- transaction -> payment method
<- preferred ->
Remember, that preferences can change, so the data from the preferred table should be copied into the transaction table, to allow the preferences to change later.
Needless to say, we presume that you are taking all the proper precautions regarding passwords, account details and other sensitive data …
The problem can be categorised as modelling inheritance. You have n payment methods, each with different (user specific) properties. The simplest is TPH table per hierarchy: put all the user properties for all payment methods on the user_payment_method table. There are other options covered here. Forget about pivot table: you're modelling a DB schema and you only need tables and columns. Think about what you need to store, how you need to retrieve it, and the importance of storing each fact once only.
Related
What is the best-practice for maintaining the integrity of linked data entities on update?
My scenario
I have two entities "Client and
Invoice". [client is definition and
Invoice is transaction].
After issuing many invoices to the
client it happens that the client
information needs to be changed
e.g. "his billing address/location
changed or business name ... etc".
It's normal that the users must be
able to update the client
information to keep the integrity of
the data in the system.
In the invoice "transaction entity"
I don't store just the client id but
also all the client information related to the
invoice like "client name, address,
contact", and that's well known
approach for storing data in
transaction entities.
If the user created a new invoice the
new client information will be
stored in the invoice record along
with the same client-id (very
obvious!).
My Questions
Is it okay to bind the data entities
"clients" from different locations
for the Insert and the update?
[Explanation: if I followed the
approach from step 1-4 I have to
bind the client entity from the
client table in case of creating new
invoice but in case of
updating/printing the invoice I have
to bind the client entity from the
invoice table otherwise the data
won't be consistent or integer...So
how I can keep the data integrity
without creating spaghetti code in
the DAL to handle this custom
requirements of data binding??]
I passed through a system that was
saving all previous versions of an
entity data before the update
"keeping history of all versions".
If I want to use the same method to
avoid the custom binding how I can
do this in term of database design
"Using MYSQL"? [Explanation: some
invoices created with version 1.0 of
the client then the client info
updated and its version became 1.1
and new invoices created with last
version...So is it good to follow
this methodology? and how I should
design my entities/tables to fulfil the requirements of entity
versioning and binding?
Please provide any book or reference
that can kick me in the right
direction?
Thanks,
What you need to do is leave the table the way it is. You are correct, you should be storing the customer information in the invoice for history of where the items were shipped to. When it changes, you should NOT update this information except for any invoices which have not yet been shipped. To maintain this type of information, you need a trigger on the customer table that looks for invoices that have not been shippe and updates those addresses automatically.
If you want to save historical versions of the client information, the correct process is to create an audit table and populate it through a trigger.
Data integrity in this case is simply through a foreign key to the customer id. The id itself should not ever change or be allowed to change by the user and should be a surrogate number such as an integer. Becasue you should not be changing the address information in the actual invoice (unless it has not been shipped in which case you had better change it or the product will be shipped to the wrong place), this is sufficent to maintain data integrity. This also allows you to see where the stuff was actually shipped but still look up the current info about the client through the use of the foreign key.
If you have clients that change (compaies bought by other companies), you can either run a process onthe server to update the customer id of old records or create a table structure that show which client ids belong to a current parent id. The first is easier to do if you aren;t talking about changing millions of records.
"This is a business case where data mnust be denormalized to preserve historical records of what was shipped where. His design is not incorrect."
Sorry for adding this as a new response, but the "add comment" button still doesn't show.
"His design" is indeed not incorrect ... because it is normalized !!!
It is normalized because it is not at all times true that the address corresponding to an invoice functionally depends on the customer ID exclusively.
So : normalization, yes I do think so. Not that normalization is the only issue involved here.
I'm not completely clear on what you are getting at, but I think you want to read up on normalization, available in many books on relational databases and SQL. I think what you will end up with is two tables connected by a foreign key, but perhaps some soul-searching per previous sentence will help you clarify your thoughts.
I know that there is not a "good" answer to my question, and it is opinion based. But since I am now learning those things on my own, I need advice.
I have a table on Mysql about "Customer". In this table there are columns referred to customer's info like name, surname, date of birth, address, and so on.
Each customer has his own credentials (username, password).
Now my question is: It is better to keep credentials in "customer" table, or it has sense to create a separate table, in order to guarantee the protection of these credentials, and also keep track of the changes of them along time, without wasting space repeating all the others customers' info?
You need to answer some questions about your data:
Do the columns change? People change names, addresses, and so on.
The credentials will change, at least the password.
What sort of history do you need?
My recommendation would be different sets of tables for different purposes:
One table that defines the customer id and whatever other immutable information there is (perhaps the date of becoming a customer and related information).
One or more tables with PII (personally identifiable information). You want to keep PII separate for regulatory and privacy reasons.
Tables for history. How you do this depends on your data model and what you need. A simple method is a single archive table per table in your data model. However, I might recommend type-2 tables (i.e. those having version effective and end dates).
Separate tables for credentials. These are even more sensitive than PII and you will want to control access.
Remember to never store clear-text passwords. And often you want to keep a history of passwords to prevent users from using the previous one.
It is better to create personal information in the person table and additional customer information in another table that has a relationship with the customer, and if you have any other information about the person in another table and link it to the table of persons.
Let’s say a user has 3 different ways for payment. Cash, IBAN, and through providing certain_document. Each payment type requires its own different details.
How can I store this in my database?
Let’s say the user has chosen to pay using his IBAN, assuming this picture is the current database, do I fill the fields associated with the IBAN option and set the others to Null? Or is there a more professional way to store the data without having these Null values?
UPDATE
I found a solution to this problem in the answer to this question, however, the answer is still not sufficient. If anybody has a link to a more detailed documents please let me know.
As #philipxy noted, you're asking about representing inheritance in a RDBMS. There are a few different ways to do this:
Have all of your attributes in one table (which, based on your screenshot, is what you have now). With this approach, it would be best to store NULLs in non-applicable columns---if nothing else, the default settings for InnoDB tables uses the compact row format, which means NULL columns don't take up extra storage. Of course, your queries can get complex, and maintaining these tables can become cumbersome.
Have child tables to store your details:
Payments (PaymentID, PaymentDate, etc.)
CashPaymentDetails(PaymentID, Cash_Detail_1, Cash_Detail_2, etc.)
IBANPaymentDetails(PaymentID, IBAN_Detail_1, etc.)
You can get the information for each payment by joining the base payment table with one of the "subsidiary" tables:
SELECT *
FROM Payments P INNER JOIN CashPaymentDetails C ON
C.PaymentID = P.PaymentID
Your third option is to use the entity-attribute-value (EAV) model. Like with Option 2, you have a base Payment table. However, instead of having one table for each payment method, you have one subsidiary table that contains the payment details. For more information, here's the Wiki page, and here's a blog with some additional information.
Good Day,
I'm currently designing database structure for a website of mine. I need community assistance in one aspect only as I never did something similar.
Website will include three types of the payments:
Internal payments (Escrow kind payments). User can send payment to another user.
Deposits. Users add fund to their accounts.
Withdrawal. User can request a withdrawal. Money will be sent to their bank/PayPal account.
Basically, I need some tips to get the best design possible.
Here's what I'm thinking about:
deposits - this table will store info about deposits
deposits_data - this table will store info about deposit transaction (ex. data returned by PayPal IPN)
payments - table to store internal payments
withdrawals - table to store info about withdrawal request
transactions - table to store info about ALL transactions (with ENUM() field called type with following values possible: internal, deposit, withdrawal)
Please note that I have already a table logs to store every user action.
Unfortunately, I feel that my design approch is not the best possible in this aspect. Can you share some ideas/tips?
PS. Can I use a name "escrow" for internal payments or should I choose different name?
Edit
DEPOSITS, PAYMENTS and WITHDRAWALS tables store specific transaction details. TRANSACTIONS table stores only limited info - it's a kind of logs table - with a details field (which contains a text to display in user log section, ex: "User 1 sent you a payment for something")/
Of course I have users tables, etc.
Can I use a name "escrow" for internal
payments or should I choose different
name?
Escrow has a specfic financial/legal meaning, which is different from how you seem to mean it: "a written agreement (or property or money) delivered to a third party or put in trust by one party to a contract to be returned after fulfillment of some condition" (source)
So choosing a different name seems like a good idea.
As for design, what data will DEPOSITS, PAYMENTS and WITHDRAWALS store which TRANSACTIONS won't? Also, you need an ACCOUNTS table. Or are you planning to just use your existing USERS table (I presume you have such a thing)? You probably ought to have something for external parties, even if you only intend to support PayPal for the time being.
What is the best-practice for maintaining the integrity of linked data entities on update?
My scenario
I have two entities "Client and
Invoice". [client is definition and
Invoice is transaction].
After issuing many invoices to the
client it happens that the client
information needs to be changed
e.g. "his billing address/location
changed or business name ... etc".
It's normal that the users must be
able to update the client
information to keep the integrity of
the data in the system.
In the invoice "transaction entity"
I don't store just the client id but
also all the client information related to the
invoice like "client name, address,
contact", and that's well known
approach for storing data in
transaction entities.
If the user created a new invoice the
new client information will be
stored in the invoice record along
with the same client-id (very
obvious!).
My Questions
Is it okay to bind the data entities
"clients" from different locations
for the Insert and the update?
[Explanation: if I followed the
approach from step 1-4 I have to
bind the client entity from the
client table in case of creating new
invoice but in case of
updating/printing the invoice I have
to bind the client entity from the
invoice table otherwise the data
won't be consistent or integer...So
how I can keep the data integrity
without creating spaghetti code in
the DAL to handle this custom
requirements of data binding??]
I passed through a system that was
saving all previous versions of an
entity data before the update
"keeping history of all versions".
If I want to use the same method to
avoid the custom binding how I can
do this in term of database design
"Using MYSQL"? [Explanation: some
invoices created with version 1.0 of
the client then the client info
updated and its version became 1.1
and new invoices created with last
version...So is it good to follow
this methodology? and how I should
design my entities/tables to fulfil the requirements of entity
versioning and binding?
Please provide any book or reference
that can kick me in the right
direction?
Thanks,
What you need to do is leave the table the way it is. You are correct, you should be storing the customer information in the invoice for history of where the items were shipped to. When it changes, you should NOT update this information except for any invoices which have not yet been shipped. To maintain this type of information, you need a trigger on the customer table that looks for invoices that have not been shippe and updates those addresses automatically.
If you want to save historical versions of the client information, the correct process is to create an audit table and populate it through a trigger.
Data integrity in this case is simply through a foreign key to the customer id. The id itself should not ever change or be allowed to change by the user and should be a surrogate number such as an integer. Becasue you should not be changing the address information in the actual invoice (unless it has not been shipped in which case you had better change it or the product will be shipped to the wrong place), this is sufficent to maintain data integrity. This also allows you to see where the stuff was actually shipped but still look up the current info about the client through the use of the foreign key.
If you have clients that change (compaies bought by other companies), you can either run a process onthe server to update the customer id of old records or create a table structure that show which client ids belong to a current parent id. The first is easier to do if you aren;t talking about changing millions of records.
"This is a business case where data mnust be denormalized to preserve historical records of what was shipped where. His design is not incorrect."
Sorry for adding this as a new response, but the "add comment" button still doesn't show.
"His design" is indeed not incorrect ... because it is normalized !!!
It is normalized because it is not at all times true that the address corresponding to an invoice functionally depends on the customer ID exclusively.
So : normalization, yes I do think so. Not that normalization is the only issue involved here.
I'm not completely clear on what you are getting at, but I think you want to read up on normalization, available in many books on relational databases and SQL. I think what you will end up with is two tables connected by a foreign key, but perhaps some soul-searching per previous sentence will help you clarify your thoughts.