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

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).

Related

How to insert rows in phpMyAdmin

I have a database which I've opened in phpMyAdmin. I clicked the "Insert" button, which has an icon showing one row being inserted between two others.
When I actually try to insert a row, I get the following error:
1062 - Duplicate entry '294' for key 'PRIMARY'
How do I get phpMyAdmin to insert a row (presumably by increasing all the higher-numbered rows by 1) as the icon and the term "Insert" implies? It only seems to want to "Add" a row to the end, not "Insert" it.
As I said, the icon specifically shows one row being inserted between two others, and this is what I want to do. How do I get it to do what it claims it will do?
First, "INSERT" is standard SQL terminology for putting something in the database; it doesn't specifically mean "putting it between two existing values". I see how the icon can be a bit confusing, but when "insertting" data there is no difference between putting something at the end or in the middle of the database. For that matter, there's no real inherent order to data stored in a database; you can select many different ways to sort it when you display the data (and phpMyAdmin generally does a good job of guessing what's reasonable), but data just exists. You can select to sort it by the primary key or alphabetically by user name or any means you wish.
Second, your primary key shouldn't change. It's the key that holds your data together; if you start changing that your references from other tables will be messed up (see below). So don't change that.
Third, if you have your primary key set up with auto_increment (the A_I checkbox in phpMyAdmin), then you shouldn't ever need to set it or worry about it yourself. It's all managed by MySQL. If you aren't happy with the order and want to move 294 to 295 so you can insert something else at 294, then your database design needs tweaking because that's not how auto_incrementing primary keys are designed to work. As a simple solution, you may wish to create another field called "sort_value" or something that you can change.
Which all brings me to the root cause of your trouble: you're trying to create a new row while reusing an existing auto_increment value, and MySQL is smart enough to know this is a bad idea.
So as I said above, changing your primary key (whether or not it's auto generated) is a bad idea, but it may not be obvious why if you only have one table. But relational databases are designed so that you can reference tables from other tables, so for instance a customer database might have a table for "customers", "products", and "purchases" where the purchases table references the primary key ID from both customers and products...imagine the carnage your data would see if you then change the value of those keys in the customer table. You'd show customers associated with some other customer's purchases. So it might not make sense in your database, but overall that's the best way to handle things.
If you really, really don't want to change your database structure, don't reference that key from any other tables, and don't want to listen to my advice, you should be able to simply turn off the auto_increment function on your primary key and reorder them however you wish.

Why does DISABLE PRIMARY KEY CASCADE doesn't set Unique Index unusable?

can anyone explain to me why the execution of "DISABLE PRIMARY KEY CASCADE" on a PK doesn't set the corresponding unique (!) index to unusable?
As far as I know the CASCADE option should do exactly that... However, I observed differently on several occasions.
Hope some of you can help.
best regards,
daZza
The cascade option disables constraints that are dependent on this one, such as foreign keys dependent on a primary or unique constraint.
A unique index is not a constraint, although it acts as one.
In general I would advise that you create non-unique indexes to support a primary or unique key, not a unique index, for precisely this reason, and to allow constraints to be deferrable, or entirely dropped and recreated without having to recreate the index.

Entity Relation Design

I am trying to implement an entity relation for a hospital oracle database system.
I am rather confused if I should seperate the table below or merge them into 1.
- Supply
ItemNo (PK) , Name, ItemDescription, QuantityInStock, BackOrderLevel, CostPerUnit
- PharmaceuticalSupply
DrugNo (PK) , Dosage, MethodOfAdmin
Basically in my ERD, I pointed PharmaceuticalSupply to Supply as a subset which inherits the attribute but also have additional attributes. Am I wrong in doing that?
Ultimately, this is a design decision that has no right or wrong answer, but keeping them separate can be helpful. For example, there are many types of supplies that are not pharmaceutical. If you merge the tables, you make it possible to enter data that has no real meaning. For example, you can't have a dosage of bandages. The separate table makes it clear that dosage only applies to pharmaceuticals.
Note that there are a few variations on how to manage the PKs and FKs in PharmaceuticalSupply. It could have both an ItemNo and a DrugNo, where ItemNo is a foreign key. In that case, either one could be the primary key, but if DrugNo is the primary key, then ItemNo probably needs to be a unique index. However, unless DrugNo is needed due to some custom format, it might work well to simply use ItemNo as both PK and FK and completely eliminate DrugNo. This results in a "specialization" as the relational database world likes to refer to it.
It depends on your population. It it's a subset, to reduce redundancy add a foreign key to Supply. That way you'll be able to build a join that list all data.
I would still introduce a DrugNo key for indexing. Can an item number appear more than once in the PharmaceuticalSupply table ? If your do then your definitely need the DrugNo key.
PharmaceuticalSupply
DrugNo (PK) , ItemNo (FK), Dosage, MethodOfAdmin

How to create unique items in RethinkDB

How to create unique items in RethinkDB?
In MongoDb I used ensureIndex for this, eg:
userCollection.ensureIndex({email:1},{unique:true},function(err, indexName){
RethinkDB does not currently support uniqueness constraints on fields other than the primary key.
You could use an auxiliary table where the unique field is stored as the primary key in order to check for uniqueness in your application explicitly.
A relatively easy alternative would be to use a secondary index. Thus not messing with auxiliary tables.
You can than do the check in your application with the get_all method (http://rethinkdb.com/api/#js:selecting_data-get_all).

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