Referential integrity for invoice and task tables - mysql

I am having trouble figuring out how to design a database for an invoicing system. I want to have an invoice table and an tasks table. I want a record in the invoices table to be able to have a variable amount of tasks associated with it but also keep referential integrity so that a task cannot be added that does not exist on the tasks table.
So far I have come up with a task_id1, task_id2, etc... fields on the invoices table that are foreign keys to the task_id field in the tasks table but it feels limiting in the number of tasks that can be put on one invoice.
Alternatively the invoices table could have a comma separated list of task_id's that would allow for a variable amount of tasks per invoice but I cant figure out how to create the foreign key if the column types are not the same. (Plus this feels a little sloppy).
Im sure there is an easy answer I am not seeing.

So far I have come up with a task_id1, task_id2, etc... fields on the
invoices table that are foreign keys to the task_id field
Alternatively the invoices table could have a comma separated list of
task_id's that would allow for a variable amount of tasks per invoice
NOO!!!
Make a many-to-many tables between invoices and tasks, and make the constraint between this table and both the invoice and task table.
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`invoices`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`invoices` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATETIME NULL ,
`amount` DECIMAL(7,2) NULL ,
`whatever` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`tasks`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`tasks` (
`id` INT NOT NULL AUTO_INCREMENT ,
`whatever` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`invoices_has_tasks`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`invoices_has_tasks` (
`invoices_id` INT NOT NULL ,
`tasks_id` INT NOT NULL ,
PRIMARY KEY (`invoices_id`, `tasks_id`) ,
INDEX `fk_invoices_has_tasks_tasks1_idx` (`tasks_id` ASC) ,
INDEX `fk_invoices_has_tasks_invoices_idx` (`invoices_id` ASC) ,
CONSTRAINT `fk_invoices_has_tasks_invoices`
FOREIGN KEY (`invoices_id` )
REFERENCES `mydb`.`invoices` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_invoices_has_tasks_tasks1`
FOREIGN KEY (`tasks_id` )
REFERENCES `mydb`.`tasks` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;

To create the invoice table
CREATE TABLE invoice (
invoice_id INT NOT NULL,
PRIMARY KEY (invoice_id)
) ENGINE=INNODB;
To create the tasks table use
CREATE TABLE tasks (
task_id INT,
invoice_id INT,
INDEX par_ind (invoice_id),
FOREIGN KEY (invoice_id)
REFERENCES invoice(invoice_id)
ON DELETE CASCADE
) ENGINE=INNODB;
That is all you need

Related

Enforcing single subtype SQL table for supertype table

I have a supertype table called "vehicles". I also have three subtype tables called "airplanes", "automobiles", and "bicycles", and one and only one of these subtype tables must be linked to the vehicles supertype table (or in other words, must use the vehicles primary key ID as its primary key ID).
How should this be modeled to enforce this behavior?
EDIT Proposed schema recommended by Mike Brant.
-- MySQL Script generated by MySQL Workbench
-- 05/25/16 09:20:17
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`vehicle_types`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicle_types` (
`type` CHAR(8) NOT NULL,
PRIMARY KEY (`type`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`vehicles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` CHAR(8) NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC),
CONSTRAINT `fk_vehicles_vehicle_types`
FOREIGN KEY (`type`)
REFERENCES `mydb`.`vehicle_types` (`type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`airplanes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`automobiles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`automobiles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_automobiles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_automobiles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`bicycles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`bicycles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_bicycles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_bicycles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
I think inserting in vehicles and any of other sub types should be simultaneously. Therefore you can get the vehicle ID and put as new sub-type PK ID. If you have all information at the same time you can create a transcation and insert the vehicle record first then the sub-type record. Then commit your transscation otherwise rollback it. IF you want to know which record belongs to which sub-type table record you can add a column to your vehicle table that for example can have 3 different values such as 0,1,2 that shows which record belongs to which sub-table. Enum in java can be used in something like that for more clarification
Looking at your proposed schema, I see no reason whatsoever for you to have separate tables for each vehicle type, or even a separate table to contain the allowable vehicle types. Your vehicle-specific tables are all basically the same thing meaning you can easily collapse into a single table, and you can use ENUM field to enforce allowable vehicle types.
Why not just have a single vehicles table like the following?
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` ENUM('airplane', 'automobile', 'bicycle') NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC))
ENGINE = InnoDB;
This approach totally eliminates 4 of your 5 tables, meaning you no longer have to consider using joins, foreign key constraints, etc. when performing CRUD operations against these records.
To enforce exclusive subtypes, copy the type indicator into each of the subtype tables and use composite foreign key constraints:
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`type` CHAR(8) NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`, `type`)
REFERENCES `mydb`.`vehicles` (`idvehicles`, `type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Next you need to restrict the value of type in each table. Unfortunately, MySQL doesn't support check constraints, so you would need to use triggers:
DELIMITER ;;
CREATE TRIGGER airplanes_insert_type_check
BEFORE INSERT ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
CREATE TRIGGER airplanes_update_type_check
BEFORE UPDATE ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
DELIMITER ;
Thus, the type indicator in the supertype table will match only one of the subtype tables' type indicators due to the trigger restrictions, and will be enforced via foreign key constraint, preventing overlapping subtypes.

What is the difference between many-to-many cross table and one-to-one cross table

Is there anything different between the two? All I see is the additional index which I don't believe fundamentally changes anything.
I would expect the first allows each t1_1 entity to be joined to multiple t1_2 entities, and the opposite as well.
For the second, I would expect each t2_1 entity to be joined to a maximum of one t2_2 entity.
But the resulting schema's generated by MySQL Workbench appear to be basically the same.
PS. Why I am doing this? Learning about super/sub tables, and went off on a tangent.
-- MySQL Script generated by MySQL Workbench
-- 08/05/15 08:12:21
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`t1_1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_1` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t1_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_2` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t1_1_has_t1_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_1_has_t1_2` (
`t1_1_id` INT NOT NULL,
`t1_2_id` INT NOT NULL,
PRIMARY KEY (`t1_1_id`, `t1_2_id`),
INDEX `fk_t1_1_has_t1_2_t1_21_idx` (`t1_2_id` ASC),
INDEX `fk_t1_1_has_t1_2_t1_1_idx` (`t1_1_id` ASC),
CONSTRAINT `fk_t1_1_has_t1_2_t1_1`
FOREIGN KEY (`t1_1_id`)
REFERENCES `mydb`.`t1_1` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_t1_1_has_t1_2_t1_21`
FOREIGN KEY (`t1_2_id`)
REFERENCES `mydb`.`t1_2` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_1` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_2` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_1_hs_t2_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_1_hs_t2_2` (
`t2_1_id` INT NOT NULL,
`t2_2_id` INT NOT NULL,
PRIMARY KEY (`t2_1_id`, `t2_2_id`),
INDEX `fk_t2_1_hs_t2_2_t2_21_idx` (`t2_2_id` ASC),
CONSTRAINT `fk_t2_1_hs_t2_2_t2_11`
FOREIGN KEY (`t2_1_id`)
REFERENCES `mydb`.`t2_1` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_t2_1_hs_t2_2_t2_21`
FOREIGN KEY (`t2_2_id`)
REFERENCES `mydb`.`t2_2` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
IMO, talking in perspective of database design (not mysql workbench)
When using 1-n relation, we mean a not null foreign key inside cross table.
When using 1-1 relation, we mean a not null foreign key inside cross table that is the or part of a unique key of cross table.
Consider tables having these records:
T1_1(A1, B1, C1)
T2_1(A2, B2, C2)
In 1-n relation, we can have (A1, A2) multiple times in T1_has_T2 table
In 1-1 relation, we can not have (A1, A2) multiple times in T1_has_T2 table.
So Achieving 1-1 could be possible by putting foreign keys inside primary key or defining a unique key(index) on combination the foreign key columns.

connecting multiple profile tables to user table

I've 3 profile tables:
-student
-teacher
-staff
All profile tables have different columns(few common columns).
These tables must be connected user table, each staff, teacher, student must be having account in user table:
user table
-id
-login
-password
-etc.
What is the best ways of connecting profiles tables to user table.
I've found one solution:
Storing User Profile as properties and values in tables
*i.e. Table to store possible options, table to store user_id, option_id and value*
-No redundant data stored, all data is relevant
-Most normalised method
-Slower to retrieve and update data
updated
Below, I've created db as #user1032531 said.
Create a super table called "people". Put all attributes in this table that are common to students, teachers, and staff.
Then create a table for students, teachers, and staff where each table's primary key is a 1-to-1 to the people table, and put unique attributes in these tables.
-- MySQL Script generated by MySQL Workbench
-- 07/30/14 05:51:12
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`people`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`people` (
`idpeople` INT UNSIGNED NOT NULL,
`name` VARCHAR(45) NULL,
`birthday` DATE NULL,
`sex` CHAR(1) NULL,
PRIMARY KEY (`idpeople`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`teachers`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`teachers` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_teachers_people`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`students`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`students` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_students_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`staff`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`staff` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_staff_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;

MySQL structure for personalized users access per site?

I need some help to structure some tables that will help me out having a good personalized way to have different access name per client with personalized allowed commands in each acess level.
So consider client A has create site Y, which he wants to create the follow access groups:
Admin (have all acess),
VIP (can access room 1),
Basic (can access louge),
Banned (cannot enter at all)
The same way client A create his personalized access I want all my other clients to be able to create their own personalized access where they can name it anything they see fit in their own language and later just put in what commands they will have access to by being on that given access level.
I have the follow tables as example (sorry that this isnt a datagram, work bench keep crashing on me when I make example and I am open to suggestion for alternatives to create datagrams as good as or better than workbench):
client TABLE:
id int,
username varchar,
password varchar,
status varchar
site TABLE:
id int,
owner_client_id,
name varchar
access TABLE:
id int,
name varchar,
commands int (bitmask?)
site_access TABLE
id int,
client_id,
site_id,
access_id
commands
id int,
action varchar,
alias varchar,
description varchar
On my application all the commands actions are alredy pre-defined and the user cannot change them in what they do or the default name, but they are allowed to create alias.
So let's say I have the command kick, they could make an alias to name it "k" or "explosion" or they could name the alias anything they want.
Some of my doubts:
Initially I tought of using site_access to link everything together, client that has access to site and what access it has and from their access what commands each have, is that a good way to go with it ?
I have many commands that will be pulled from the database but since some have their own alias I dont thin I could use a bitmask for the acess and still being able to query the alias if not null could I so I would have to use a list of commands or are there good options ?
What engine should I use, InnoDB or MyISAM in my case ?
Is it ok to mix engines or not a good idea at all ?
What should I change on my current table structure and could you provide any samples too (if possible) ?
UPDATE:
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`clients`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`clients` ;
CREATE TABLE IF NOT EXISTS `mydb`.`clients` (
`id` INT NOT NULL,
`username` VARCHAR(45) NOT NULL ,
`password` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `username_UNIQUE` (`username` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`sites`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`sites` ;
CREATE TABLE IF NOT EXISTS `mydb`.`sites` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`groups`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`groups` ;
CREATE TABLE IF NOT EXISTS `mydb`.`groups` (
`id` INT NOT NULL ,
`name` VARCHAR(45) NOT NULL ,
`alias` VARCHAR(45) NOT NULL ,
`commands` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`membership`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`membership` ;
CREATE TABLE IF NOT EXISTS `mydb`.`membership` (
`client_id` INT NOT NULL ,
`group_id` INT NOT NULL ,
PRIMARY KEY (`client_id`, `group_id`) ,
INDEX `client_id` (`client_id` ASC) ,
INDEX `group_id` (`group_id` ASC) ,
CONSTRAINT `client_id`
FOREIGN KEY (`client_id` )
REFERENCES `mydb`.`clients` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `group_id`
FOREIGN KEY (`group_id` )
REFERENCES `mydb`.`groups` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`access`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`access` ;
CREATE TABLE IF NOT EXISTS `mydb`.`access` (
`site_id` INT NOT NULL ,
`group_id` INT NOT NULL ,
PRIMARY KEY (`site_id`, `group_id`) ,
INDEX `site_id` (`site_id` ASC) ,
INDEX `group_id` (`group_id` ASC) ,
CONSTRAINT `site_id`
FOREIGN KEY (`site_id` )
REFERENCES `mydb`.`sites` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `group_id`
FOREIGN KEY (`group_id` )
REFERENCES `mydb`.`groups` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
I would do it a bit differently
Client Table
Group Table
Membership Table (Client - Group)
Site Table
Access Table (Group Site)
Also see pages 12-13 in this link for ideas http://support.sas.com/resources/papers/proceedings09/265-2009.pdf

MySQL Triggers - Implementation Issue

I am developing a MySQL database using Workbench. I want two send two fields from a newly created record to another table. I would then like to update the original table with newly created data from the second table. I was looking to implement this with triggers, unless there is a better way of course :) My attempt was a fail when I went to upload it(see below)
Specifically, I would like tc_Event to send the ID & tc_EventTags_ID to tc_EventTags to fill in tc_Tag_ID & tc_Event_ID. Afterwards I want the ID of tc_EventTags sent back to tc_Event to the tc_EventTags_ID field.
Thanks for any help.
-- -----------------------------------------------------
-- Table `mcontest`.`tc_EventTags`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mcontest`.`tc_EventTags` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`tc_Tag_ID` INT NOT NULL ,
`tc_Event_ID` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `fk_tc_EventTags_tc_Tag1` (`tc_Tag_ID` ASC) ,
INDEX `fk_tc_EventTags_tc_Event1` (`tc_Event_ID` ASC) ,
CONSTRAINT `fk_tc_EventTags_tc_Tag1`
FOREIGN KEY (`tc_Tag_ID` )
REFERENCES `mcontest`.`tc_Tag` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_EventTags_tc_Event1`
FOREIGN KEY (`tc_Event_ID` )
REFERENCES `mcontest`.`tc_Event` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
-- -----------------------------------------------------
-- Table `mcontest`.`tc_Event`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mcontest`.`tc_Event` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`date` DATE NOT NULL ,
`time` TIME NOT NULL ,
`location` VARCHAR(45) NOT NULL ,
`description` VARCHAR(45) NOT NULL ,
`tc_EventTags_ID` INT NULL ,
`tc_Orgs_ID` INT NOT NULL ,
`tc_PersonEvent_ID` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `fk_tc_Event_tc_EventTags1` (`tc_EventTags_ID` ASC) ,
INDEX `fk_tc_Event_tc_Orgs1` (`tc_Orgs_ID` ASC) ,
INDEX `fk_tc_Event_tc_PersonEvent1` (`tc_PersonEvent_ID` ASC) ,
CONSTRAINT `fk_tc_Event_tc_EventTags1`
FOREIGN KEY (`tc_EventTags_ID` )
REFERENCES `mcontest`.`tc_EventTags` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_Event_tc_Orgs1`
FOREIGN KEY (`tc_Orgs_ID` )
REFERENCES `mcontest`.`tc_Orgs` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_Event_tc_PersonEvent1`
FOREIGN KEY (`tc_PersonEvent_ID` )
REFERENCES `mcontest`.`tc_PersonEvent` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
USE `mcontest`;
DELIMITER $$
USE `mcontest`$$
CREATE TRIGGER eventTag_Trigger
AFTER insert ON tc_Event
FOR EACH ROW BEGIN
INSERT INTO tc_EventTags values('',NEW.tc_Event_ID);
END;
END$$
DELIMITER ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
Why have put a tc_EventTags_ID in table tc_Event? What is the logic behind that?
I mean that the relationship between the 2 tables would be (I guess): 1 Event - many EventTags. This is already achieved by the tc_EventTags.tc_Event_ID which is a Foreign Key to tc_Event.
To answer your question:
As it is now, the Trigger tries for every row inserted in table Event, to add a row in table EventTag. But it will fail for 2 reasons:
EventTag has 2 Constraints (Foreign keys) which have to be fulfilled for the triggered insert to succeed. So, tc_Event_ID is ok but tc_Tag_ID has to be NOT NULL and reference the Tag table but the value you supply, '', probably is not in table Tag.
EDIT: the value you supply, '', is also a CHAR while it should be INT.
But trigger will probably not be started at all, since every time you insert a row in table Event, those constraints have to be fulfilled and one of them is the tc_EventTags_ID which references EventTag table. But EventTag table is empty. Do you see the circular logic here?