Re: Foreign key-type constraints
The methodology my company has defined and uses to attack this problem is
based upon looking for large grain 'business components' within the
business model.
When translating the functionality of the 'business component' to a
physical design we end up with a component object which usually consists of
a major entity(table) and several subsidiary entities and the services
which operate on and maintain those entities i.e. a component object.
We would then remove the referential integrity constraints only between the
components - to be managed by a component reference object - but internally
to the component leave the database referential integrity rules in place.
I beleive this maintains idea of encapsulation as the only way to
communicate with the component is through a defined public service
interface. It also lessens the impact of database changes as they are
usually confined to one componeet and the public service interface to any
other is left intact. It makes use of the database functionality without
dramatically effecting maintenance and performance by writing it all
yourself and/or defining every relationship with the refence manager.
It also leads very much to the definition of large grain reusable
components which can be used in many applications, important to a company
such as mine which develops software for others.
Unfortunately it is not always as simple as it sounds, the methodology helps.
Good database management systems with declarative referential integrity
will usuaually prevent you from defining circular references so you could
test for this by attempting to create the database before you remove the
inter component links. But circular references are much less likely with
the component technique properly applied.
Keith Matthews
Caro System Inc.
www.carosys.com
At 02:07 PM 10/23/97 +0100, John Challis wrote:
We've been pondering the issue of how database integrity should be
represeted within a Forte/OO app. We're thinking, in particular, about
foreign key-type constraints.
First of all, we're not sure whether these constraints should be on the
database, because some would say that this represents business knowledge
which should only be in the app. Also, if constraints are on the
database, the errors you receive if they are violated may not be very
useful; i.e. we're using Oracle, and we'd have to map constraint names
in error messages to some more meaningful message to present to a user.
If foreign key-type constraints aren't on the database, what other
options do we have?
Let's say there's associations between objects X, Y and Z, whereby X and
Y both know about and use Z - we don't want to delete Z while X and Y
exist. I accept that Z should know how to delete itself, from
persistance, but how does it check for the existence of X and Y? If Z
asks objects of types X and Y to check whether they exist in the
database, you can end up with a circular reference. If you do the check
yourself, i.e. by having SQL checking existence of X and Y within the
delete method for Z, then I reckon you've blown encapsulation, and
you've also got a problem in relation to impact if the shape of your
database changes.
We're toying with the idea of having a central integrity manager, which
will tell Z whether it can go ahead with the delete, thus centralising
the integrity constraint knowledge within the app. and minimising impact
of changes to the shape of the database.
I'd be interested to know what others have done to address this issue,
and any thoughts you may have.
Thanks,
John Challis
PanCredit
Leeds, UK
** bassssss **
At 02:07 PM 10/23/97 +0100, you wrote:
...>First of all, we're not sure whether these constraints should be on the
database, because some would say that this represents business knowledge
which should only be in the app. This is a long-winded response, but I tried to relate it to a real-world
example, so bear with me...
Purists may argue with me here, but I must take issue with the notion that
your database cannot have any business knowledge. As soon as you define a
table, you have implicitly given the database business knowledge.
For example, suppose you define a database table Person, with columns Name,
ID, and BirthDate. You are specifically telling the database that there
exists a business "something" called Person which can (or must!) have
values called Name, ID, and Birthdate. You are probably also telling the
database about certain business rules: The value called ID can be used to
uniquely identify a Person; The value Name contains text, and has a maximum
length; Birthdate must conform to the format rules for something of type
Date; etc. Need I go on?
So, to me the argument cannot be that your database should not have any
business knowledge, but rather, what type of business knowledge should be
given to the database?
On the other side of the coin, I also take exception to the argument that
business knowledge belongs only in the Application. In fact, if your
discussion centers around whether business knowledge belongs in the
Application vs. the Database, then maybe both sides are still thinking in
two tiers, and you need to take a step back and think about your business
classes some more.
In our oversimplified example above, we set a limit on the length of the
Name attribute. This is a business rule, and so "belongs" to the business
class. However, our application class needs to have knowledge of that rule
so that it can set a limit on the length of data that it allows to be
entered. Likewise, the persistent storage class must have knowledge of
that rule to effectively store and retrieve the data.
We also have an attribute that is a Date, and a date by definition must
follow certain rules about format and value. The application class and the
storage class will both do their job more effectively if they know that the
attribute is a Date.
Does it break the rules of encapsulation if you allow the application class
or the storage class to have knowledge of certain rules that are defined in
the business class? If it does, then we might as well throw encapsulation
out the door, because it is a totally useless concept in the real world.
Now, let's think about the referential constraints. Suppose you want to
create a business class Employee which inherits from the class Person, and
adds attributes HireDate and Department. When you physically store the
Employee information in your Relational database, you might actually store
two tables, with the ID as a foreign key between them. In this case, the
foreign key relationship would clearly belong to the storage class and the
database. The business class should not know or care whether the Employee
information is physically stored in one table, or two, or twelve.
Now, let's add another business rule, that Employee Department must be a
valid department. To support this rule, you will create a business Class,
Department. For the sake of argument, let us say that the persistent data
for this business class will be stored in a database table, also called
Department.
We have said that there is a relationship between Employee and Department.
Which business class will contain the rule that defines the relationship?
Clearly, it is not Department. Department has no reason to know about
Employee, or any other class that might contain a reference to it. Since
Employee is the one that contains a reference to Department, you could
argue that the rule belongs there. That works fine, until you want to
delete a Department object. Obviously, you would not go to the Employee
class for that. So it seems that the relationship does not belong in
either class.
Someone has suggested that you have an integrity manager or some similar
class for that purpose. The integrity manager would have knowledge of the
rules that define the relationships between your business objects. This
allows you to keep your OO design more "pure" from the standpoint of
encapsulation. Conceptually, this makes good sense, since the relationship
between two classes does not belong to either of the individual classes.
Let's hold that thought for a minute.
Now let's think about your physical database design. I am betting that
there is a high degree of correlation between your database tables and your
business objects. It won't be 100%, because, among other things,
relational databases do not deal well with the concept of inheritance. But
if there is a very wide divergence, then I would need to question the
validity of your design. With that in mind, I am going to propose that you
already have an Integrity Manager, and that is your relational DBMS.
My position is this, that it is ok, even necessary, for the data storage
class to have knowledge of the structure and relationships of the data. It
needs this information to effectively do its job. From my point of view,
saying that you cannot tell the database that there is a relationship
between Employee and Department is just as pointless as saying that you
cannot tell the database that a certain column contains a date, or that
another column contains a unique key which should be used as an index.
Would you argue that an index implies business knowledge, and therefore
does not belong in the database? On the other hand, you could argue that
referential constraints always belong to the physical storage classes,
since they describe under what circumstances data can be stored or deleted.
Now, for performance or other reasons, you might choose not to implement
the Employee-Department relationship in your physical database, and that's
ok, too. Maybe you have decided that since you do not delete departments
very often, that you do not want to incur the database overhead to maintain
the foreign key relationship. Or maybe you have determined that the
Department data will be stored somewhere else other than the database.
Perhaps you would create an Integrity Manager instead, that would only be
invoked when you wanted to delete a Department object. The point is, if
you create an Integrity Manager, be sure you do it for the right reason,
and not because someone has mistakenly decreed that a database cannot have
any business knowledge.
This brings us to the other question, which is: What do you do with the
error if the constraint is violated? Consider this as an option: Create a
User-defined exception named DeleteFailed or something like that. Then it
does not matter if the error comes from the database manager or a separate
Integrity manager. In either case, you fill the exception object with
whatever meaningful data is appropriate, and raise the exception. The
application, which knows what it was trying to do, can listen for the
exception and deal with it appropriately. (btw, this is a good way to deal
with other predictable database exceptions as well, such as DuplicateKey,
or NotFound - your application need not listen for a particular SQL Code or
SQL State, which might tie it to a particular database or storage format.)
I do not see a problem with using the DBMS to define relational
constraints. That is, after all, what a Relational database does. You do
not need an integrity manager for OO-purity, but you can use one if it
makes sense for other reasons. You should be able to change the method of
enforcing the relationships, or even change the entire DBMS without having
any impact on the application classes or the business classes. If you can
meet that test, then as far as I am concerned, you have not violated any
rules of encapsulation.
Any rebuttals?
=========================================
Jeanne Hesler <[email protected]>
MSF&W, Springfield, Illinois
(217) 698-3535 ext 207
=========================================
Similar Messages
-
Oracle 9i primary and foreign key constraint
I had created table in the following way
create table dept(deptno number,dname varchar2(20));
create table emp(empno number primary key,ename varchar2(25), deptno number references dept(deptno));
One can get constraint name and constraint type from user_constraints table. But I want to know name of the column of table from which column is used as foreign key in another table. How to get such information?SQL> Select *From user_cons_columns A
2 Where Constraint_Name In (Select r_Constraint_Name
3 From User_Constraints B
4 Where Table_Name='EMP'
5 And Constraint_Type='R'
6 Group By r_Constraint_Name
7 )
8 /
OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME
SCOTT PK_DEPTNO DEPT DEPTNO Edited by: babaravi on Oct 5, 2009 3:34 PM -
HI GUYS
I DID THE FOLL
CREATE TABLE MASTER(EMPNO NUMBER PRIMARY KEY,
ENAME VARCHAR2(12));
CREATE TABLE CHILD(EMPNO NUMBER);
ALTER TABLE CHILD ADD CONSTRAINT FOREIGN KEY REFERNCES MASTER(EMPNO)
NOW WHEN I DOTHE ABOVE AND THE DO DESC CHILD
I GET THE FOLL
EMPNO NUMBER
ENAME VARCHAR2(12)
KEY NUMBER
WHAT IS THIS KEY COLUMN ? WHY IS IT COMING
KINDLY CLARIFYInteresting.
The correct syntax to add a FK constraint is:
ALTER TABLE child ADD CONSTRAINT
FOREIGN KEY (empno) REFERENCES master (empno);I can replicate your behaviour in 9.2.0.6, and in 8.1.7.4. It appears that in the absence of a column list in parens, Oracle takes the word after FOREIGN and adds a column with that name and the appropriate data type to the table and uses that in the FK.
SQL> CREATE TABLE master (empno NUMBER PRIMARY KEY,
2 ename VARCHAR2(12));
Table created.
SQL> CREATE TABLE child (empno NUMBER);
Table created.
SQL> ALTER TABLE child ADD CONSTRAINT
2 FOREIGN new_col REFERENCES master (empno);
Table altered.
SQL> desc child
Name Null? Type
EMPNO NUMBER
NEW_COL NUMBERJust to show that the constraint is enforced:
SQL> INSERT INTO child VALUES(1,1);
INSERT INTO child VALUES(1,1)
ERROR at line 1:
ORA-02291: integrity constraint (OPS$ORACLE.SYS_C0070911) violated -
parent key not foundBut, this only works when there is no KEY keyword:
SQL> DROP TABLE child;
Table dropped.
SQL> CREATE TABLE child (empno NUMBER);
Table created.
SQL> ALTER TABLE child ADD CONSTRAINT
2 FOREIGN KEY new_col REFERENCES master (empno);
FOREIGN KEY new_col REFERENCES master (empno)
ERROR at line 2:
ORA-00902: invalid datatypeOn a fast scan of the documentation I don't see where this behaviour is documented, and I have certainly never seen this before. Anyone out there have any thoughts?
John -
FOREIGN KEY Constraint And Table Lock
According to Db Concepts on Data Integrity->Types of Integrity Contraints->Referential Integrity Constraints, if the FK column is not indexed, delete/update of parent table would cause child table share locked.
I can understand the reason behind this behaviour because if parent's PK is modified but not commited yet, we don't want another transaction to insert/update the child's FK column to use the deleted parent PK value and this requires a table share lock.
The problem is, I don't understand why if the child's FK is indexed, no table share lock is acquired. The same condition could happen and we still need to prevent another transaction from using the uncommitted deleted PK in parent as the child's FK.
Appreciate and advice.hi
When PK column change, Oracle is going to have to do a
referential integrity check on any referenced columns ,in
the absence of an index on the child end of the foreign
key, that would seem to result in a full table scan of the table which cause locks the entire table for any
Delete or Update on Parent table.
Khurram -
Wrong order foreign key constraints
Hi,
i have problems with non-deferred foreing key constraints:
I have a table "PERSON" and a table "ADRESSE" which has a foreign key
to "PERSON". Both tables have primary keys with two columns.
In the mappings I use application identity. The mappings are generated by
xdoclet.
We cannot use deferred constraint because we have to support following
databases: Oracle, Firebird, MS SQL, DB2.
I tested the mappings with Oracle and Firebird and got this exception
(with SQL Trace):
5602 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (1 errors)>
[15 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 1, (String) [email protected], (String)
04941 183742, (int) 12761, (int) 1, (int) 1, (String) 0171 2846751,
(String) Oldenburg, (int) 12760, (String) 26129, (int) 1, (null) null,
(String) Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=0]
5602 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 3, (null) null, (null) null, (int) 12764,
(int) 1, (int) 0, (null) null, (String) Sylt, (int) 12759, (String) 25980,
(int) 0, (null) null, (String) Stephanstra__e 47, (String) 04651 19283]
[reused=1]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 13390902 INSERT INTO VAMP.PERSON (ANREDEID, ID,
KUNDENNR, LOESCHBEMERKUNG, MANDANTID, NAME1, NAME2, PERSONENDATUM,
PERSONENORT, TYP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(null)
null, (int) 12759, (String) 9999452800, (null) null, (int) 1, (String)
Horstmann, (String) Manfred, (Timestamp) 1959-03-10 00:00:00.381, (String)
Flensburg, (int) 1] [reused=0]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 1, (String) [email protected], (String)
04941 183742, (int) 12763, (int) 1, (int) 1, (String) 0171 2846751,
(String) Oldenburg, (int) 12759, (String) 26129, (int) 1, (null) null,
(String) Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=2]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 3, (null) null, (null) null, (int) 12762,
(int) 1, (int) 0, (null) null, (String) Sylt, (int) 12760, (String) 25980,
(int) 0, (null) null, (String) Stephanstra__e 47, (String) 04651 19283]
[reused=3]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 13390902 INSERT INTO VAMP.PERSON (ANREDEID, ID,
KUNDENNR, LOESCHBEMERKUNG, MANDANTID, NAME1, NAME2, PERSONENDATUM,
PERSONENORT, TYP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(null)
null, (int) 12760, (String) 9999452801, (null) null, (int) 1, (String)
Horstmann, (String) Christine, (Timestamp) 1972-03-10 00:00:00.381,
(String) Erfurt, (int) 1] [reused=1]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 11320634 INSERT INTO VAMP.NATPERSON
(ANZAHLKINDER, ARBEITGEBERID, BEITRAGSSATZ, BERUFID, BRANCHEID,
FAMILIENSTAND, FAMSTANDSEIT, FINANZAMTID, GEBIETSFREMDERAWG, GUETERSTAND,
IDBEHOERDE, IDNR, KIRCHENSTEUER, KVID, MANDANTID, PERSONID, PRIVATKV,
STAAT, STEUERBERATERID, STEUERKLASSE, STEUERNR, STEUERTARIF, TITEL) VALUES
[params=(int) 0, (null) null, (double) 0.0, (null) null, (int) 12410,
(int) 2, (Timestamp) 1991-12-12 00:00:00.381, (null) null, (int) 0, (int)
3, (null) null, (null) null, (int) 0, (int) 12576, (int) 1, (int) 12760,
(int) 0, (null) null, (null) null, (int) 0, (null) null, (int) 1, (null)
null] [reused=0]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 11320634 INSERT INTO VAMP.NATPERSON
(ANZAHLKINDER, ARBEITGEBERID, BEITRAGSSATZ, BERUFID, BRANCHEID,
FAMILIENSTAND, FAMSTANDSEIT, FINANZAMTID, GEBIETSFREMDERAWG, GUETERSTAND,
IDBEHOERDE, IDNR, KIRCHENSTEUER, KVID, MANDANTID, PERSONID, PRIVATKV,
STAAT, STEUERBERATERID, STEUERKLASSE, STEUERNR, STEUERTARIF, TITEL) VALUES
[params=(int) 0, (null) null, (double) 0.0, (int) 12362, (int) 12378,
(int) 2, (Timestamp) 1991-12-12 00:00:00.381, (null) null, (int) 0, (int)
3, (null) null, (null) null, (int) 0, (int) 12576, (int) 1, (int) 12759,
(int) 0, (null) null, (null) null, (int) 0, (null) null, (int) 1, (null)
null] [reused=1]
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> [16 ms] rollback
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> return
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> [0 ms] close
com.solarmetric.jdbc.ReportingSQLException: ORA-02291: integrity
constraint (VAMP.ADRESSE_PS) violated - parent key not found
{prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART, EMAIL, FAXNR,
ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ, POSTADRESSE,
POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?) [params=(int) 1, (String) [email protected], (String) 04941
183742, (int) 12761, (int) 1, (int) 1, (String) 0171 2846751, (String)
Oldenburg, (int) 12760, (String) 26129, (int) 1, (null) null, (String)
Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=0]} [code=2291,
state=23000]
at
com.solarmetric.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:124)
at
com.solarmetric.jdbc.LoggingConnectionDecorator.access$600(LoggingConnectionDecorator.java:19)
at
com.solarmetric.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:728)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:362)
How can I force it to insert in the table "NATPERSON" first and then in
the table "ADRESSE"?
I use following JDBC-drivers:
Firebird: 1.5.5
Oracle: 9.2.0.1.0
My property file:
<!-- standard properties for all dbms -->
<prop key="kodo.LicenseKey">LICENSE KEY REMOVED</prop>
<prop key="kodo.ConnectionFactoryProperties">MaxCachedStatements=150,
MaxActive=50, MaxIdle=50</prop>
<prop key="kodo.FetchBatchSize">200</prop>
<prop key="kodo.DataCache">true(CacheSize=5000)</prop>
<prop key="kodo.RemoteCommitProvider">sjvm</prop>
<prop key="kodo.jdbc.MappingFactory">metadata</prop>
<prop key="kodo.jdbc.ForeignKeyConstraints">true</prop>
<prop key="kodo.jdbc.SchemaFactory">native</prop>
<prop
key="javax.jdo.PersistenceManagerFactoryClass">kodo.jdbc.runtime.JDBCPersistenceManagerFactory</prop>
<prop key="javax.jdo.option.Optimistic">true</prop>
<!-- oracle connection properties -->
<prop key="kodo.jdbc.DBDictionary">oracle</prop>
<prop
key="javax.jdo.option.ConnectionDriverName">oracle.jdbc.driver.OracleDriver</prop>
<prop key="javax.jdo.option.ConnectionURL">..</prop>
<prop key="javax.jdo.option.ConnectionUserName">..</prop>
<prop key="javax.jdo.option.ConnectionPassword">..</prop>
<prop key="kodo.jdbc.SequenceFactory">native</prop>
<prop key="kodo.jdbc.Schemas">..</prop>
<!-- firebird connection properties
<prop key="kodo.jdbc.DBDictionary">kodo.jdbc.sql.FirebirdDictionary</prop>
<prop
key="javax.jdo.option.ConnectionDriverName">org.firebirdsql.jdbc.FBDriver</prop>
<prop key="javax.jdo.option.ConnectionURL">..</prop>
<prop key="javax.jdo.option.ConnectionUserName">..</prop>
<prop key="javax.jdo.option.ConnectionPassword">..</prop>
<prop key="kodo.jdbc.SequenceFactory">native(TableName=SYSDUAL,
Format="SELECT GEN_ID({0},1) FROM {1}")</prop>
-->
My database schema looks like this:
TABLE PERSON
FIELD MANDANTID (SMALLINT REQUIRED COMMENT (""))
FIELD ID (AUTOINC COMMENT (""))
FIELD TYP (SMALLINT REQUIRED COMMENT (""))
FIELD KUNDENNR (CHAR(15) COMMENT ("Kundennummer"))
PRIMARY KEY
FIELD MANDANTID
FIELD ID
FOREIGN KEY MD
TABLE MANDANT
FIELD MANDANTID
INDEX KDNR
FIELD MANDANTID
FIELD KUNDENNR
UNIQUE
TABLE ADRESSE
FIELD MANDANTID (SMALLINT REQUIRED COMMENT (""))
FIELD ID (AUTOINC COMMENT (""))
FIELD PERSONID (LONGINT REQUIRED COMMENT (""))
PRIMARY KEY
FIELD MANDANTID
FIELD ID
FOREIGN KEY PS
TABLE PERSON
FIELD MANDANTID
FIELD PERSONID
My metadata looks like this:
<class name="PersonDO"
identity-type="application"
objectid-class="com.elaxy.vamp.dom.person.PersonDOId"
persistence-capable-superclass="com.elaxy.vamp.dom.AbstractDO">
<extension vendor-name="kodo"
key="jdbc-class-ind"
value="metadata-value">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-ind/column"
value="TYP">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-ind-value"
value="-1">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map"
value="base">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map/table"
value="PERSON">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map/column"
value="ID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map/column"
value="MANDANTID">
</extension>
<field name="kundenNr"
persistence-modifier="persistent">
</field>
<field name="adressen"
persistence-modifier="persistent">
<collection
element-type="com.elaxy.vamp.dom.person.AdresseDO">
</collection>
<extension vendor-name="kodo"
key="jdbc-field-map"
value="one-many">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/ref-column.MANDANTID"
value="MANDANTID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/ref-column.ID"
value="PERSONID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/table"
value="ADRESSE">
</extension>
</field>
.. fields ..
</class>
<class name="AdresseDO"
identity-type="application"
objectid-class="com.elaxy.vamp.dom.person.AdresseDOId"
persistence-capable-superclass="com.elaxy.vamp.dom.AbstractDO">
<extension vendor-name="kodo"
key="jdbc-class-map"
value="base">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map/table"
value="ADRESSE">
</extension>
<extension vendor-name="kodo"
key="jdbc-sequence-name"
value="ADRESSE_SEQ">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map/column"
value="ID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map/column"
value="MANDANTID">
</extension>
.. fields ..
</class>
Many thanks,
JanMarc
This is a part of the output from the "schemagen" tool:
<schemas>
<schema name="VAMP">
<table name="ADRESSE">
<pk name="ADRESSE_PRIMARY">
<on column="ID"/>
<on column="MANDANTID"/>
</pk>
<column name="ADRESSART" type="decimal" type-name="NUMBER"
size="5"/>
<column name="EMAIL" type="varchar" type-name="VARCHAR2"
size="30"/>
<column name="FAXNR" type="varchar" type-name="VARCHAR2"
size="25"/>
<column name="ID" type="decimal" type-name="NUMBER"
not-null="true" size="10"/>
<column name="LAND" type="decimal" type-name="NUMBER"
size="10"/>
<column name="MANDANTID" type="decimal" type-name="NUMBER"
not-null="true" size="5"/>
<column name="MELDEADRESSE" type="decimal" type-name="NUMBER"
size="1"/>
<column name="MOBILNR" type="varchar" type-name="VARCHAR2"
size="25"/>
<column name="ORT" type="varchar" type-name="VARCHAR2"
size="30"/>
<column name="PERSONID" type="decimal" type-name="NUMBER"
not-null="true" size="10"/>
<column name="PLZ" type="varchar" type-name="VARCHAR2"
size="5"/>
<column name="POSTADRESSE" type="decimal" type-name="NUMBER"
size="1"/>
<column name="POSTFACH" type="varchar" type-name="VARCHAR2"
size="10"/>
<column name="STRASSE" type="varchar" type-name="VARCHAR2"
size="30"/>
<column name="TELEFONNR" type="varchar" type-name="VARCHAR2"
size="25"/>
<fk name="ADRESSE_PS" delete-action="cascade"
to-table="VAMP.PERSON">
<join column="MANDANTID" to-column="MANDANTID"/>
<join column="PERSONID" to-column="ID"/>
</fk>
<index name="ADRESSE_ORT">
<on column="MANDANTID"/>
<on column="ORT"/>
</index>
<index name="ADRESSE_PLZ">
<on column="MANDANTID"/>
<on column="PLZ"/>
</index>
<index name="ADRESSE_PS">
<on column="MANDANTID"/>
<on column="PERSONID"/>
</index>
<index name="ADRESSE_STR">
<on column="MANDANTID"/>
<on column="STRASSE"/>
</index>
</table>
The foreign key "ADRESSE_PS" was identified correctly.
I've taken a look at the class OracleDictionary and it seems that the
object "ForeignKey" considers only one column from the foreign keys -
but I use foreign keys that include two columns ("MANDANTID", "PERSONID").
Is that right or are foreign keys with two columns allowed by the
OracleDictionary?
Marc Prud'hommeaux wrote:
Jan-
That is odd ... Kodo should be identifying the foreign keys and ordering
the statements accordingly. The mappings appear correct to me at first
glance. If you run the "schemagen" tool, does Kodo correctly identify
the foreign key constraints in the database? Can you post the output
from the command so we can take a look?
Jan-Esdert Franken wrote:
Hi,
i have problems with non-deferred foreing key constraints:
I have a table "PERSON" and a table "ADRESSE" which has a foreign key
to "PERSON". Both tables have primary keys with two columns.
In the mappings I use application identity. The mappings are generated by
xdoclet.
We cannot use deferred constraint because we have to support following
databases: Oracle, Firebird, MS SQL, DB2.
I tested the mappings with Oracle and Firebird and got this exception
(with SQL Trace):
5602 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (1 errors)>
[15 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 1, (String) [email protected], (String)
04941 183742, (int) 12761, (int) 1, (int) 1, (String) 0171 2846751,
(String) Oldenburg, (int) 12760, (String) 26129, (int) 1, (null) null,
(String) Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=0]
5602 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 3, (null) null, (null) null, (int) 12764,
(int) 1, (int) 0, (null) null, (String) Sylt, (int) 12759, (String) 25980,
(int) 0, (null) null, (String) Stephanstra__e 47, (String) 04651 19283]
[reused=1]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 13390902 INSERT INTO VAMP.PERSON (ANREDEID, ID,
KUNDENNR, LOESCHBEMERKUNG, MANDANTID, NAME1, NAME2, PERSONENDATUM,
PERSONENORT, TYP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(null)
null, (int) 12759, (String) 9999452800, (null) null, (int) 1, (String)
Horstmann, (String) Manfred, (Timestamp) 1959-03-10 00:00:00.381, (String)
Flensburg, (int) 1] [reused=0]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (2 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 1, (String) [email protected], (String)
04941 183742, (int) 12763, (int) 1, (int) 1, (String) 0171 2846751,
(String) Oldenburg, (int) 12759, (String) 26129, (int) 1, (null) null,
(String) Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=2]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART,
EMAIL, FAXNR, ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ,
POSTADRESSE, POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?) [params=(int) 3, (null) null, (null) null, (int) 12762,
(int) 1, (int) 0, (null) null, (String) Sylt, (int) 12760, (String) 25980,
(int) 0, (null) null, (String) Stephanstra__e 47, (String) 04651 19283]
[reused=3]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 13390902 INSERT INTO VAMP.PERSON (ANREDEID, ID,
KUNDENNR, LOESCHBEMERKUNG, MANDANTID, NAME1, NAME2, PERSONENDATUM,
PERSONENORT, TYP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(null)
null, (int) 12760, (String) 9999452801, (null) null, (int) 1, (String)
Horstmann, (String) Christine, (Timestamp) 1972-03-10 00:00:00.381,
(String) Erfurt, (int) 1] [reused=1]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 11320634 INSERT INTO VAMP.NATPERSON
(ANZAHLKINDER, ARBEITGEBERID, BEITRAGSSATZ, BERUFID, BRANCHEID,
FAMILIENSTAND, FAMSTANDSEIT, FINANZAMTID, GEBIETSFREMDERAWG, GUETERSTAND,
IDBEHOERDE, IDNR, KIRCHENSTEUER, KVID, MANDANTID, PERSONID, PRIVATKV,
STAAT, STEUERBERATERID, STEUERKLASSE, STEUERNR, STEUERTARIF, TITEL) VALUES
[params=(int) 0, (null) null, (double) 0.0, (null) null, (int) 12410,
(int) 2, (Timestamp) 1991-12-12 00:00:00.381, (null) null, (int) 0, (int)
3, (null) null, (null) null, (int) 0, (int) 12576, (int) 1, (int) 12760,
(int) 0, (null) null, (null) null, (int) 0, (null) null, (int) 1, (null)
null] [reused=0]
5618 TRACE [main] kodo.jdbc.SQL - <t 26577913, conn 33108879 (3 errors)>
[0 ms] executing prepstmnt 11320634 INSERT INTO VAMP.NATPERSON
(ANZAHLKINDER, ARBEITGEBERID, BEITRAGSSATZ, BERUFID, BRANCHEID,
FAMILIENSTAND, FAMSTANDSEIT, FINANZAMTID, GEBIETSFREMDERAWG, GUETERSTAND,
IDBEHOERDE, IDNR, KIRCHENSTEUER, KVID, MANDANTID, PERSONID, PRIVATKV,
STAAT, STEUERBERATERID, STEUERKLASSE, STEUERNR, STEUERTARIF, TITEL) VALUES
[params=(int) 0, (null) null, (double) 0.0, (int) 12362, (int) 12378,
(int) 2, (Timestamp) 1991-12-12 00:00:00.381, (null) null, (int) 0, (int)
3, (null) null, (null) null, (int) 0, (int) 12576, (int) 1, (int) 12759,
(int) 0, (null) null, (null) null, (int) 0, (null) null, (int) 1, (null)
null] [reused=1]
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> [16 ms] rollback
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> return
5634 TRACE [main] kodo.jdbc.JDBC - <t 26577913, conn 33108879 (3
errors)> [0 ms] close
com.solarmetric.jdbc.ReportingSQLException: ORA-02291: integrity
constraint (VAMP.ADRESSE_PS) violated - parent key not found
{prepstmnt 22511833 INSERT INTO VAMP.ADRESSE (ADRESSART, EMAIL, FAXNR,
ID, MANDANTID, MELDEADRESSE, MOBILNR, ORT, PERSONID, PLZ, POSTADRESSE,
POSTFACH, STRASSE, TELEFONNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?) [params=(int) 1, (String) [email protected], (String) 04941
183742, (int) 12761, (int) 1, (int) 1, (String) 0171 2846751, (String)
Oldenburg, (int) 12760, (String) 26129, (int) 1, (null) null, (String)
Ammerl__nder Heerstra__e 19, (String) 04941 183740] [reused=0]} [code=2291,
state=23000]
at
com.solarmetric.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:124)
at
com.solarmetric.jdbc.LoggingConnectionDecorator.access$600(LoggingConnectionDecorator.java:19)
at
com.solarmetric.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:728)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:362)
How can I force it to insert in the table "NATPERSON" first and then in
the table "ADRESSE"?
I use following JDBC-drivers:
Firebird: 1.5.5
Oracle: 9.2.0.1.0
My property file:
<!-- standard properties for all dbms -->
<prop key="kodo.LicenseKey">LICENSE KEY REMOVED</prop>
<prop key="kodo.ConnectionFactoryProperties">MaxCachedStatements=150,
MaxActive=50, MaxIdle=50</prop>
<prop key="kodo.FetchBatchSize">200</prop>
<prop key="kodo.DataCache">true(CacheSize=5000)</prop>
<prop key="kodo.RemoteCommitProvider">sjvm</prop>
<prop key="kodo.jdbc.MappingFactory">metadata</prop>
<prop key="kodo.jdbc.ForeignKeyConstraints">true</prop>
<prop key="kodo.jdbc.SchemaFactory">native</prop>
<prop
key="javax.jdo.PersistenceManagerFactoryClass">kodo.jdbc.runtime.JDBCPersistenceManagerFactory</prop>
<prop key="javax.jdo.option.Optimistic">true</prop>
<!-- oracle connection properties -->
<prop key="kodo.jdbc.DBDictionary">oracle</prop>
<prop
key="javax.jdo.option.ConnectionDriverName">oracle.jdbc.driver.OracleDriver</prop>
<prop key="javax.jdo.option.ConnectionURL">..</prop>
<prop key="javax.jdo.option.ConnectionUserName">..</prop>
<prop key="javax.jdo.option.ConnectionPassword">..</prop>
<prop key="kodo.jdbc.SequenceFactory">native</prop>
<prop key="kodo.jdbc.Schemas">..</prop>
<!-- firebird connection properties
<prop key="kodo.jdbc.DBDictionary">kodo.jdbc.sql.FirebirdDictionary</prop>
<prop
key="javax.jdo.option.ConnectionDriverName">org.firebirdsql.jdbc.FBDriver</prop>
<prop key="javax.jdo.option.ConnectionURL">..</prop>
<prop key="javax.jdo.option.ConnectionUserName">..</prop>
<prop key="javax.jdo.option.ConnectionPassword">..</prop>
<prop key="kodo.jdbc.SequenceFactory">native(TableName=SYSDUAL,
Format="SELECT GEN_ID(,1) FROM ")</prop>
-->
My database schema looks like this:
TABLE PERSON
FIELD MANDANTID (SMALLINT REQUIRED COMMENT (""))
FIELD ID (AUTOINC COMMENT (""))
FIELD TYP (SMALLINT REQUIRED COMMENT (""))
FIELD KUNDENNR (CHAR(15) COMMENT ("Kundennummer"))
PRIMARY KEY
FIELD MANDANTID
FIELD ID
FOREIGN KEY MD
TABLE MANDANT
FIELD MANDANTID
INDEX KDNR
FIELD MANDANTID
FIELD KUNDENNR
UNIQUE
TABLE ADRESSE
FIELD MANDANTID (SMALLINT REQUIRED COMMENT (""))
FIELD ID (AUTOINC COMMENT (""))
FIELD PERSONID (LONGINT REQUIRED COMMENT (""))
PRIMARY KEY
FIELD MANDANTID
FIELD ID
FOREIGN KEY PS
TABLE PERSON
FIELD MANDANTID
FIELD PERSONID
My metadata looks like this:
<class name="PersonDO"
identity-type="application"
objectid-class="com.elaxy.vamp.dom.person.PersonDOId"
persistence-capable-superclass="com.elaxy.vamp.dom.AbstractDO">
<extension vendor-name="kodo"
key="jdbc-class-ind"
value="metadata-value">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-ind/column"
value="TYP">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-ind-value"
value="-1">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map"
value="base">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map/table"
value="PERSON">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map/column"
value="ID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map/column"
value="MANDANTID">
</extension>
<field name="kundenNr"
persistence-modifier="persistent">
</field>
<field name="adressen"
persistence-modifier="persistent">
<collection
element-type="com.elaxy.vamp.dom.person.AdresseDO">
</collection>
<extension vendor-name="kodo"
key="jdbc-field-map"
value="one-many">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/ref-column.MANDANTID"
value="MANDANTID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/ref-column.ID"
value="PERSONID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-map/table"
value="ADRESSE">
</extension>
</field>
.. fields ..
</class>
<class name="AdresseDO"
identity-type="application"
objectid-class="com.elaxy.vamp.dom.person.AdresseDOId"
persistence-capable-superclass="com.elaxy.vamp.dom.AbstractDO">
<extension vendor-name="kodo"
key="jdbc-class-map"
value="base">
</extension>
<extension vendor-name="kodo"
key="jdbc-class-map/table"
value="ADRESSE">
</extension>
<extension vendor-name="kodo"
key="jdbc-sequence-name"
value="ADRESSE_SEQ">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.id/jdbc-field-map/column"
value="ID">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId"
value="">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map"
value="value">
</extension>
<extension vendor-name="kodo"
key="jdbc-field-mappings/AbstractDO.mandantId/jdbc-field-map/column"
value="MANDANTID">
</extension>
.. fields ..
</class>
Many thanks,
Jan
Marc Prud'hommeaux
SolarMetric Inc. -
Generated Script fails when attempting to drop Foreign Key Constraint
I made some changes to my database. I used the generate script process to generate a drop and create script to these tables. The generated script first ran Alter Table Drop Constraints to drop the Foreign Key constraints and then did Drop tables
and then did create table to construct the script with the proper changes.
However, when we attempted to run the script, all of the Drop constraint statements failed reporting that there was no such constraint. Then the drop table scripts failed because of the existence of the very foreign key constraints that SQL Server
had just stated did not exist.
BOL states that the statement "DROP { [ CONSTRAINT ] constraint_name | COLUMN column_name } " is "Used in a CHECK, FOREIGN KEY, UNIQUE, or PRIMARY KEY constraint." So why couldn't I drop those specified Foreign
Key constraints in a script generated by SQL Server itself.
Edward R. Joell MCSD MCDBAAre you sure there are no Constraints on other tables which are causing your issue?
If a foreign key from table abc refences table def it will cause the drop to fail.
If your script is already attempting to drop such constraints, have you checked that they are dropping from the correct table (and not the table that would be the target of the drop)?
I discovered two things yesterday and one thing today about generated scripts.
When you generated a script to drop and create a set of tables and you mark it to include foreign keys, the generated script will first create a set a scripts to drop the foreign keys , then will create a set of statements for each table that will,
first, again drop the same foreign keys that it did earlier, then drop the table. If there is no "if exists" statement for each statement, the drop constraint will fail.
The script generated by the generate scripts wizard, even when you set the Drop and Create option in the advanced tab, unlike the scripts generated when you right click a table and select Drop and Create from the context menu, does not by default create
an "If Exists" statement before the attempt to drop anything.
You can make the generate Scripts wizard generate an "if exists" statement by changing the "Include if NOT EXISTS" option on the advanced tab to true. However, while the script generator will find all of the foreign keys that show that
table as the parent_id, it will not show the FK constraints on tables which are not being dropped and created. Nor can you find them by querying the sys.foreign_keys view using the standard type of Foreign Key "If Exists" statement because
it would do a query like
SELECT *
FROM sys.foreign_keys
WHERE object_id = OBJECT_ID(N'[dbo].[FK_prc_ContractSubLines_prc_PRSubLines]')
AND parent_object_id = OBJECT_ID(N'[dbo].[prc_ContractSubLines]')
And the script generator does not care even if you show an option like "Generate Scripts For Dependent Objects", it will not generate a drop script for the foreign constraints on other tables that reference your table. I have not even found
a way to get back the results of a query on the sys.foreign_keys view that will show those keys that reference your table. The only thing I been able to do is to open the table in design and check out the list of relationships in your table and see open each
relationship and see which table is the "foreign key table" rather than the primary key table. This will make writing drop and create scripts very very long and tedious. As you would have to create addional Alter tables scripts to do a drop
and create foreign keys on each table referencing yours and manually place them into your scripts at correct locations. This is almost as bad as the Oracle SQL Developer's generate script results which (at least in 2010) so screws up the order of the generated
script that it is trying to create foreign keys on tables it has not created yet.
So Patrick I see that you thought about the foreign keys on other tables. I wish I had read your post before spending the morning troubleshooting this issue based on this morning's script that ran and crashed embarrassingly.
I would like to know if someone has a query to reveal all of the foreign keys that reference your table from another table using the sys views. As it is I have to open each table in design to get a list of FKs that reference it.
Edward R. Joell MCSD MCDBA -
Creating a foreign key constraint on a synonym of table in another schema.
Hi,
I am having two user operapps and oper
owner of table po_vendors is operapps ,i have created a synonym in oper with select permission.
now i am trying to create a foreign key.
ALTER TABLE OPS_BR_VENDORS ADD ( FOREIGN KEY (VENDOR_ID) REFERENCES PO_VENDORS (VENDOR_ID));
the bolded po_vendors is the synonym for the table po_vendors in operapps.
i am getting the below error message.
SQL> ALTER TABLE OPS_BR_VENDORS ADD ( FOREIGN KEY (VENDOR_ID) REFERENCES PO_VENDORS (VENDOR_ID));
ALTER TABLE OPS_BR_VENDORS ADD ( FOREIGN KEY (VENDOR_ID) REFERENCES PO_VENDORS (VENDOR_ID))
ERROR at line 1:
ORA-01031: insufficient privileges.
i have given dba privileges to oper user.
Please advice.1) You cannot create a constraint on a synonym. You have to specify a physical table (i.e. OPERAPPS.PO_VENDORS)
2) The owner of the OPS_BR_VENDORS table will need to have the REFERENCES permission on the PO_VENDORS table granted directly (not via a role).
Justin -
How to customize the foreign key constraint exception
Hi All,
I have two table, A and B.
B.ref is foreign key references to A.id in database.
Now I want to delete a row of table A in screen, error messages are :
"Constraint "xxx.xxxx_S_FK1" is violated during post operation "Delete" using SQL statement "DELETE FROM xxxxxx WHERE xxxxxxxxx" and "ORA-02292: integrity constraint (xxx.xxxx_S_FK1) violated - child record found"
How do I customize this error message? Is it possible to do it in EO Validation?
Thank you!You can override the DoDML() method in EntityImpl something like follows
@Override
protected void doDML(int i, TransactionEvent transactionEvent) {
try
super.doDML(i, transactionEvent);
catch(DMLConstraintException _ex) {
if(_ex.getErrorCode().equals("26048") ) {
// handle your exception
sid -
Ora-2270 Error while adding foreign key constraint on top a view
While adding a constraint, referencing a foreign key column from a view raises error. However, it works fine over a table.
Here's the sample script:
create table t_temp (
sample_id number,
text varchar2(40))
alter table t_temp add constraint temp_pk
primary key (sample_id);
create view tempvw as select sample_id,text from t_temp;
create table t_sample (
uniq_id number,
sample_id number,
sample_text varchar(40));
=========
ALTER TABLE t_sample ADD CONSTRAINT FK_sample_temp
FOREIGN KEY (sample_id) REFERENCES t_temp (sample_id);
This works fine.
=========
==============
The following raises ERROR....
ALTER TABLE t_sample ADD CONSTRAINT FK_sample_temp1
FOREIGN KEY (sample_id) REFERENCES tempvw (sample_id);
Error starting at line 1 in command:
ALTER TABLE t_sample ADD CONSTRAINT FK_sample_temp1
FOREIGN KEY (sample_id) REFERENCES tempvw (sample_id)
Error report:
SQL Error: ORA-02270: no matching unique or primary key for this column-list
02270. 00000 - "no matching unique or primary key for this column-list"
*Cause: A REFERENCES clause in a CREATE/ALTER TABLE statement
gives a column-list for which there is no matching unique or primary
key constraint in the referenced table.
*Action: Find the correct column names using the ALL_CONS_COLUMNS
catalog viewWhat exactly are you trying to accomplish by having a
referential integrity constraint on a view (which is
not allowed). PKs and FKs are allowed on views. DISABLE NOVALIDATE is the only allowed state for them. View constraints are used for query rewriting: http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/qradv.htm#sthref1457
Regards,
Dima -
Is this a BUG??? Database Export not including Foreign Key Constraints
I'm using SQL Developer 1.5.4 with both the 59.47 and 59.59 patches installed. I want to do a database export from a 10g XE schema, and include all objects in the resulting DDL. So, I select ALL the checkboxes in the export wizard and when I get to Step 3 to specify objects, I don't see any of my constraints in the listbox... no foreign key constraints, no primary key constraints, no check constraints, nothing. Is this a bug, or is there a workaround, or what could I possibly be doing wrong? We want to be able to use the database export feature to easily transport and track modifications to our entire schema using source control compare.
Any help or alternate suggestions would be apprieciated.
Thanks,
MattThanks skutz, we just figured that out this morning. Also, it should be noted that you need to be logged in as the owner of the schema otherwise selecting nothing in the filter will give you nothing, but selecting items in the filter will give you those items even if you're not connected as the schema owner. I wonder if that is the detail of the Bug 8679318.
Edited by: mattsnyder on Jul 14, 2009 9:24 AM -
Publish: dropping index when it is used for foreign key constraint enforcement
Hi,
I'm trying to update a target schema from a reference database via Publish. Among the changes to apply, there's an index that needs to be dropped. Since it's linked to a foreign key constraint, it cannot be deleted unless the foreign key is temporarily dropped
(I saw somewhere that disabling the foreign key should be enough but it doesn't seem to work either).
Since there are other changes to be made on the same table, this foreign key also has to be dropped before the script can delete the table and re-create it. This part of the script is correctly generated. The problem is that this part appears after the 'DROP
INDEX' instruction.
So when generating the update script, SSDT tries to drop the index BEFORE dropping the foreign key. And I can't drop the foreign key in my custom pre-deployment script, otherwise the update script would fail when trying to delete it again.
Shouldn't SSDT be smart enough to drop the constraint before the index? Is it a bug or did I forget to set an option? If it's not a bug, what can I do apart from doing it manually?
Thank you for your helpHi Elsa,
That sounds like a bug. Could you please file a Connect issue for this at
https://connect.microsoft.com/SQLServer/feedback/CreateFeedback.aspx using the category "Developer Tools (SSDT, BIDS, etc.)"? We're trying to track all bugs through
Connect so that you can tell when we have fixed the issue and we can request more information.
A workaround for this issue might be to write a pre-deployment script for your project to drop the foreign key prior to deployment. A pre-deployment script can be added to your project by right-clicking on the
project in solution explorer and then clicking on Add > Script... and selecting Pre-Deployment Script from the list.
Thanks! -
Query the name of the parent table in a foreign key constraint
Hello,
Does anyone know how to query for the parent table name in a foreign key constraint? I don't see that relationship in ALL_CONS_COLUMNS or ALL_CONSTRAINTS.
Thanks in advance,
Michaelor try this...
SELECT rc.TABLE_NAME "PK_Table_Name",cc.TABLE_NAME "FK_Table_Name",
case when cc.column_name = rc.column_name
then c.TABLE_NAME || '(' || cc.COLUMN_NAME || ')'
else r.TABLE_NAME || '(' || rc.COLUMN_NAME || ') = ' ||c.TABLE_NAME || '(' || cc.COLUMN_NAME || ')' end as "TABLE_NAME(COLUMN_NAME)"
from all_constraints c,
all_constraints r,
all_cons_columns cc,
all_cons_columns rc
WHERE
r.table_name = upper('emp')
and c.CONSTRAINT_TYPE = 'R'
and c.R_OWNER = r.OWNER
and c.R_CONSTRAINT_NAME = r.CONSTRAINT_NAME
and c.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
and c.OWNER = cc.OWNER
and r.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
and r.OWNER = rc.OWNER
and cc.POSITION = rc.POSITION
ORDER BY r.TABLE_NAME; -
Foreign key mapped to a unique constraint
ok here is the issue
create table parent(col1 char, col2 char);
alter table parent add constraint pk_parent primary key(col1);
alter table parent add constraint uk_parent unique(col1,col2);
insert into parent values('A','7');
*1 row created.*
create table child(col1 char, col2 char);
alter table child add constraint fk_child_parent foreign key(col1,col2) references parent(col1,col2);
insert into child values('B','4');
insert into child values('B','4')
ERROR at line 1:
ORA-02291: integrity constraint (WILDGOD.FK_CHILD_PARENT) violated - parent key
not found
thats what i expect....but
insert into child values('B',NULL);
*1 row created.*
why does it let me do this, i realize its because col2 is NULL but shouldnt it still check for col1 to be in the parent?
Please clarify, thanks in advance.I see the same & am not sure why either.
SQL> @a
SQL> create table parent(col1 char, col2 char);
Table created.
SQL> alter table parent add constraint pk_parent primary key(col1);
Table altered.
SQL> alter table parent add constraint uk_parent unique(col1,col2);
Table altered.
SQL>
SQL> insert into parent values('A','7');
1 row created.
SQL> create table child(col1 char, col2 char);
Table created.
SQL> alter table child add constraint fk_child_parent foreign key(col1,col2) references parent(col1,col2);
Table altered.
SQL>
SQL> insert into child values('B','4');
insert into child values('B','4')
ERROR at line 1:
ORA-02291: integrity constraint (DBADMIN.FK_CHILD_PARENT) violated - parent key not found
SQL>
SQL> insert into child values('B',NULL);
1 row created.
SQL>
SQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production -
Foreign key constraint on multi-column primary key accepts 1 empty column!?
Hi, we have a reference table with a two-column primary key. In the child table there is a non-mandatory foreign key constraint to this table. So if both child columns are null it's ok too. But now we see that if one of the two child table columns that build up the foreign key is null, the other column can have any (non-existant in the master-tabel) value you like!? That does not make sense.
Can anyone explain this to me???
Regards, Paul.Paul, I believe that this is in accordance to the ANSI SQL standard requirement for the treatment of nulls in a multi-column FK. In any case Oracle specifically states this is the way FK work From the 10 Concepts manual, Ch 21 Data Integrity, topic Nulls and Foreign Keys:
The relational model permits the value of foreign keys either to match the referenced primary or unique key value, or be null. If any column of a composite foreign key is null, then the non-null portions of the key do not have to match any corresponding portion of a parent key. <<HTH -- Mark D Powell -- -
Primary Key and Foreign Key Constraints
Hi All,
I would like to know PRIMARY KEY and FOREIGN KEY constraints on existing oracle tables. Could any one suggest me how to find out.
Thanks,
REDYou can query DBA_CONSTRAINTS to get a list of all the constraints on table A and/or table B. The documentation I linked to gives a full list of the data you can see in DBA_CONSTRAINTS, but it includes things like the referenced table name and referenced constraint name for a foreign key constraint. If A is a parent of B or B is a parent of A, you could match up the parent's primary key constraint to the child's foreign key constraint.
More generally, though, if you don't know that one of the tables is a parent of the other, figuring out how to join the two tables is probably not something that can be done using just the Oracle data dictionary. You would probably need an understanding of the data model being used to figure out what intermediate table(s) needed to be joined in order to relate rows in A to rows in B.
Justin
Maybe you are looking for
-
Is photoshop Cs6 compatibale with windows 8.1
I have problems to sign in afther re installation christiane. beerlandt
-
Changing pop-up for form validating
I have simple contact forms that are validated which makes sure the fields in the form are filled out and that it is a proper email address. I have 2 contact forms on the same page. On the first one the field name's and id's are "name", "email" and "
-
Can I upgrade from mac os x 10.6 to Mavericks ?
can I upgrade from mac os x 10.6 to Mavericks ?
-
ViewRow Method Action VS. ApplicationModule Method action in a Taskflow
Hello all, I have a method on my ViewRow which i dropped in my TaskFlow, whenever it was called i got a NoSuchElemenException. I created a method in my application module which calls the method on the ViewRow: MyViewRow vCurrentRow = (MyVie
-
How to become a linux-developer
I was wondering, how can I make something for linux community. But not testing packages and/or unstable programs. How to start writing some stuff that may be helpful ?