AXMLS database schema - default values and foreign keys - adodb

I am developing a package for Concrete5 that uses AXMLS format to specify the database schema.
http://www.concrete5.org/documentation/how-tos/developers/creating-and-working-with-db-xml-files/
Here is the schema:
<?xml version="1.0"?>
<schema version="0.3">
<table name="notificationCategory">
<field name="id" type="I"> <!-- integer -->
<key/>
<autoincrement/>
</field>
<field name="name" type="C" size="255"> <!-- varchar(255) -->
</field>
<field name="created" type="T">
<deftimestamp/>
</field>
<field name="modified" type="T">
</field>
<opt>
Type=InnoDB
</opt>
</table>
<table name="notificationEntry">
<field name="id" type="I"> <!-- integer -->
<key/>
<autoincrement/>
</field>
<field name="name" type="C" size="255"> <!-- varchar(255) -->
</field>
<field name="cat_id" type="I">
</field>
<constraint>
ADD CONSTRAINT `cat_id_ibfk_1` FOREIGN KEY (`cat_id`) REFERENCES `notificationCategory`.(`id`) ON DELETE CASCADE
</constraint>
<opt>
Type=InnoDB
</opt>
</table>
</schema>
I am struggling with two things:
Foreign keys. The result of the following is a table NotificationEntry where foreign key does not get set (it is using InnoDB)
Default values for created and modified field. I want created to have a default value of the current date, while for modified I'd like to have ON UPDATE CURRENT_TIMESTAMP
show create table notificationCategory;
CREATE TABLE `notificationCategory` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
There is very little documentation available for this format, did anyone have success using it?

As per the MySQL documentation, you don't use ADD CONSTRAINT when you're creating the table:
http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
Second, all <constraint> definitions need to be inside the <field> definitions as per ADOdb documentation:
http://adodb.sourceforge.net/docs-datadict.htm
Additional constraints defined at the end of the field definition.
Third, the constraint definition needs a comma in front of it because it is concatenated at the end of the CREATE TABLE block so the generated MySQL would be invalid without the comma. I'm not sure whether this is documented anywhere but the PostgreSQL example on the ADOdb documentation page shows a comma in front of the statement.
So, your field definition and constraint should look like this:
<field name="catID" type="I">
<constraint>
, FOREIGN KEY (catID) REFERENCES NotificationsNotificationCategory(catID) ON DELETE CASCADE
</constraint>
</field>
And few more suggestions:
Follow the naming conventions for the database tables and columns set by the
concrete5 core. You can easily figure these out by exploring the core database tables.
Table names in CamelCaseFormat (note the starting capital letter). Only exceptions to
this rule are BlockType tables (starting with bt) and AttributeType tables
(starting with at).
Name your primary key names following the core conventions. E.g. the primary key for
the Collections table is cID and the primary key for the Files table is fID.
Try to avoid possible conflicts with the core primary keys when naming your fields,
e.g. instead of using "cID" as the name for your category table, use "catID" like you
had already suggested.
Use camelCaseFormat (note the lower starting letter) also in the field names
just like any other table in concrete5.
Always prefix the database table names with your package handle in CamelCased format.
E.g. if your package's handle is "notifications", you would create database tables
named NotificationsTableName
Following these conventions keeps your code clean and allows easy reading for any possible future developers that are already familiar with concrete5 and might explore your code. Although you would not agree with all the conventions, it is better to follow them than to let every developer reinvent the wheel every time.

Related

SQL datatype to store 8000 characters in a column and should also be a primary key

