[db2-as400] I have a table ENR_DATA that has column EnrollmentID as a primary key. This column is referred by many tables as a "foreign key". Is there a way to list down all those tables who refer to EnrollmentID of ENR_DATA table?
There are a few catalog views that each give just a part of the answer, and you have to join them all together.
SYSCST provides a list of constraints with the constrain type. From here we can select out Foreign Key constraints. TABLE_NAME in this table is the table that contains the foreign key.
SYSKEYCST provides a list of columns for a given Foreign Key, Primary Key, or Unique constraint along with the ordinal position of the column in the key, and the associated table name.
SYSREFCST provides the name of the Primary or Unique Key constraint that is referenced by a given Foreign Key Constraint.
From these three tables we can write the following SQL:
select cst.constraint_schema, cst.constraint_name,
fk.table_schema, fk.table_name, fk.ordinal_position, fk.column_name,
pk.table_schema, pk.table_name, pk.column_name
from qsys2.syscst cst
join qsys2.syskeycst fk
on fk.constraint_schema = cst.constraint_schema
and fk.constraint_name = cst.constraint_name
join qsys2.sysrefcst ref
on ref.constraint_schema = cst.constraint_schema
and ref.constraint_name = cst.constraint_name
join qsys2.syskeycst pk
on pk.constraint_schema = ref.unique_constraint_schema
and pk.constraint_name = ref.unique_constraint_name
where cst.constraint_type = 'FOREIGN KEY'
and fk.ordinal_position = pk.ordinal_position
and pk.table_name = 'ENR_DATA'
and pk.column_name = 'ENROLLMENTID'
order by cst.constraint_schema, cst.constraint_name;
This will get you the table names that reference 'ENR_DATA' via foreign key. Note I have ENROLLMENTID in all upper case. That is how DB2 for i stores all column names unless they are quoted using "".
DB2 on IBM i (AS 400) offers a list of all system tables, the system catalog. It is the place where metadata is stored. One of the views, SYSCST, is the view with all constraints, the view SYSCSTCOL has information about the constraint columns, and SYSCSTDEP stores the dependencies.
So you would query SYSCST, SYSCSTCOL and SYSCSTDEP for finding the details.
Related
(One image, tousands of words)
I'd made few tables that are inherited between themselves. (persons)
And then assign child table (address), and relate it only to "base" table (person).
When try to insert in child table, and record is related to inherited table, insert statement fail because there is no key in master table.
And as I insert records in descendant tables, records are salo available in base table (so, IMHO, should be visible/accessible in inherited tables).
Please take a look on attached image. Obviously do someting wrong or didn't get some point....
Thank You in advanced!
Sorry, that's how Postgres table inheritance works. 5.10.1 Caveats explains.
A serious limitation of the inheritance feature is that indexes (including unique constraints) and foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint. Thus, in the terms of the above example:
Specifying that another table's column REFERENCES cities(name) would allow the other table to contain city names, but not capital names. There is no good workaround for this case.
In their example, capitals inherits from cities as organization_employees inherits from person. If person_address REFERENCES person(idt_person) it will not see entries in organization_employees.
Inheritance is not as useful as it seems, and it's not a way to avoid joins. This can be better done with a join table with some extra columns. It's unclear why an organization would inherit from a person.
person
id bigserial primary key
name text not null
verified boolean not null default false
vat_nr text
foto bytea
# An organization is not a person
organization
id bigserial not null
name text not null
# Joins a person with an organization
# Stores information about that relationship
organization_employee
person_id bigint not null references person(id)
organization_id bigint not null references organization(id)
usr text
pwd text
# Get each employee, their name, and their org's name.
select
person.name
organization.name
from
organization_employee
join person on person_id = person.id
join organization on organization_id = organization.id
Use bigserial (bigint) for primary keys, 2 billion comes faster than you think
Don't enshrine arbitrary business rules in the schema, like how long a name can be. You're not saving any space by limiting it, and every time the business rule changes you have to alter your schema. Use the text type. Enforce arbitrary limits in the application or as constraints.
idt_table_name primary keys makes for long, inconsistent column names hard to guess. Why is the primary key of person_address not idt_person_address? Why is the primary key of organization_employee idt_person? You can't tell, at a glance, which is the primary key and which is a foreign key. You still need to prepend the column name to disambiguate; for example, if you join person with person_address you need person.idt_person and person_address.idt_person. Confusing and redundant. id (or idt if you prefer) makes it obvious what the primary key is and clearly differentiates it from table_id (or idt_table) foreign keys. SQL already has the means to resolve ambiguities: person.id.
I am basically trying to replicate data from a table on one server to another.
I have two identical databases on the servers. I created a foreign table called opentickets_aux1 to represent the opentickets table on the secondary server on the primary server. Both have a primary key of incidentnumber. I can access the data in the foreign table just fine but when I try the following SQL,I get "ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification."
INSERT INTO opentickets_aux1 (SELECT * FROM opentickets)
ON CONFLICT (incidentnumber)
DO
UPDATE SET
status = EXCLUDED.status,
lastmodifieddate = EXCLUDED.lastmodifieddate
I want to update a few columns if the primary key exist. I use this statement for other queries and they work when its a local table. Any ideas?
A foreign table cannot have a primary key constraint, because PostgreSQL wouldn't be able to enforce its integrity. Therefore, you cannot use INSERT ... ON CONFLICT with foreign tables.
Your idea also does not handle rows that are deleted on the foreign server, but maybe that's intentional.
If you want a local copy of a foreign table, the easiest way would be to create a materialized view on the foreign table.
If that is not your desire (perhaps because you don't want to copy deletions), you'd have to use statements like
INSERT INTO localtable
SELECT * FROM foreigntable f
WHERE NOT EXISTS
(SELECT 1 FROM localtable l
WHERE f.id = l.id);
UPDATE localtable l
SET /* all columns from f */
FROM foreigntable f
WHERE f.id = l.id
AND (f.*) <> (l.*);
Table: A
columns names
--------------------------
PK varchar |datasource
PK int |programid
int |workspaceid
composite pk key of: datasource and programid
Table: B
columns names
---------------------------------------
PK varchar | datasource
PK int | quantitycontractid
int | workspaceid
composite pk key of: datasource and quantitycontractid
I need to make relationship between those tables but using workspaceid and datasource. So i try as usual:
ALTER TABLE A
ADD CONSTRAINT fk_relation
FOREIGN KEY (workspaceid, datasource)
REFERENCES B(workspaceid, datasource)
I am getting following error:
there is no unique constraint matching given keys for referenced table
"B"
You need to add UNIQUE key to B(workspaceid, datasource) before you consider that as a foreign key in table A. This is to ensure a correct one to one or one to many relationships between the two tables.
ALTER TABLE B
ADD CONSTRAINT unq_contraint
UNIQUE KEY (workspaceid, datasource)
The error makes perfect sense to me, your table B doesn't have any unique index or primary key linked to workspaceid. Having said that, your table structure for B looks kinda weird to me. Most databases have a primary key that is an autoincrement and one or more foreign keys linking to other tables. You seem to have made your primary key a combination of multiple foreign keys. While this works, you're gonna have issues like you described and have complicated joins when your query your tables.
Vishal R already answered on how to fix your problem.
PostgreSQL 11.1
How can "Editing" of a record be transmitted to dependent records?
Summary of my issue:
The master table, disease, needs a unique constraint on the description column. This unique constraint is needed for foreign key ON UPDATE CASCADE to its children tables.
To allow for a temporary violation of the unique constraint, it must be made deferrable. BUT A DEFERABLE CONSTRAINT CAN NOT BE USED IN A FOREIGN KEY.
Here is the situation.
The database has 100+ tables (and keeps on growing).
Most all information has been normalized in that repeating groups of information have been delegated to their own table.
Following normalization, most tables are lists without duplication of records. Duplication of records within a table is not allowed.
All tables have a unique ID assigned to each record (in addition to a unique constraint placed on the record information).
Most tables are dependent on another table. The foreign keys reference the primary key of the table they are dependent on.
Most unique constraints involve a foreign key (which in turn references the primary key of the parent table).
So, assume the following schema:
CREATE TABLE phoenix.disease
(
recid integer NOT NULL DEFAULT nextval('disease_recid_seq'::regclass),
code text COLLATE pg_catalog."default",
description text COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT disease_pkey PRIMARY KEY (recid),
CONSTRAINT disease_code_unique UNIQUE (code)
DEFERRABLE,
CONSTRAINT disease_description_unique UNIQUE (description)
,
CONSTRAINT disease_description_check CHECK (description <> ''::text)
)
CREATE TABLE phoenix.dx
(
recid integer NOT NULL DEFAULT nextval('dx_recid_seq'::regclass),
disease_recid integer NOT NULL,
patient_recid integer NOT NULL,
CONSTRAINT pk_dx_recid PRIMARY KEY (recid),
CONSTRAINT dx_unique UNIQUE (tposted, patient_recid, disease_recid)
,
CONSTRAINT dx_disease_recid_fkey FOREIGN KEY (disease_recid)
REFERENCES phoenix.disease (recid) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT dx_patients FOREIGN KEY (patient_recid)
REFERENCES phoenix.patients (recid) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE RESTRICT
)
(Columns not involved in this question have been removed. :) )
There are many other children tables of disease with the same basic dependency on the disease table. Note that the primary key of the disease table is a foreign key to the dx table and that the dx table uses this foreign key in a unique constraint. Also note that the dx table is just one table of a long chain of table references. (That is the dx table also has its primary key referenced by other tables).
The problem: I wish to "edit" the contents of the parent disease record. By "edit", I mean:
change the data in the description column.
if the result of the change causes a duplication in the disease table, then one of the "duplicated" records will need to be deleted.
Herein lies my problem. There are many different tables that use the primary key of the disease table in their own unique constraint. If those tables ALSO have a foreign key reference to the duplicated record (in disease), then cascading the delete to those tables would be appropriate -- i.e., no duplication of records will occur.
However, if the child table does NOT have a reference to the "correct" record in the parent disease table, then simply deleting the record (by cascade) will result in loss of information.
Example:
Disease Table:
record 1: ID = 1 description = "ABC"
record 2: ID = 2 description = "DEF"
Dx Table:
record 5: ID = 5 refers to ID=1 of Disease Table.
Editing of record 1 in Disease table results in description becoming "DEF"
Disease Table:
record 1: ID = 1 "ABC" --> "DEF"
I have tried deferring the primary key of the disease table so as to allow the "correct" ID to be "cascaded" to the child tables. This causes the following errors:
A foreign key can not be dependent on a deferred column. "cannot use a deferrable unique constraint for referenced table "disease"
additionally, the parent table (disease) has no way of knowing ahead of time if its children already have a reference to the "correct" record so allowing deletion, or if the child needs to change its own column data to reflect the new "correct" id.
So, how can I allow a change in the parent table (disease) and notify the child tables to change their column values -- and delete within them selves should a duplicate record arise?
Lastly, I do not know today what future tables I will need. So I cannot "precode" into the parent table who its children are or will be.
Thank you for any help with this.
Setting a primary key, a composite of 3 columns, generates an index, which can be viewed with:
select t.relname as tbl, i.relname as idx, a.attname as col
from pg_class t, pg_class i, pg_index ix, pg_attribute a
where t.oid = ix.indrelid
and i.oid = ix.indexrelid
and a.attrelid = t.oid
and a.attnum = any(ix.indkey)
and t.relkind = 'r'
and t.relname not like 'pg%'
order by t.relname, i.relname;
The table is "customer" as defined in the TPC-C benchmarking guide. The question I have is, when creating the foreign key on the table, as necessitated by the guide, does one need to create a corresponding index.
Given that the 2 columns for the foreign key match the first two columns of the primary key, would the index generated as part of the primary key constraint suffice?
Table & key DDL:
create table customer (c_id numeric,c_d_id numeric,c_w_id numeric ..);
alter table customer add constraint pk_customer
primary key (c_w_id, c_d_id, c_id) ;
alter table customer add constraint fk_cust_district
foreign key (c_w_id, c_id) references district (d_w_id, d_id);
The reason for the question is that in Oracle and SQL Anywhere one need not create an index and the respective optimizers would make use of whichever index assisted with improved referral performance, in this case, the 2 column prefix of the index generated as part of the primary key constraint.
The way your tables are created, the primary key index cannot support the foreign key constraint well because the columns of the foreign key definition are not at the beginning of the primary key constraint definition.
The primary key index is better than nothing, though: at least it can be scanned for c_w_id (with c_id as a filter), but not for both columns at the same time, as would be most efficient.
So PostgreSQL will make use of the index at hand, but it will still not be very efficient.
Unless there is a good reason that the primary key columns are defined in this order, I suggest that you swap the second and third column in the primary key definition. Then the index is a perfect fit for the foreign key constraint.
If that is not feasible, create a second index on (c_w_id, c_id).
(This would be just the same on Oracle, by the way, except that they have an index skip scan of – in my opinion – questionable merits.)