I want to write a query that presents for every event (tbl_events) all objects (tbl_objects) related to it (relation type — M:N).
I have a problem with tables that are connection tables (association class) that holds only foreign keys of the 2 tables that connects.
For instance, tbl_events is connected with a connection table named tbl_object_has_tbl_events to tbl_objects.
Here is a structure of connected tables:
tbl events has: eventID, eventName
tbl_object has: objectID, objectName
tbl_object_has_tbl_events: eventID, objectID
Here is what I tried to write:
IList dataList = (from dEvent in App.glidusContext.tbl_events.
join dObject in App.glidusContext.tbl_objects
on dEvent.tbl_objects equals dObject.objectID
select new { dEvent.eventName, dObject.objectName}).ToList();
I can't reach the connection table tbl_object_has_tbl_events
How I can implement such query, when I have an M:N relationship?
UPDATE Generation of Many-to-many relationship:
-- -----------------------------------------------------
-- Table tbl_events
-- -----------------------------------------------------
CREATE TABLE tbl_events (
eventID INT NOT NULL IDENTITY,
eventName NVARCHAR(100) NOT NULL,
PRIMARY KEY (eventID));
-- -----------------------------------------------------
-- Table tbl_objects
-- -----------------------------------------------------
CREATE TABLE tbl_objects (
objectID INT NOT NULL IDENTITY,
objectName NVARCHAR(100) NOT NULL,
PRIMARY KEY (objectID));
-- -----------------------------------------------------
-- Table tbl_objects_has_tbl_events
-- -----------------------------------------------------
CREATE TABLE tbl_objects_has_tbl_events (
objectID INT NOT NULL,
eventID INT NOT NULL,
PRIMARY KEY (objectID, eventID),
CONSTRAINT fk_tbl_objects_has_tbl_events_tbl_objects
FOREIGN KEY (objectID)
REFERENCES tbl_objects (objectID)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_tbl_objects_has_tbl_events_tbl_events
FOREIGN KEY (eventID)
REFERENCES tbl_events (eventID)
ON DELETE CASCADE ON UPDATE CASCADE);
The entity data model doesn't show tables that only contain FK's. So in your case the Events entity will have a navigation property Objects and your Object entity will have a navigation property Events.
So to get your information you could write a query like this:
IList dataList = (from dEvent in App.glidusContext.tbl_events
from dObject in dEvent.Objects
select new { dEvent.eventName, dObject.objectName}).ToList();
Related
In code, I tried with #Interleaved in 1-many relationship at non-owning side to get child list. Could anyone help with below questions:
How to implement bidirectional relationship e.g. get parent from child for 1-1, 1-many relationship
Regarding many-many relationship, what are best practices to implement it and how to implement bidirectional relationship for it.
Thank you very much.
Cloud Spanner currently doesn't offer a way to enforce foreign-key constraints between non-interleaved tables. You will have to enforce such constraints in your application logic. You could use DML statements in Cloud Spanner(that come with the ability to read-your-writes in a Cloud Spanner transaction) to enforce these constraints at insert time by inserting into your tables as follows:
INSERT INTO Referenced(key1,value1) VALUES ('Referenced','Value1');
INSERT INTO Referencing(key2, value2, key1)
SELECT 'Referencing', 'Value2', key1 FROM Referenced WHERE
key1 = 'Referenced';
Running the two statements in a read-write transaction will ensure that the PK-FK relationship between the Referenced and Referencing table is always maintained at insert time. You may have to similarly modify update requests/SQL update statements in your application logic to enforce the PK-FK constraint for updates.
For a 1-many relationship, when using interleaved tables, then the child row's primary key already contains the primary key of its parent, so it is trivial to get the parent row.
CREATE TABLE parent (
parent_key INT64 NOT NULL,
...
) PRIMARY KEY (parent_key);
CREATE TABLE child (
parent_key INT64 NOT NULL,
child_key INT64 NOT NULL,
...
) PRIMARY KEY (parent_key, child_key),
INTERLEAVE IN PARENT parent ON DELETE CASCADE;
If for some reason you do not have the key of the parent, and only the key of the child, then for efficiency you would need to create an index for the reverse lookup:
CREATE INDEX child_to_parent_index
ON child (
child_key
);
and force use of that index when performing the query for the parent:
SELECT
p.*
FROM
parent as p
JOIN
child#{FORCE_INDEX=child_by_id_index} AS c ON p.parent_key = c.parent_key
WHERE
c.child_key = #CHILD_KEY_VALUE;
Many-many relationships would have to be implemented using a 'mapping' table linking table1-key to table2-key.
You will also need a top-level index to get efficient reverse-lookups, and use the FORCE_INDEX directive as above in your queries.
And as #adi mentioned, foreign key constraints would have to be enforced by the application.
CREATE TABLE table1 (
table1_key INT64 NOT NULL,
...
) PRIMARY KEY (table1_key);
CREATE TABLE table2 (
table2_key INT64 NOT NULL,
...
) PRIMARY KEY (table2_key);
CREATE TABLE table1_table2_map (
table1_key INT64 NOT NULL,
table2_key INT64 NOT NULL,
) PRIMARY KEY (table1_key, table2_key);
CREATE INDEX table2_table1_map_index
ON table1_table2_map (
table2_key
) STORING (
table1_key
);
Your application would be responsible for keeping the referential integrity of the mapping table - deleting the mapping rows when rows in table1 or table2 are deleted
If you want to use interleaved tables, then if your application needs to perform bi-directional lookups, you may have to create 2 mapping tables - as a child of each parent, so that finding the mappings from both directions are equally efficient.
CREATE TABLE table1 (
table1_key INT64 NOT NULL,
...
) PRIMARY KEY (table1_key);
CREATE TABLE table2 (
table2_key INT64 NOT NULL,
...
) PRIMARY KEY (table2_key);
CREATE TABLE table1_table2_map (
table1_key INT64 NOT NULL,
table2_key INT64 NOT NULL,
) PRIMARY KEY (table1_key, table2_key),
INTERLEAVE IN PARENT table1 ON DELETE CASCADE;
CREATE TABLE table2_table1_map (
table2_key INT64 NOT NULL,
table1_key INT64 NOT NULL,
) PRIMARY KEY (table2_key, table1_key),
INTERLEAVE IN PARENT table2 ON DELETE CASCADE;
Note that the application needs to keep both of these mapping tables up to date -- ie when deleting a row from table1, the application has to get the referenced table2_key values and delete the mappings from the table2_table1_map (and vice versa).
currently i am facing an oracle constraints issue.
After submiting an insert my foreign key constraint(s) won't fire. What it should do is giving two tables the same ID, but unfortunately only the one table with the primary Key is giving an ID. The column with the foreign key in the second table remains null.
For Instance: Insert into table t1 (t1_id,name, dpt) values (value1 (trigger with autoincrement for id), value2, value3); The same procedure is behind table 2, table 3 ... All constraints are written correctly
Table 1 (Emp)
ID Name Department
1 Joe HR
Table 2 (Projects)
ID Project EmpID
1 new (null) -> must be 1
Thank you in advanced.
Constraint: ALTER TABLE "PROJECTS" ADD CONSTRAINT "EMP_FK" FOREIGN KEY ("EMP_ID")
REFERENCES "EMP" ("EMP_ID") ON DELETE CASCADE ENABLE
Trigger: create or replace TRIGGER Projects_TRG BEFORE
INSERT ON Projects FOR EACH ROW BEGIN :NEW.Project_ID := Projects_SEQ.NEXTVAL;
END;
How do i manage to populate the parent id from the parent table into the child table?
Please note that I used different names in my application.
It appears that you've misunderstood the purpose of a foreign key constraint. A foreign key constraint does NOT automatically propagate constraint values from the parent table to the child table. The purpose of the constraint is to ensure that the values of the key column in the child table, when populated, have matching values in the key column of the parent table. Your application is responsible for ensuring that the key column on the child table is populated with the appropriate value. The constraint doesn't do that for you. It's also perfectly legitimate to have a NULL in the key column of the child table, assuming the the column on the child table doesn't have a NOT NULL constraint on it.
What I have is several tables...two of them being:
CREATE TABLE Orders(
oid int NOT NULL,
rdate date,
sdate date,
cid int NOT NULL,
eid int NOT NULL,
PRIMARY KEY (oid),
FOREIGN KEY (cid) REFERENCES Customer(cid),
FOREIGN KEY (eid) REFERENCES Employee(eid));
CREATE TABLE PartOrder(
poid int NOT NULL,
pid int NOT NULL,
oid int NOT NULL,
PRIMARY KEY (poid),
FOREIGN KEY (pid) REFERENCES Part(pid),
FOREIGN KEY (oid) REFERENCES Orders(oid));
What I need to do is this:
Create and execute a query that deletes all PartOrder records for Orders for which the shipping date is in the past.
So, I came up with this...
DELETE
FROM (SELECT * FROM PartOrder FULL OUTER JOIN Orders ON partorder.oid=orders.oid)
WHERE sdate<sysdate;
This is giving me this error:
ORA-01752: cannot delete from view without exactly one key-preserved table
Can someone offer me some insight?
I'd write this as something like
DELETE FROM PARTORDER
WHERE POID IN (SELECT p.POID
FROM PARTORDER p
INNER JOIN ORDERS o
ON o.OID = p.OID
WHERE o.SDATE < SYSDATE);
Best of luck.
How can I make a constraint on Entity Framework to read a foreign key relation from table cars to vehicle (for example) as 0..1 -> 1 instead of * -> 1?
I have tables
create TABLE [dbo].[Vehicles](
[Id] [int] IDENTITY(1,1) NOT NULL primary key,
<rest of the columns>
)
create TABLE [dbo].[Cars](
[Id] [int] NOT NULL,
<rest of the columns>
)
and foreign key:
alter table [Cars] add foreign key(id) references [Vehicles](id)
when I create a model from the DB, it is created as * -> 1 an I cant change:
I know I manually change the association between the two entities but it doesn't matter because it doesn't change the constraint
I need to do that to set the baseType property of Cars to Vehicle to Implement a Inheritance.
Currently I'm getting this error:
Multiplicity is not valid in Role 'BoatsTPT' in relationship
'FK__BoatsTPT__Id__117F9D94'. Because the Dependent Role refers to the
key properties, the upper bound of the multiplicity of the Dependent
Role must be 1.
You must first make Id column in your Cars table a primary key otherwise it is not one-to-one relation.
Something like:
create table Employee(
ID int primary key,
Name nvarchar(200)
IDArea int foreign key references Area(ID)
);
go
create table Area(
ID int primary key,
Name nvarchar(200)
);
Does something like this exist in Oracle?
Yes, just leave out the "GO" keywords and put the statements in a file:
create table Area(
ID int primary key,
Name nvarchar2(200)
);
create table Employee(
ID int primary key,
Name nvarchar2(200),
IDArea int references Area(ID)
);
You must create the Area primary key before the foreign key that references it, so I have swapped these around. Also the foreign key syntax is slightly different in Oracle.
You should first create the master table, forget nvarchar datatype, and eventually the script would be :
create table Area(
ID number primary key,
Name varchar2(200)
);
create table Employee(
ID number primary key,
Name varchar2(200) ,
IDArea number, constraint fk_idarea foreign key (idarea) references Area(ID)
);