Check constraint to enforce referential integrity? - oracle

Can we use a check constraint to enforce referential constraint? Let's say I have a column that contains a UUID; this UUID can reference either table A or B depending on the value of a 2nd column.
------------------------------------------
|ID | Type | PK in Other Table |
------------------------------------------
|1 | Employee | 500 |
------------------------------------------
|2 | Store | 7000 |
------------------------------------------
so record #1 points to a record in the employee table, #2 points to a record in store table with the respective PK. so the goal is to enforce the referential integrity based of "Type".

Not with this data model, no.
You could have separate columns, i.e. employee_id and store_id, with foreign key constraints to the appropriate tables and a check constraint that ensures that only the correct column for the particular type is entered.
There are potentially other ways to set up the data model depending on what you're actually modeling. I'm a bit hard-pressed to think of employees and stores as separate subtypes of some higher level type. But if your actual use case is something else, it potentially makes sense to have a supertype table that is the actual parent that all the tables are children of.

Related

How can we uniquely identify a each record in Vertica database in absence of a primary key?

There are some tables in which the primary key, unique key, or composite key is not specified.
How can we uniquely identify each record in Vertica?
Vertica, in this respect, is a real relational database: If there is no declared identifier, there is no identifier.
And it is columnar.
Row based DBMSs have a way to physically identify the location of a certain row. That's where, for example, the ROWID of Oracle comes from.
Vertica being columnar, you can not even locate the actual position of the first column in the sort order:
If, for example, you have gender as the first column in the sort order, and the column is encoded as Run-Length-Encoding (RLE), then, you have, in that file that contains the column, for example, the value 'F', an integer of 502, the value 'M' and an integer of 498 for a table containing 1000 rows.
You could calculate the hash of all columns (with a small risk of hash collisions), but if you have two rows like this:
42 | Arthur Dent | 2022-01-25
42 | Arthur Dent | 2022-01-25
There is now way of discerning one row from the other.
Even if you apply a
ROW_NUMBER() OVER(PARTITION BY <all_columns_of_the_table> )
which would lead one of the above rows to get a 1 and the other to get a 2- there will be no way of determining which was assigned to which row.
These are the two, not completely satisfactory, ways of working around this behaviour. Which is not a problem, but a behavioural feature.

create a table with composed primary keys

I have a table:
course
---------
id_course
id_groupe (references a table named group)
id_module (references a table named module)
In my case a course can be shared by many groups.
My question is :
it is correct to choose the primary key composed of (id_course , id_group )?
and is there any other way to make the same table ?
Lets assume that the course has another attribute - its title.
Ask yourself the question:
Will the title of the course change if it is being taken by a member of "group A" or "group B"?
For most institutions, a course will have a set title and it does not matter who is taking that course so with your table structure you will have to duplicate the title across every course/group combination and breaks the concept of database normalisation.
You would be better splitting the table into two tables:
course
---------
id_course (Primary Key)
title
course_group
------------
id_course (FK referencing course) } composite PK
id_groupe (FK referencing groupe) }
Then you can set the title for the course and it is independent of the groups associated with the course. You can, of course, have a composite primary key on the course_group table consisting of both ids to enforce uniqueness.
If you have a course that may be shared by many groups, I'd think of a sligthly different design, with a relation table linking COURSE and GROUPE; this table could have a composite PK, based on the two foreing key columns:
COURSE
id_course PK
id_module KF references MODULE
MODULE
id_module PK
GROUPE
id_groupe PK
COURSE_REL_GROUPE
id_course FK references COURSE
id_groupe FK references GROUPE
PRIMARY KEY (id__course, id_groupe)

Laravel many to many model relationship

I have a table called jobs and another table called job_questions - a job can have five screening questions. Table job_questions is a type of lookup table but with some additional data as follows:
job_questions
-------------
job_id int
question_id int
question varchar
expected_answer enum ('y', 'n')
job_id | question_id | question | expected_answer
--------------------------------------------------------------
1 | 1 | Do you have experience | Y
There is no table called questions - question_id merely refers to question numbers on a form (1-5) How would you map such a model in laravel since you dont normally have a many to many model class in laravel? Do i create a model class for the lookup table, otherwise I how would i pull the additional information it contains?
If one question can be in multiple jobs, you indeed have a many to many relationship.
You're gonna need one table for jobs and one table for questions to represent the data. To actually make a relationship, you're gonna need a pivot table. Basically it's gonna have a job_id and a question_id, so if job 3 has questions 1, 2 and 3, there will be three rows in this table with the job_id 3 and the three question_id.
You don't need a model for this pivot table, just a model for the two actual data.
In your models, the relationship functions don't change much. Both have the many word: return $this->belongsToMany('App\Job', 'pivot_table_name', 'question_id_column', 'job_id_column'). You also may put this method in the other model so you can query the relationships both ways, question's jobs and job's questions. Parameters 2 and on to the belongsToMany are optional but you'll probably need at least the second to set the pivot table name.
Docs to this is here:
http://laravel.com/docs/5.0/eloquent#many-to-many
and
http://laravel.com/docs/5.0/eloquent#working-with-pivot-tables

Oracle 11g Reference Partitioning and Indexes