I need a column which should store more than 4000 characters(to be exact: between 4000 to 8000). And I want that particular column to be a primary key. Since I have dependency in UI end for that particular column to be primary key.
I tried CLOB and varchar(max) but those datatypes doesn't allow primary key property.
Can anyone help me with a proper datatype which can satisfy both conditions?
I'm using Oracle SQL developer 18.3.0.277
You cannot specify a primary key or unique constraint on a CLOB column. If you try then you get the exception:
ORA-02329: column of datatype LOB cannot be unique or a primary key
You can have a composite primary key with two VARCHAR2(4000) columns:
CREATE TABLE table_name (
value_start VARCHAR2(4000),
value_end VARCHAR2(4000),
CONSTRAINT table_name__value__pk PRIMARY KEY (value_start, value_end)
);
Or, from Oracle 12, you can set the system setting MAX_STRING_SIZE to be extended and can use:
CREATE TABLE table_name (
value_start VARCHAR2(8000) PRIMARY KEY
);
However
I would question the design choice of using a VARCHAR2(8000) column as a primary key as you will need to duplicate the (large) column value in all the referential constraints. Instead, make the value UNIQUE and provide a IDENTITY column which can act as the primary key with a one-to-one correspondence to the large string values.

Can I use the tag column of fnd_lookup_values to store custom information?

I need to create a new lookup code in fnd_lookup_values and add additional information to the code. Oracle suggests that we can use arrribute1...attribute15 columns. But to use attribute1..15 columns, we need to do extra steps like creating DFF and attaching it to the current lookup code.
But also there is a tag column:
create table FND_LOOKUP_VALUES
(
lookup_type VARCHAR2(30) not null,
language VARCHAR2(30) not null,
lookup_code VARCHAR2(30) not null,
...
attribute1 VARCHAR2(150),
...
attribute14 VARCHAR2(150),
attribute15 VARCHAR2(150),
tag VARCHAR2(150)
...
Is it safe to use it in a custom oracle-ebs application to store additional information for lookup codes?
Yes, it is safe to use the tag column for custom purpose as there isn't any Oracle standard functionality depending on it.
The EBS online help reads:
Tag: Optionally enter in a tag to describe your lookup. The tag can be used to categorize lookup values.
Regards,
Andy

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.

Referential Integrity and Translations

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.

Oracle Foreign or Primary keys

I'm a bit confused over when I should use a primary or foreign key. I have two tables, and in both of them, some of the columns reference columns that are primary keys in other tables.
Here they are:
CREATE TABLE roles (
movie_id NUMBER(10,0) NOT NULL REFERENCES movies(movie_id),
actor_id NUMBER(10,0) NOT NULL REFERENCES actors(actor_id),
movie_description VARCHAR2(50),
salary NUMBER(10),
CONSTRAINT pk_roles PRIMARY KEY (movie_id, actor_id)
);
CREATE TABLE profits (
movie_id NUMBER(10,0) NOT NULL,
gross_profit NUMBER(9) NOT NULL,
net_profit NUMBER(9) NOT NULL,
CONSTRAINT fk_profits FOREIGN KEY (movie_id) REFERENCES movies(movie_id) ON DELETE CASCADE
);
In the first table I have made a composite primary key from teh two columns that reference columns in other tables. Those columns happen to be primary keys in their respective tables.
In the second table, I've made a foreign key again referencing a primary key in anther table. But what is best practice? Should the key in the first table also be a foreign key since it references primary keys in other tables?
Primary key constraints and unique constraints prevent duplicate rows. Duplicate rows not only waste space, they make it harder to get meaningful answers from your database.
Foreign key constraints restrict values to those that exist in another table. The target of a foreign key constraint is commonly a primary key, but it could be any column(s) that have a unique constraint.
Every table should have a primary key constraint. If the column(s) that make up the primary key also require a foreign key constraint, add the foreign key constraint as well.
Your table "roles" is fine, as far as implementing primary key constraints and foreign key constraints. But "profits" needs a primary key.
To your Question "Should the key in the first table also be a foreign key since it references primary keys in other tables?"
There is no simple answer, as it heavily depends on type of planned usage of data and database being used. If you need a simple answer, yes it is a good idea. Below is the longer version.
Pros :
It helps keep your data clean.
Based on how database is planned to be used and which database you are using, some databases, tend to optimize joins better, if Foreign keys are defined for joins upfront.
Cons :
If you plan to bulk load into your tables frequently, then FK constraints tend to slow down your loads, if that is the case, some databases allow you to define soft constraints, which are only used for query optimization purposes, but are not verified during loads.

Resources