User Management System approach for Group and Firm - php

I am creating a User Management System and need your advice.
3 entities:
Users
Firm
Group
Each user will belong to one Firm.
Some users (not all) may belong to Group.
Group is a combination of Firms. (E.g. 3 firms in a group)
The data will be displayed according to user's firm or group, if a user belongs to firm (but not group), then firm level data will be displayed. And if the user belong to group then group level data (e.g. 3 firms' data) will be displayed.
Is my below mentioned approach correct for this purpose:
CREATE TABLE `user_account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`firm` varchar(45) DEFAULT NULL, # each user belong to a client firm
`group` varchar(45) DEFAULT NULL, # some users may belong to client group
`name` varchar(45) DEFAULT NULL,
`username` varchar(15) NOT NULL, # USER ID
`password` varchar(255) NOT NULL,
`email` varchar(40) NOT NULL,
`account_creation_date` datetime DEFAULT NULL,
`active` tinyint(1) DEFAULT '1',
`token_code` varchar(255) DEFAULT NULL, # for password recovery
`token_creation_date` datetime DEFAULT NULL, # for password recovery
PRIMARY KEY (`id`),
UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL, # FOREIGN KEY user_account.user_name
`association` varchar(45) DEFAULT NULL, # Firm or Group
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Related

Why is primary key a duplicate [duplicate]

This question already has answers here:
MySQL 1062 - Duplicate entry '0' for key 'PRIMARY'
(9 answers)
Closed 6 years ago.
I am building a CRUD app in PHP & MySql. It uses two tables, called users and medical_records:
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`username` varchar(255) NOT NULL,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(1024) NOT NULL,
`validation_code` text NOT NULL,
`active` tinyint(1) NOT NULL,
`telefon` varchar(255) DEFAULT NULL,
`oras` varchar(255) DEFAULT NULL,
`adresa` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE medical_records (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`fo` VARCHAR(255),
`condition` VARCHAR(255),
`transfer` VARCHAR(255),
`memo` text(1024),
`body_temperature` VARCHAR(255),
PRIMARY KEY (`id`),
CONSTRAINT FK_medical_records_1
FOREIGN KEY (user_id) REFERENCES users(id)
ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
The "business logic" of these tables is: every user has one (only one) medical record.
I used and tested the application when it only had the users table. Register and login worked fine, so I conclude that the problem's source can't be the application's (PHP) code.
I later doped the users table and added the 2 fresh tables the application now uses (users and medical_records).
At this moment whenever I try to register a second user, I get the error:
QUERY FAILED: Duplicate entry '0' for key 'PRIMARY'
This happens despite the fact that both tables have auto incremented primary keys. What could be the explanation of that?
the id in the users table is not set to AUTO_INCREMENT. that's why this happens.

how to insert many items from a file txt to a database in one step

Hello guys I'm about to create a quiz as a school project
so the web application allow users to pass a quiz
the problem is I've too many questions to add and each question has a correct answer and 3 choices so it's way too difficult to add all this stuff in the database
so I'm wondered if I could do it automatically
this is a question table
CREATE TABLE IF NOT EXISTS `question` (
`Id_Qst` int(11) NOT NULL AUTO_INCREMENT COMMENT 'identifiant',
`choice1` varchar(150) NOT NULL,
`choice2` varchar(150) DEFAULT NULL,
`choice3` varchar(150) DEFAULT NULL,
`correctanswer1` varchar(150) NOT NULL,
`correctanswer2` varchar(150) DEFAULT NULL,
`qst1` varchar(150) NOT NULL,
`qst2` varchar(150) DEFAULT NULL,
`lvl` int(11) NOT NULL,
`Image` blob NOT NULL,
PRIMARY KEY (`Id_QstS`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
composed questions are included in my quiz so I chose to add qst1 and qst2
Thank you !

Polymorphic Associations or something easier

This is my first post and I can't seem to find the answer anywhere....
I have a database that has multiple companies,each company has multiple locations.
I'm running into problems trying to define the contacts. Some contacts need to be global and available
at any location....some contacts only need to exist for one location. In the contact_info table below
we specify the visibility of the contact (company or location). However the location needs to choose its primary contact.
That leaves a FK from contact -> location and from location -> contact.
I know there is another table involved but I can't seem to conceptualize it.
CREATE TABLE `company_info` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`));
CREATE TABLE `location_info` (
`id` INT NOT NULL AUTO_INCREMENT,
`company_info` INT NOT NULL DEFAULT -1,
`name` VARCHAR(100) NOT NULL DEFAULT '',
`primary_contact_id` INT NOT NULL DEFAULT -1,
PRIMARY KEY(`id`),
UNIQUE KEY(`company_id`,`name`),
FOREIGN KEY (company_id) REFERENCES company_info(id)
FOREIGN KEY (primary_contact_id) REFERENCES contact_info(id));
CREATE TABLE `contact_info` (
`id` INT NOT NULL AUTO_INCREMENT,
`company_id` INT
`location_id` INT,
`type` ENUM('Company','Location') NOT NULL DEFAULT 'Company',
`first_name` VARCHAR(50) NOT NULL DEFAULT '',
`last_name` VARCHAR(50) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
UNIQUE KEY(`id`,`company_id`,`location_id`),
FOREIGN KEY (location_id) REFERENCES location_info(id),
FOREIGN KEY (company_id) REFERENCES company_info(id)
The most effective way would be splitting it up so that there's a table for your companies, a table with your users, and a table solely for the purpose of storing all connections (i.e. EntryID, UserID, CompanyID). This way you'll be able to easily load them afterwards.

which is the correct way for this database design

I have four tables, namely
countries,states,cities,areas
which will be the best feasible solution for my database table
Method A :
CREATE TABLE IF NOT EXISTS `countries` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
PRIMARY KEY  (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `states` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`country_id` int(11) NOT NULL,
PRIMARY KEY  (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `cities` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`state_id` int(11) NOT NULL,
PRIMARY KEY  (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `areas` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`zipcode` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
PRIMARY KEY  (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
or Method B :
CREATE TABLE IF NOT EXISTS `countries` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `states` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`country_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `cities` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`state_id` int(11) NOT NULL,
`country_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `areas` (
`id` int(11) auto_increment NOT NULL,
`name` varchar(50) NOT NULL,
`zipcode` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`country_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Thank you..
The first is less likely to have problems with synchronization.
The second will offer better performance through denormalization.
Possible related thread: What is a good way to denormalize a mysql database?
The second version will lead to major headaches if mismatched data is entered. Take the following sample data:
countries: Canada, USA
states: Saskatchewan, Michigan
cities: Saskatoon, Detroit
zipcode: 90210 (california)
insert into area (...) ('Canada', 'Michigan', 'Saskatoon', 90210)
all individually valid, but the entire record is utterly wrong. Yet, by your design, it's supposed to be valid.
It probably depends on what queries you are going to run on those tables. In general, A is normalized whereas B is not (A will use less space).
I would start with Method A, but if it turns out performance requires the additional columns further down the chain, I'd add them only as needed.
Just be sure to make your _id columns indexes.
I prefer Method A at first glance, but without knowing specifics about what you want the relationships and constraints to be, it's impossible to say categorically that one is "better" than the other. Follow your application's functional requirements.
Congratulations on looking towards a normalised approach: it's nice to see!
I personally would choose the first one [Method A]. If you know, for example, the city ID of an area, then you automatically know the state ID and the country ID. While the second one may be a bit more convenient, you may run into issues down the line if say, a city moved to a different state.
It's always best to start with the normalized form. I would only suggest Method B if you had your RDBMS automatically managing cached column updates. For example, if you mistakenly placed Los Angeles in Michigan, you would need to update multiple locations (unless you had triggers that would update cascading pieces of information in denormalized tables). But without triggers, Method A is without a doubt the best form.
This is assuming of course that your constraints match the ones implicitly dictated by common interpretation when viewing Method A's definition.

Database structure for social login implementation?

In my application, I have a "user" table that has the following structure.
CREATE TABLE IF NOT EXISTS `users` (
`userId` int(10) unsigned NOT NULL auto_increment,
`username` varchar(128) NOT NULL default '',
`password` varchar(32) NOT NULL default '',
`email` text NOT NULL,
`newsletter` tinyint(1) NOT NULL default '0',
`banned` enum('yes','no') NOT NULL default 'no',
`admin` enum('yes','no') NOT NULL default 'no',
`signup_ip` varchar(20) NOT NULL default '',
`activation_key` varchar(60) NOT NULL default '',
`resetpassword_key` varchar(60) NOT NULL default '',
`createdon` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`userId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;
I want to implement social login via Facebook, Twitter, and OpenID in my application, just like Stack Overflow did.
I would suggest that you introduce the concept of an AuthenticationProvider:
CREATE TABLE IF NOT EXISTS `AuthenticationProvider` (
`ProviderKey` varchar(128) NOT NULL,
`userId` int(10) unsigned NOT NULL,
`ProviderType` enum('facebook','twitter', 'google') NOT NULL,
PRIMARY KEY (`ProviderKey`) )
ENGINE=MyISAM DEFAULT CHARSET=latin1;
Each login provider provides a unique key for the user. This is stored in ProviderKey. The ProviderType contains information about which login provider this ProviderKey belongs to, and finally, the userId column couples the information with the users table. So when you receive a succesful login from one of the login providers you find the corresponding ProviderKey in the table and use set the authentication cookie for the user in question.
I'm not sure that you want the ProviderType to be an enum. It would probably be more correct to make another table that could hold these.
When a user first registers with your site, and logs in via Facebook, for example, you will have to create a row in the users table. However, there will be no password, activation_key and resetpassword_key involved. So you may want to move those fields to a separate table, such that your users table only contains the core user data, and no data that is only relevant for a single login mechanism (username/password).
I hope this makes sense and that it points you in the right direction.
/Klaus

Categories