I have a parent table containing the following columns:
- PARENT_ID: UUID
- EVENT_DATE: TIMESTAMP
- DATA_COLUMN1: VARCHAR2(255)
- DATA_COLUMN2: VARCHAR2(255)
The table is range partitioned by EVENT_DATE. Data is only retained for a month and the last partition is dropped on a daily basis.
Following my understanding, using a global index for PK would result in sub-standard performance when dropping a partition. This means that the PK of this table has to be based on both PARENT_ID + EVENT_DATE in order to create a local index.
I have a second table that is the child of the first (via one-to-many relationship). It has the following columns:
- CHILD_ID: UUID
- PARENT_ID: UUID - FK into parent table
- DATA_COLUMN3: VARCHAR2(255)
- DATA_COLUMN4: VARCHAR2(255)
To partition the child table, I decided to use reference partitioning. One of its big advantages: it removes the need to duplicate the partition key in the child table. However, based on my reasoning, the only way to achieve this is through global indexes. Here is my train of thought:
For the unique index of the parent table to be local, the PK must include the partition key, e.g. EVENT_DATE.
A foreign key constrain cannot reference only part of the PK. Thus the child table must include both PARENT_ID and EVENT_DATE columns.
What's more, I also read that "When using reference partitioning, most child table indexes
should be defined as global, unless there is a compelling reason
for a given index to be defined as local." (http://www.nocoug.org/download/2010-05/Zitelli-Reference_Partitioning_NoCOUG.pdf).
Am I missing something or is there no way to use reference partitioning without having global indexes or duplicating data?
An explanation on how reference partitioning works with local/global indexes will be much appreciated!
You understand correctly. if you want to create a reference partition you need to define a valid FK. in your case - both parent_id and event_id needs to be present in the child table.
Ref partitions are for cases when you want to partition a table according to a column not in the PK those not in the child table. this is not your case - you can apply range partition on both tables and gain max pruning.
The event_date in the child table is not redundant - it's required by the model - you need data_columns 3/4 in the child table for each instance of parent_id + event_date.
Regarding the local indexes on a child table in a ref partitioned table - my logic say exactly the opposite. if i have a ref partition i'm aiming at max pruning which means that i want as less partitions as possible to be accessed in each query. in this case i would want local indexes and not global.
You said "using a global index for PK would result in sub-standard performance when dropping a partition". when you drop a partition from the table all global indexes will be invalidated and you will have to rebuild them. this is the only performance impact regarding DDL changes. PK on a partitioned table must be global so you don't have a choice here any way.
Though above answer has been answered but on you thought: 'A foreign key constrain cannot reference only part of the PK. Thus the child table must include both PARENT_ID and EVENT_DATE columns.'
I believe FK can refer to part of PK if your attribute has been defined with Unique constraint & I see that possible in your example.
Example:
Table A ( orderid, orderdate, custid)
PF -> OrderID, OrderDate
Table B(OrderID, ItemID)
In table B, orderID can be FK if OrderID is defined as Unique in Table A.
I hope this helps.

How to have unique primary key in two tables?

I have two tables in my system EMPLOYEE and EMPLOYEE_FORECAST. Both have the same columns, entire structure is same. I have another archive table with same structure called EMPLOYEE_ARCHIVE table.
I need to put data from both tables to this archive table. Since records in EMPLOYEE and EMPLOYEE_FORECAST may have same primary key e.g. a record in EMPLOYEE will have a pk of say 100 and another record in EMPLOYEE_FORECAST may also have pk of 100 and this will definitely happen so when they are inserted into archive table I will have a duplicate primary key.
The problem is I will also have some relation table like employee_products, employee_forecast_products and also employee_archive_products. These tables will have emp_id and product_id. So with same emp_id I wont be able to figure out the exact employee.
So, is there any way to have a unique primary key both the EMPLOYEE and EMPLOYEE_FORECAST tables.
So you cannot not use the PK column of EMPLOYEE table as a PK column of the archive table.
You can add a new PK column to the archive table.
If, for some reason, you want the EMPLOYEE table's PK column to be the PK in the archive table, then you could add a flag column to the archive table which would indicate from which table the record comes from. And you could have a composite PK in the archive table containing the original PK and the flag column. (In general, I discourage composite PK-s, so, even if you want to have this flag column, you could have an additional normal PK column in the archive as well.)
To expand on my comment, set up you archive table as:
EMPLOYEE
EMPID NUMBER PK
EMPNAME VARCHAR2(30)
...
EMPLOYEE_FORECAST
EMPID NUMBER PK
EMPNAME VARCHAR2(30)
...
EMPLOYEE_ARCHIVE
ORIG_TABLE VARCHAR2(30) PK
EMPID NUMBER PK
EMPNAME VARCHAR2(30)
...
Data in EMPLOYEE_ARCHIVE:
ORIG_TABLE EMPID EMPNAME
------------------------------------
EMPLOYEE 100 JO BLOGGS
EMPLOYEE_FORECAST 100 JO BLOGGS
As the archive table PK is across both the original table and empid columns it will remain unique for all your data.
Obviously this is just an example and you can use whatever derived column you want to enforce the uniqueness in your archive table.
Hope it helps...
Create a Common Super-Table. Make another table EMPLOYEE_ID with only a primary key. Let both EMPLOYEE, EMPLOYEE_FORECAST and EMPLOYEE_ARCHIVE reference it.
Your data model seems a tad confused. If EMPLOYEE and EMPLOYEE_FORECAST have identical structures why have two tables? What is the business rule here?
And if they are supposed to be two separate tables why store them in a common archive table? Why not have separate archives for each table?
I agree with #Ollie. You need to rethink your data model so it clearly expresses how your business operates. If you post your business rules here I'm sure we can help you untangle things. But here is probably the crucial question: do the following keys identify one employee (i.e one person in the real world) or two?
employee.emp_id = 100
employee_forecast.emp_id = 100

Resources