Rails: creating column references without foreign keys - mysql

In Rails 4 models, I want to model an employee-department relationship. An employee belongs_to a department and a department has_many employees. Can I create a department_id reference in the employee table without making it a foreign key?
The reason I want to do this is that I suspect this impacts the record-locking behavior in MySQL, which is the database I am using, and it may be causing random errors when I perform concurrent updates from multiple threads in my Rails application.

Yes you can. If you're using Rails 4.2 and using references or add_reference within your migrations, just set the :foreign_key option to false.
You can also take the approach described by #user1063998 and just add an integer column called department_id to your employees table although in that case, I would recommend also adding an index for this column.

Rails by default does not add a foreign key constraint at the database level.
Using a migration you can simply add an integer column to the employee table called department_id. If you need to mimic the behaviour of a foreign key constraint, you can use validations on the model.

Related

IS_A relationship primary key validation rules

So I am building a database for a police station in access. I have a reports super-class that is divided into several sub-classes.From what my books tell me the supper-class should be the one with the "ID" that is the primary key
and that the ID should be passed onto the sub classes so that there are no 2 sub-classes with the same ID .How do I make a validation rule that doesn't allow to make a new sub-clas report if that ID doesn't exists or is being used by other sub classes
There is no way insertion in a table can check whether that primary key is present in another table apart from either forcing this constraint through business rule or by using DB Trigger.
You need to analyse your DB Model again and try to identify a good design.

Mysql Multiple Foreign Key for a attribute in table

I want to design a database for e-learning. Here is the case.
"Each subject has 2 hierarchy i.e. ScoringComponent and Competency.Each hierarchy is updated every period. Each hierarchy has unlimited depth-level. The lowest level of the ScoringComponent should be mapped to one or more lowest level of competency hierarchy."Relation between the ScoringComponent and Competency Image
Based on the case, i tried to design the database. The result is like Database Design.
The issue in the database design is the multiple Foreign Key for Year-Period Attributes.
From this issue, i want to create the table without Foreign Key and handle the data validity in the application code.
Is it okay for me to remove the Foreign key from the table? and is there any suggestion for my case?
Thank you.
I would not move away from using a foreign key in your table, if you need it.
Are you the only one that will know how the data is arranged in the database?

Replace primary key that is foreign key in other tables

I am currently rebuilding a database which is used to store patient records. In the current database, the primary key for a patient is their name and date of birth, (a single column, ie "John Smith 1970-01-01", it is not composite). This is also a foreign key in many other tables to reference the patients table. I am planning to replace this key with an auto-generated integer key (since there will obviously be duplicate keys one day under the current system). How can I add a new primary key to this table and add appropriate foreign keys on all the other tables? Keep in mind that there is already a very large amount of data (~500,000 records) and these data references cannot be broken.
Thanks!
If up to me..
Add a new future-PK column as a non-null unique index (it must be a KEY, but not necessarily the PK) with auto_increment.
Add the appropriate new-FK columns to all the related tables, these should be initially nullable.
Set the new-FK value to the appropriate future-PK value based on the current-PK/FK relationships. Use an "UPDATE .. JOIN" for this step.
Enable the Referential Integrity Constraints (DRI) on the relevant tables. It only needs to be KEY/FK, not PK/FK, which is why the future-PK can be used. Every existing DRI constraint using the current-PK should likely be updated during this step.
Remove the new-FK column nullability based on modeling requirements.
Remove any residue old-FK columns as they are now redundant data.
Switch the old-PK and the new/future-PK (this can be done in one command and may take awhile to physically reorganize all the rows). Remove the old PK column as applicable, or perhaps simply remove the KEY status.
I would also offline the database during the process, review and test the process (use a testing database for dry-runs), and maintain backups.
The Data-Access Layer and any Views/etc will also need to be updated. These should be done at the same time, again through a review and testing process.
Also, even when adding an auto-increment PK, the table should generally still have an appropriate covering natural key enforced with unique constraints.
I solved the problem using the following method:
1- Assigned added a new primary key to the patients table and assigned unique values to all existing records
2- Created materialized views (without triggers) for each of the referencing tables that included all fields in the referencing table as well as the newly created id field in the patients table (via a join).
3- Deleted the source referencing tables
4- Renamed the materialized views to the names of the original source tables
The materialized views are now the dependent tables.
A reference for materialized views: http://www.fromdual.com/mysql-materialized-views

Possible to Fix a Foreign Key in Yii without having set it up in the Database?

