Foreign key, or no foreign key? Defining Laravel relationships - laravel

What is the difference between defining a foreign key VS just creating an integer column named user_id?
// create_posts migrations
$table->integer('user_id')->unsigned();
// vs
$table->foreign('user_id')->references('id')->on('users');
Can they be used interchangeably? What purpose do each one serve? Which is considered a best practice, first or second definition?
Edit
The command $post->user() will work either ways, so what advantages does usage of a foreign key bring?

$table->integer('user_id')->unsigned();
// Above command is creating a column in database and it is required to have the required table structure
$table->foreign('user_id')->references('id')->on('users');
// Above command is creating foreign key index and making reference to id in users table.
As you can see from command explanations they can't be interchangeable, you need first command to have second command without first second command would complain.
Best practise is to use both of them together.
Few of advantages are listed below:
You can implement cascade update/delete.
Database level validation that only valid values of user_id is recorded ( to avoid some one entering 999999 which might be invalid or non existing user_id).
Above two are main advantages and you can express multiple scenarios how above two can be life saviour.
Let's say in post table by human error or bug in script makers user_id = 9999. What you think $post->user() will do?
Unless you can have a post without any reference to user you can see there could be multiple logical issue you may find if foreign keys are not used.
Think of foreign keys as enforcing relations and taking care of post if user is removed / deleted from db.

No, They can't be used interchangeably and each one has its usage. Use index when you want to define index on column, means database index, see here. But when you define a foreign key it set a index to that column (for searching, ...) and also make a relation between user_id and id column in user table, so if there is a user by id 10, then you can use user_id = 10 on another table. Also it has another benefits such as making sure your data are integrated. For example you can't delete user by id 10 if there is article that belongs to this user. For more information see this.

The first line, will only create a user_id column not something special,
while the other line will create a column as a foreign key which will be tightly coupled with id column of users table, this will create some limitations.
read about foreign key reference

For the best practices I always use:
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
Don't mix the definition of index with foreign key, they don't mean the same.

Related

is bad habit to don't use foreign in migration laravel?

I am new in laravel. In my tutorial video teacher use foreign in migration but,i can create my relationships without it and use just belongTo and hasMany.When i use foreign can not delete one post easily (error is you can not delete because parent foreign has child ......).
my question is my way is good or not? and why?
Thank you all
Your way is good but I think foreign keys are better. Had you not had that foreign key, you would have deleted the post but all that post's children (referred to as orphans because they no longer have a parent) would have stuck around. In order to get around the foreign key error, you would need to first delete all the children for that post, and then delete the post.
The good news is foreign keys can also do this for you so you don't need to worry about keeping track of all the children. When you setup the foreign key, if you add the on delete cascade clause, when deleting the post, the database would automatically remove all of the posts's children for you and deleting a post without first deleting the children would no longer result in an error.
If it's your preference to keep the children around even when the post is deleted, you can use on delete set null instead which would simply set the children's foreign key to null rather than delete the record.
This is all useful for enforcing data integrity (databases should contain only accurate and valid data).
The answer really is not 'is this good practice in Laravel' so much as 'is this good practice for database management'.
There are many articles on the topic as to the good and bad side of using foreign keys. Here is a good explanation on the DBA stack exchange
https://dba.stackexchange.com/questions/168590/not-using-foreign-key-constraints-in-real-practice-is-it-ok
My personal preference is to use them to maintain data integrity. The real power comes in adding cascading deletes to the relationship (if applicable to your design).
It really comes down to how good you want your database to be.The main reasons to use foreign keys in your database are
To prevent actions that would destroy links between your tables
This would prevent the invalid data from being inserted to the foreign key column as it has to point to a existing value
Also defining foreign keys makes your query faster depending on database I don't know the exact milliseconds but if I find it out I will post it.
Well from the laravel point of view the way you do is a better way as this is how one of the main teacher of the Laravel(Jeffrey Way) teaches in the getting started with laravel series.
Foreign Keys are the way to define relationship between tables in your database whereas Laravel belongsTo() or hasMany() is a way to define relationship between tables in Laravel

Changing Primary Key in Oracle

