Referential Integrity and Translations - oracle

Description
Hi, so I am looking at a legacy database that includes multiple translation tables for existing tables.
So there is a laws table, but then there is also a translation_laws table:
Laws (law_id, inForceDate, type, etc)
Translation_Laws (law_id, lang_code, translation)
There is also a law_type table:
Law_Type (law_type_id, description, isDecreed, etc.)
Translation_Law_Type(law_type_id, lang_code, translation)
So, with the following scheme referential integrity is maintained, but you end up with multiple translations tables.
I would prefer to make one table with the following format:
translations(table_name, id, lang_code, translation)`
This would basically be like bundle, key, lang_code, label. I could also combine bundle+key+lang_code into one varchar key: bundle.key.lang_code.
However, I don't see much of a way to define a relationship in Oracle SQL.
Questions:
Any Ideas how to define a relationship while using Integer IDs??
Would it be so bad to NOT to define a relationship in the database?
Only solution I can think of would be to try add a String foreign key to every table needing a translation (aaa.bbb.ccc.ddd) that is unique.
Update
Currently I have done away with the official relationships in the DB and made the following type of schema:
CREATE TABLE TRANSLATIONS(
DESCRIPTION_ENTITY VARCHAR(30) NOT NULL,
DESCRIPTION_COLUMN VARCHAR(30) NOT NULL,
KEY_OR_ID VARCHAR(30) NOT NULL,
LANG_CODE VARCHAR(2),
TEXT CLOB,
-- Legacy are To be able to cross check using columns - but not needed
LEGACY_TABLE VARCHAR(30) NOT NULL,
LEGACY_COLUMN VARCHAR(30) NOT NULL);
ALTER TABLE TRANSLATIONS
add CONSTRAINT UNIQUE_COMBINATION UNIQUE (DESCRIPTION_ENTITY, DESCRIPTION_COLUMN, KEY_OR_ID, LANG_CODE);
CREATE INDEX ind_description_entity ON TRANSLATIONS (DESCRIPTION_ENTITY);
CREATE INDEX ind_description_column ON TRANSLATIONS (DESCRIPTION_COLUMN);
CREATE INDEX ind_key_or_id ON TRANSLATIONS(KEY_OR_ID);
CREATE INDEX ind_lang_code ON TRANSLATIONS(LANG_CODE);
insert into TRANSLATIONS(DESCRIPTION_ENTITY, DESCRIPTION_COLUMN, KEY_OR_ID, LANG_CODE, TEXT, LEGACY_TABLE, LEGACY_COLUMN)
select 'LAW','TITLE', LAW_CODE, LANG_CODE, LAW_TITLE,
'LAW_TRANS','TITLE'
from LAW_TRANS where TITLE is not null;

Personally, I don't think there is anything wrong with not defining a relationship in a DB. At a massive investment bank where I was working before our Oracle specialists NEVER defined the relationships for performance reasons.
The basic question for your setup is, do you need a defined amount of languages or do you have to be flexible with adding languages later? If not, your approach is almost too flexible. Just adding different rows with the translation into the Laws table would be much more performant if you know you only every need 4 different languages.
Alternatively, you could just build a lock-up table:
original-string -> translated-string
And you can ignore the table name completely.

Related

How to create form/report on a table which has only primary keys?

Im trying to create a form with a report on a table that has only primary keys.
I have a table:
create table WRITE
(
author varchar(5) references AUTHOR (authorcode) ,
book varchar(20) references BOOK (bookid),
primary key(author,book)
);
I'm using APEX Application Builder to create a form on a table with report;
But When I get to the "Select the columns to include in the form" , I have no options to select from because I only have unique primary keys in my table.
Which Apex version is it? I've tried it on apex.oracle.com which uses 19.1 and it doesn't have that problem.
Anyway, two options I can think of:
temporarily drop primary key constraint
then create report + form pages
after you're done, create the primary key constraint once again
create an interactive report (using the wizard)
then create a form, manually adding items
this isn't as easy as it looks like because you'll have to create all processes as well (initialization one, along with automatic row processing)
I presume that the first option is a lot simpler.

Tables showing up with two: 'one to many' relationships in oracle sql developer

I'm looking through our data and there's a handful of tables in our oracle database that show up with two one to many relationships: http://i.stack.imgur.com/icGcV.png
I'm not sure why this would be happening, and is it something I should look into getting changed or fixed?
(I did not create this database, I am only trying to understand it!)
Too long for a comment, let's see a very simple example:
CREATE TABLE persons
(
id NUMBER PRIMARY KEY,
name VARCHAR2(10)
)
/
CREATE TABLE marriages
(
wife NUMBER REFERENCES persons(id),
husband NUMBER REFERENCES persons(id)
)
/
CREATE TABLE dogs
(
id NUMBER PRIMARY KEY,
name VARCHAR2(10),
owner NUMBER REFERENCES persons(id)
)
/
Here you have one table with two different FKs to the same table. At the same time you have another table with a single FK to the same table.
So, it's not a problem to fix, but a part of DB design to understand;
your DB can be well or bad designed, but the existence of such situations does not say anything about that.

how to create foreign key at runtime using Triggers and/or procedures in Oracle environment

I have two tables named as patient and pharmacy. Each patient is uniquely associated with one pharmacy. I want to create the foreign key constraint at run-time between these tables.
Create table patient
(patient_Id varchar2(5) primary key,
patient_name varchar2(20));
Create table pharmacy
(pharmacy_Id varchar2(5) primary key,
pharmacy_name varchar2(20);
Create table patient_pharmacy_mapper
(patient_Id varchar2(5) references patient(patient_Id),
pharmacy_Id varchar2(5) references pharmacy(pharmacy_Id));
Instead of writing the "references" at design time, Can I create/delete these foreign key constraints at run-time (when any DML statement fires)?
I know little about creating a trigger where we have to call a procedure with the "Alter table statement".
DDL statements automatically commit the transaction. As you are not allowed to commit (or rollback) in a trigger, you can not run DDL statements in a trigger (neither with static SQL nor with dynamic SQL)
The whole idea does not make sense. The only sane way to do this, is to create the FK constraints when creating the tables. You gain no security from delaying this, absolutely none.
Let me just add another vote to the others about this being a Very Bad Idea (tm). FK relationships enforce fundamental business rules. They are part of the design, to be implemented when at the same time tables are created. Any time (and I emphasize ANY time) you find yourself wanting to execute DDL at run time, you need to step back, get a cup of coffee, and reconsider.
Like the other statements I also say it is a very bad idea.
Consider, you can enable/disable constraints or you can set them deferred: SET CONSTRAINT[S]
Perhaps this is a solution for you problem.

Oracle Table structure

I have a table in Oracle Database which has 60 columns. Following is the table structure.
ID NAME TIMESTAMP PROERTY1 ...... PROPERTY60
This table will have many rows. the size of the table will be in GBs. But the problem with the table structure is that in future if I have to add a new property, I have to change the schema. To avoid that I want to change the table structure to following.
ID NAME TIMESTAMP PROPERTYNAME PROPERTYVALUE
A sample row will be.
1 xyz 40560 PROPERTY1 34500
In this way I will be able to solve the issue but the size of the table will grow bigger. Will it have any impact on performance in terms on fetching data. I am new to Oracle. I need your suggestion on this.
if I have to add a new property, I have to change the schema
Is that actually a problem? Adding a column has gotten cheaper and more convenient in newer versions of Oracle.
But if you still need to make your system dynamic, in a sense that you don't have to execute DDL for new properties, the following simple EAV implementation would probably be a good start:
CREATE TABLE FOO (
FOO_ID INT PRIMARY KEY
-- Other fields...
);
CREATE TABLE FOO_PROPERTY (
FOO_ID INT REFERENCES FOO (FOO_ID),
NAME VARCHAR(50),
VALUE VARCHAR(50) NOT NULL,
CONSTRAINT FOO_PROPERTY_PK PRIMARY KEY (FOO_ID, NAME)
) ORGANIZATION INDEX;
Note ORGANIZATION INDEX: the whole table is just one big B-Tree, there is no table heap at all. Properties that belong to the same FOO_ID are stored physically close together, so retrieving all properties of the known FOO_ID will be cheap (but not as cheap as when all the properties were in the same row).
You might also want to consider whether it would be appropriate to:
Add more indexes in FOO_PROPERTY (e.g. for searching on property name or value). Just beware of the extra cost of secondary indexes in index-organized tables.
Switch the order of columns in the FOO_PROPERTY PK - if you predominantly search on property names and rarely retrieve all the properties of the given FOO_ID. This would also make the index compression feasible, since the leading edge of the index is now relatively wide string (as opposed to narrow integer).
Use a different type for VALUE (e.g. RAW, or even in-line BLOB/CLOB, which can have performance implications, but might also provide additional flexibility). Alternatively, you might even have a separate table for each possible value type, instead of stuffing everything in a string.
Separate property "declaration" to its own table. This table would have two keys: beside string NAME it would also have integer PROPERTY_ID which can then be used as a FK in FOO_PROPERTY instead of the NAME (saving some storage, at the price of more JOIN-ing).

Do foreign key constraints influence query transformations in Oracle?

I have a situation like this:
create table a(
a_id number(38) not null,
constraint pk_a primary key (id)
);
create table b(
a_id number(38) not null
);
create index b_a_id_index on b(a_id);
Now b.a_id is in fact meant to be a foreign key referencing a.a_id, but it isn't formally declared as such. Obviously, it should be for integrity reasons. But does a foreign key constraint also improve join performance in general or in specific cases? If yes, for what types of query transformations?
Is there any relevant documentation about this topic?
I'm using Oracle 11g (11.2.0.2.0)
Yes, having foreign key constraints in place can improve query performance. There are various transforms that are open to the optimizer when appropriate foreign key constraints exist that are not generally available. For example, if you were to join A and B but only select data from B, the optimizer could eliminate A from the query plan entirely if there was a foreign key constraint in place (this sort of thing comes in very handy when you've got useful views that join in more tables than your current query strictly needs because you don't have to trade the performance costs of the extra joins against the code reuse from using an existing view). They also come in handy when you're doing things like using things like query rewrite to rewrite a query to use a materialized view in a data warehouse/ DSS type system.
Tom Kyte has a presentation Metadata Matters that talks about how various types of constraints, along with other pieces of metadata, can influence the optimizer.
As Justin already pointed out, JOIN elimination is an essential non-cost based SQL transformation, which can be applied based on the presence of meta data only. I have blogged about this more recently:
JOIN Elimination: An Essential Optimiser Feature for Advanced SQL Usage
10 Cool SQL Optimisations That do not Depend on the Cost Model
As I originally assumed, there are a lot of SQL transformations that depend on meta data, so adding foreign key constraints (and other constraints) definitely can impact performance in a positive way.

Resources