I'm using phpMyAdmin for my database GUI and it's connecting to Yii Framework on my website.
I wish for my products table for instance, to have a foreign key department_id which is a reference to the id field of my departments table. Unfortunately, I don't currently have the facility to set the foreign key up properly in phpMyAdmin, so department_id is just an indexed field. I cannot change the configuration of phpMyAdmin at the moment so it's stuck like it is without a foreign key and relationship facility.
Is there a way to modify the Models of these tables in Yii so they link? I know there is a relations function inside the Model Class file that holds this information:
return array('department_id' => array(self::BELONGS_TO, 'Departments', 'id'),
Could I not just add something similar to the above? Is there more legwork? Is it now fixed (as in static, not corrected) because of phpMyAdmin?
Cheers
If I'm not mistaken, you don't need to have mySql enforcing foreign key relationships for them to still work in Yii. Setting up FK constraints in mySql ensures proper database integrity, but I don't think Yii actually uses that at runtime.
When initially running yiic (of Gii) to build the project I think it looks at the DB to build the right relations in the Model, but it doesn't use them after that.
Yii then uses this knowledge (from yiic) of the table relationships to make your life easier by providing shortcut methods to access relational data, and to ensure you don't violate mySql constraints and get ugly SQL errors, etc. But you can still use Yii relation logic without the underlying SQL constraints. The only problem will be that if Yii messes up and assigns a non-existing FK or something, your database will not catch this error (your data integrity will be more error prone).
To link your products to departments, just make sure you have a department_id field in the Product (which it sounds like you do). Then add a relation rule like so to Product:
'department' => array(self::BELONGS_TO, 'Department', 'department_id'),
And in your Department model:
'products' => array(self::HAS_MANY, 'Product', 'department_id'),
Now you should be able to use the relation like normal:
$myProductModel->department; // returns the model of the Department referenced
$myDepartmentModel->products; // returns the models of all Products in the department
Good luck, and let me know if I am way off base and it doesn't work for you!

How to relate two tables without a foreign key?

Can someone give a demo?
I'm using MySQL,but the idea should be the same!
EDIT
In fact I'm asking what's the difference between Doctrine_Relation and Doctrine_Relation_ForeignKey in doctrine?
I suspect what you are looking at would be to be map columns from one db table to another db table. You can do this using some string comparison algorithm. An algo like Levenstein or Jaro-Winkler distance would let you infer the "matching" columns.
For example, if db1.tableA has a column L_Name and db2.tableB has a column LastName, a string distance match would fetch you one measure. You can extend that by comparing the values in the rows to check if there is some consistency for example if the values in both tables contains: "Smith"s, "Johnson"s etc. you have a double-win.
I recently did something similar, integrating multiple large databases (one of them in a different language - French!) and it turned out to be quite a great experience.
HTH
You should use foreign keys to relate tables in MySQL, because it does not offer other ways to create relationships (such as references or nested tables in an object-oriented database).
See:
http://lists.mysql.com/mysql/206589
EDIT:
If you are willing to use Oracle, references and nested-tables are alternate ways to create relationships between tables. References are more versatile, so here is an example.
Since references are used in object-oriented fashion, you should first create a type and a table to hold objects of that type.
Lets create an object type of employee which has a reference to his manager:
CREATE TYPE employee_type AS OBJECT (
name VARCHAR2(30),
manager REF manager_type
);
We should also create an object type for managers:
CREATE TYPE manager_type AS OBJECT (
name VARCHAR2(30),
);
Now lets create two tables, one for employees and other for managers:
CREATE TABLE employees OF employee_type;
CREATE TABLE managers OF manager_type;
We can relate this tables using references. To insert an employee in employees table, just do this:
INSERT INTO employees
SELECT employee_type('Bob Jones', REF(m))
FROM managers m
WHERE m.name = 'Larry Ellison';
More info: Introduction to Oracle Objects
Well you could get around that by taking care of relationships in a server side language. Some database abstraction layers can handle this for you (such as Zend_Db_Table for PHP) but it is recommended to use foreign keys.
MySQL has InnoDB storage engine that supports foreign keys and also transactions.
Using a foreign key is the standard way of creating a relationship. Alternatives are pretty much nonexistent, as you'd have to identify the related rows SOMEHOW.
A column (or set of columns) which links the two tables IS a foreign key - even if it doesn't have a constraint defined on it (or even an index) and isn't either of the tables' primary key (although in that case you can end up with a weird situation where you can get unintended cartesian products when joining, as you will end up with a set vs set relationship which is probably not what you want)
Not having a foreign key constraint is no barrier to using a foreign key.