I'm updating a table that was originally poorly designed. The table currently has a primary key that is the name of the vendor. This serves as a foreign key to many other tables. This has led to issues with the Vendor name initially being entered incorrectly or with typos that need to be fixed. Since it's the foreign key to relationships, this is more complicated than it's worth.
Current Schema:
Vendor_name(pk) Vendor_contact comments
Desired Schema:
id(pk) Vendor_name Vendor_contact comments
I want to update the primary key to be an auto-generated numeric key. The vendor name field needs to persist but no longer be the key. I'll also need to update the value of the foreign key on other tables and on join tables.
Is the best way to do this to create a new numeric id column on my Vendor table, crosswalk the id to vendor names and add a new foreign key with the new id as the foreign key, drop the foreign key of vendor name on those tables (per this post), and then somehow mark the id as the primary key and unmark the vendor name?
Or is there a more streamlined way of doing this that isn't so broken out?
It's important to note that only 5 users can access this table so I can easily shut them out for a period of time while these updates are made - that's not an issue.
I'm working with SQLDeveloper and Python/Django.
The biggest problem you have is all the application code which references VENDOR_NAME in the dependent tables. Not just using it to join to the parent table, but also relying on it to display the name without joining to VENDOR.
So, although having a natural key as a foreign key is a PITN, changing this situation is likely to generate a whole lot of work, with a marginal overall benefit. Be sure to get buy-in from all the stakeholders before starting out.
The way I would approach it is this:
Do a really thorough impact analysis
Ensure you have complete regression tests for all the functions which rely on the Vendor data
Create VENDOR_ID as a unique key on VENDOR
Add VENDOR_ID to all the dependent tables
Create a second foreign on all the dependent tables referencing VENDOR_ID
Ensure that the VENDOR_ID is populated whenever the VENDOR_NAME is.
That last point can be tackled by either fix the insert and update statements on the dependent tables, or with triggers. Which approach you take will determine on your application design and also the number of tables involved. Obviously you want to avoid the performance hit of all those triggers if you can.
At this point you have an infrastructure which will support the new primary key but which still uses the old one. Why would you want to do this? Because you could go into Production like this without changing the application code. It gives you the option to move the application code to use VENDOR_ID across a broader time frame. Obviously, if developers have been keen on coding SELECT * FROM you will have issues that need addressing immediately.
Once you've fixed all the code you can drop VENDOR_NAME from all the dependent tables, and switch VENDOR_NAME to unique key and VENDOR_ID to primary key on the master table.
If you're on 11g you should check out Edition-Based Redefinition. It's designed to make this sort of exercise an awful lot easier. Find out more.
I would do it this way:
create your new sequence
create table temp as select your_sequence.nextval,vendor_name, vendor_contact, comments from vendor.
rename the original table to something like vendor_old
add the primary key and other constraints to the new table
rename the new table to the old name
Testing is essential and you must ensure no one is working on the database except you when this is done.

Oracle data modeler logical design unique constraint

How can I define column to be unique when creating logical model? It's because I want to create relationship 1:N and both columns are not primary key. I tried to define surrogate keys when defining relationship and typed column names in field Name of source/target, but when creating relational model, I don't get what I want.
So basically I want define which columns from tables go into relationship and define unique constraint over column with multiplicity 1.
I found that I can set up Unique Constraints in the Relational Model in the Table Properties. There is an item in the list called "Unique Constraints" name the Constraint and then add the column. After that click the check box to generate the DDL for the constraint.
just use the UNIQUE constraint.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm
BTW, why are you using a FK that does not reference the PK? You might need to do this, but you might also consider refining your conceptual model so that the reference can refer to the PK.

Are there any reason to use both primary key and unique key together on the same field?

