1

My database/table each endpoint/scope have multiple table,
e.g user: user, user_information, user_role ...
I was wondering should I separate table like below, or not?

This is my first time to build a product not like before just make some onetime work small website. and this it might add more feature in future version.

I'm not sure about is this overdesign? Does separate table like this any benefit in the future ??
and cons I know is use more table join, and more difficult to me to maintain build the query.

any suggestion, share experience will be really appreciate.



For now I only can imagine I might want to know each column last modified time?

So if I want to know each column last modified time, is there any original build method in PostgreSQL? or I have to add for each column like email_last_modified_date, username_last_modified_date ...



endpoint/scope user

CREATE TABLE IF NOT EXISTS "user"(
    "id" SERIAL NOT NULL,
    "create_date" timestamp without time zone NOT NULL,
    "last_modified_date" timestamp without time zone,
    "last_modified_by_user_id" integer,
    "status" integer NOT NULL,
    PRIMARY KEY ("id")
  );

CREATE TABLE IF NOT EXISTS "user_information"(
    "id" SERIAL NOT NULL,
    "create_date" timestamp without time zone NOT NULL,
    "last_modified_date" timestamp without time zone,
    "last_modified_by_user_id" integer,
    "user_id" integer NOT NULL,
    "email" varchar(100) NOT NULL,
    "username" varchar(50),
    "password" varchar NOT NULL,
    "first_name" varchar(50),
    "last_name" varchar(50),
    "website" varchar,
    "description" varchar,
    "birth_date" timestamp without time zone,
    "country" varchar(50),
    "gender" integer,
    "file_type" integer,
    "file_name" varchar(50),
    "file_extension" varchar(50),
    "file_portrait" boolean,
    PRIMARY KEY ("id"),
    FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE
  );
CREATE TABLE IF NOT EXISTS "user_role"(
    "id" SERIAL NOT NULL,
    "create_date" timestamp without time zone NOT NULL,
    "last_modified_date" timestamp without time zone,
    "last_modified_by_user_id" integer,
    "user_id" integer NOT NULL,
    "role" integer NOT NULL,
    PRIMARY KEY ("id"),
    FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE
  );

merge table ?

CREATE TABLE IF NOT EXISTS "user"(
    "id" SERIAL NOT NULL,
    "create_date" timestamp without time zone NOT NULL,
    "last_modified_date" timestamp without time zone,
    "last_modified_by_user_id" integer,
    "status" integer NOT NULL,

    "information_last_modified_date" timestamp without time zone,
    "information_last_modified_by_user_id" integer,
     .... user_information 

    "role_last_modified_date" timestamp without time zone,
    "role_last_modified_by_user_id" integer,
    ... user_role
    PRIMARY KEY ("id")
  );

1 Answer 1

1

I was wondering should I separate table like below, or not?

Well, one immediately obvious downside of the table design you posted is that there are no constraints on user_information or user_role ensuring that you don't have more than one such row in each of these tables for each user. And even if you remember to add that, you will still have the problem that it will be difficult or impossible to enforce the rule "every user must have a role (or other critical attribute)".

Where it typically makes sense to break out metadata like this is when you have either many-to-one relationship of this metadata (e.g. a single user may have multiple roles), or you have a lot (i.e. many columns) of optional metadata that is unwieldy to cram into a single table.

For now I only can imagine I might want to know each column last modified time?

So if I want to know each column last modified time, is there any original build method in PostgreSQL? or I have to add for each column like email_last_modified_date, username_last_modified_date ...

You'll have to create individual columns (e.g. "email_last_modified_date") and have a trigger function enforce that the column is set correctly to achieve this. A more flexible and useful approach is usually constructing an audit table, with a trigger on the "user" table saving the changed columns for every UPDATE, or the contents of the whole row for every DELETE. This is where json, jsonb, or hstore types come in handy, if you'd like a single audit table capable of dealing with several tables, or capable of dealing with many columns from a single user table without needing to know the structure of the user table.

3
  • Thanks for reply, how about if I add a a new column modified json ? or jsonb? and everytime in table which column change also create new row in json data, is this easy to use in future select/read. and data structure like: "modified": [ { "id": 0, "column": "email", "date": "", "by_user_id": "" } ] Commented Jul 10, 2016 at 5:27
  • Plenty of examples of how to set up audit tables to choose from: here or here or here. Commented Jul 11, 2016 at 0:39
  • thanks, I found these and I made a example code in stackoverflow.com/questions/38296728/… but I can't find how to save only changed column Commented Jul 11, 2016 at 0:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.