I am analyzing an Oracle database design and I am perplexed at seeing both unique keys and primary keys on the same fields. These unique-primary key pairs are consistently created on all tables. I see no reason to do this.
If I have a primary key anyway, is there a good reason to create an additional unique key on the same field?
For a table resolving a many-to-many it would be common to have a two part key (as indicated by Quassnoi). It is also quite likely to need indexes supporting access through either parent.
If you have, for example, PERSON, ADDRESS and PERSON_ADDRESS tables, your PERSON_ADDRESS table may have the primary key of (PERSON_ID, ADDRESS_ID) and a supporting index. You would also have another index on (ADDRESS_ID,PERSON_ID), and you would likely make this a UNIQUE index (as it is a unique combination of fields).
It is also possible that your DBA has some particular way of generating tables that starts with a UNIQUE index on the primary key fields followed by the creation of the PRIMARY KEY constraint. That may show up in some GUI tools in the way you suggest.
No, there is no reason to have it also as unique; when you set a column as PK you are sure that:
No NULL will be accepted for that column on INSERT or UPDATE;
Values in the whole table for that column are always UNIQUE;
so just PK is enough. Since there is a UNIQUE index for the PK column, by definition, there is no need to add any other index on that column only because queries will use the PK index whenever only that column is affected.
I believe it's impossible (PK and unique constraint on the same column[s])...
You cannot designate the same column or combination of columns as both a primary key and a unique key.
(from here, section "Restrictions on Primary Key Constraints"). Isn't it?
Oracle won't let you create multiple UNIQUE and PRIMARY KEY constraints on the same field set in the same order and will fail with ORA-02261.
If you have composite keys, you can create PRIMARY KEY on the column set in one order (PRIMARY KEY (a, b)) and a unique constraint on another (UNIQUE (b, a)).
This will parse and execute, however a single index will be used to police both constraints so it makes no sense.
Could you please post the table scripts?
Just a little theoretical background here... When modeling your table, you identify a set of keys. These keys are logically equivalent, but for practical purposes you pick one of them and call it "primary" while the rest of them become "alternate".
(In DDL SQL, a primary key is called "PRIMARY KEY", while "alternate key" is called "UNIQUE constraint".)
So, in light of that, your question is equivalent to: "is there a good reason to have two identical keys", and the answer is: "no".
That being said, you may have overlapping keys (i.e. keys that share some fields but not all), but this is usually a sign of a bad design... and the answer is: "probably not".
OTOH, if by "unique key", you actually mean "unique index", then yes, you need both of them.
Index is not a logical constraint - it is there just to allow a logical constraint such as PRIMARY KEY to perform well (and for querying, but that's a different topic).

Surrogate key in 'User' / 'Role' tables for desktop app? Whats the purpose?

I have to add some security for a C#/.NET WinForms/Desktop application. I am using Oracle DB back-end.
The tables are simple: User (ID,Name), Role(ID,Role), UserRole(UserID,RoleID).
I am using the windows account name to populate User table. Role table will for now just be simply 'Admin','SuperUser','BasicUser'...
Since no two people could ever possible have the same windows account name... even when I do not control these name management (netops does, hence why I want to use windows accounts so I don't have to manage it ;)). For Role table, I should again never have dupe value - I control the input, there will only be 3 (tactical app going away within year). UserRole is a join table to represent the Many-To-Many relationships of users and roles, so no surragate key is justified.
Simple question - Why bother with 'ID' (int) in the User and Role table? Any point or advantage here? Is this one of those 'I've always done it this way' type things? Or have I just not done this in awhile and forget the reason?
Names change - primary key values must not. Abigail Smith becomes Abigail Jones and the username changes but a surrogate key protects against having to cascade those changes everywhere.
If you are using a surrogate key but there is a column or combination of columns which should be unique, then enforce that using a unique index. There's a good chance you'll want indexes on your user.name and role.role columns anyway, and a unique index is more space efficient and supplies useful metadata to the optimizer. If you have a surrogate key but don't have another combination of columns that uniquely identify a row then think again whether you have your entity definition right.
One caution. Especially for very narrow tables with few access paths, you may use an index-organized table. Oracle will only allow an index organized table on the primary key, but does allow foreign keys against a unique set of columns (if it is enforced by a unique constraint, not simply a unique index).
It is possible that you'll end up with a table where a unique ID is enforced through a unique index and treated as PK by an ORM and used as the parent for foreign key relationships, but the primary key (as defined in the DB) is the rolename/username/whatever because you want that as the driver for an index-organised table.
A surrogate key is not required on intersection tables, but here are a few reasons to do so:
Consistency: If every table has a single artificial key, you always know the key name when you know the table name.
Ease Of Use: Less typing — one key means ON and WHERE clauses are shorter and thus less error-prone.
Interoperability: Some ORMs only work well with tables with a single primary key column.

Resources