How to insert a range of keys in another column - sql

I've just gone blank. I have a many to many relationship with three tables. Lets call them A, B and C. C stores the primary keys of the other two tables.
Now, I would like to insert all primary keys from table A, and lets say primary key 1 from B into table C. I just don't get it. All I came up with was some stored procedure that runs with a cursor through all primary keys of A and insert them with 1 into C. Guess, there is a much easier way to do this.
Any help appreciated!

I would say:
INSERT INTO C
SELECT A_Id, 1
FROM A
where 1 is the single primary key from B.
Check here for more info on the INSERT statement.

Related

Reading an SQL record and all descendants

What would be the most efficient way to selectively read records from a SQL table, along with all their descendants - i.e., records in other tables with different schemas but of the same database, referencing the starting table via foreign keys?
For example, the following 4 tables have a primary key called id and records in Table A are referenced from the other 3 tables via the column x_id, where x = B, C, or D and x_id is the foreign key pointing to a record of Table X with primary key id.
Table A: id
Table B: id, a_id
Table C: id, a_id, b_id
Table D: id, a_id, c_id
Assuming that somehow the application knows the "graph" of table foreign key dependencies and thus can enumerate all "children" of a record (i.e., all records from other tables directly referencing it via its id), the data can be retrieved via multiple SELECT queries. That, however, becomes very slow for large tables.
Is there any more efficient way of getting the same information?

Automatically populate SQL column based on foreign key constraint

Table 1:
parent_id string_id
5001 a
8759 b
3957 c
string_id is the primary key for Table 1.
parent_id has an UNIQUE constraint on it.
Table 2:
child_id parent_id string_id
1 5001 a
2 8759 b
3 3957 c
child_id is the primary key for Table 2.
string_id is the foreign key to Table 1.
When I populate new row into Table 2, I do NOT want to insert the parent_id in my query by joining/merging Table 1.
INSERT INTO table_2 (string_id)
VALUES ('a'),
('b'),
('c')
Could anyone give me suggestion whether SQL can populate the parent_id automatically by using built in relationship (e.g. constraint, foreign keys, cascade)? If join is the only way, could you also let me know so that I can stop investigating?
Basically, I want to know what is the most elegant way of solving this problem. I could use join with INSERT, but I think that is an ugly query for such a simple functionality.
Thank you.
The purpose of storing tables with foreign key constraints is so that the data does not need to be duplicated. SQL then offers the JOIN for looking up values.
I would strongly encourage you to use JOIN to look up the parent_id when you need it. If you like, you can write the query once and use a JOIN -- and then anyone using the view would have the parent_id.

Database design queries regarding inheritance and foreign key references

I have a query regarding a design problem that I faced …
There is a table A with subtypes B and C. Table A has an attribute type which tells whether the type is B or C. The common attributes of B and C are in A .
The problem is that there are no extra attributes for B .. all attributes required for B are in A already. However , there are extra attributes for C.
Is it an acceptable solution if I make tables A and C only ??… to extract entities of B I will query through the type attribute from table A
Can you refer any material ?
I also had a another confusion where table A has subtypes B,C,D . Table Z has a column that requires a value of primary id of either B or C but NOT D.
I thought of adding the primary id column of A as a foreign key reference to Z’s column and then making a trigger to ensure that the id isn't D ...
Can anyone please comment ?
Thank you !
Many people just enforce all these rules in application code. That is, they "simply" don't insert wrong data. Of course this is very fragile and depends on writing perfect application code at all times. So we want the database to enforce the constraints instead, so that wrong data can never be inserted.
CREATE TABLE A (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL,
unique key (id, type)
);
CREATE TABLE B (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL DEFAULT 'B',
FOREIGN KEY (id, type) REFERENCES A(id, type)
);
If you can force B.type to always be 'B' (CHECK constraint, trigger, or reference a one-row lookup table) then it can of course reference parent rows in A where type='B'. And do something similar in tables C and D, so then each row of A can be referenced by a row from only one sub-type table.
That is, if A.type is 'B' on a given row, and C.type can only be 'C', then no row of C can reference any row where A.type is 'B'.
Now if you want table Z to reference B or C but not D, you can reference by id and type, so Z also has its own type column. You can restrict Z.type by using a lookup table:
CREATE TABLE Ztypes (
type CHAR(1) PRIMARY KEY
);
INSERT INTO Ztypes VALUES ('B'), ('C');
CREATE TABLE Z (
id INT PRIMARY KEY,
Aid INT NOT NULL,
type CHAR(1) NOT NULL,
FOREIGN KEY (Aid, type) REFERENCES A(id, type),
FOREIGN KEY (type) REFERENCES Ztypes(type)
);
You've already got the answer you were looking for. But for other who run across this, it's worth researching two techniques: Class Table Inheritance and Shared Primary Key.
These two techniques used together make it fast, simple and easy to join A's data with either B's or C's data. And in this pattern, B contains only the key, but still contains usefull informaton.
Both of these techiques have their own tags.

Need help adding a constraint to check values across tables in SQL Server 2000

I have two tables and I want to use the database to enforce a constraint against them.
Table A has a one to many relationship with table B, that is many table B rows belong to exactly one table A row. Table B has a column of the Table A primary key that it belongs to. Anyway, I want to add a column to both table A and table B where the value of it in a table A record must equal the value of it in the corresponding table B records.
I want to tell SQL Server 2000 to disallow updates or additions of table B records unless the values in the sister columns are the same. How can I do this? I tried using a check constraint but it doesn't like subqueries. Will I have to venture into the world of triggers? Is there another way?
Any help would be appreciated.
Thanks
Isaac
What you're trying to do sounds like a foreign key relationship - but you already seem to have that (Table B has a column of Table A primary key).
I don't think you can define such a constraint - CHECK constraints cannot span tables, as far as I know. So in the end, you will probably need to use triggers instead on both tables to achieve this.

1 to 1 relationship with exactly one of multiple tables

OK, I hope I'll be able to make clear what my problem is:
I have a database with 5 tables. Let's call them A and B, V_1, V_2, and V_3. A and B represent a list of things to be done. These actions are described in the V_i tables. Now, A represents sort of a template of stuff that has to be done with a certain type of item. B, on the other hand, describes what has to be done (or has been done) with a concrete instance if the abstract item described by A. So in OOP terminology one might say that A represents a class and B represents an instance of A. Whenever something is inserted into table B, the related data from table A is copied, so that it can be modified for that specific item without affecting A.
Okay, so here is the actual problem: How do I model this properly? My main concern is that each record in V_i must not be linked to both A and B. It has to be a 1 to 1 relationship with EITHER A OR B. Also, V_i and V_j must not be linked to the same record in A or B. I have no clue how to do this properly. The current structure looks like this:
A and B have a PK called ID. Each V_i also has a PK called ID and two FKs that referene A or B, let's call them A_ID and B_ID. Now, the current implementation ensures that either A_ID or B_ID is NULL, but not both. However, I was wondering if there is a better way to do this. Additionally, there is the problem that multiple V_i could reference the same entry in A or B.
So, I hope my problem is clear. Is there a way to properly model this with relational databases without relying on external code to enforce the constraints? Thanks for your input in advance.
Best regards
David
In relational theory, one-to-one relationships are generally translated to a single table in the physical model. This single table would contain rows from both tables and you would use check constraints to determine the type of the row. This is by far the simplest way to get reliable 1-to-1 relationships.
First thing: when designing a database, you express relations between records not tables.
You are expressing your problem with an OO point of view. This paradigm cannot be used to design tables (SQL being a declarative language).
Otherwise, you can add constraints on your table ensuring your predicate.
Maybe Oracle offers other possibilities I don't know.
The most common way to model the class - instance relationship in rdbs is
Class = table
Instance = row
Think about it: you insert a new row for each new instance; where you do not insert data, defaults are inserted, which give you class data; and triggers give you class-level behaviours.
Alternatively, give A and B the same primary key, and set the PK of B to be an FK to the PK of A. When a row is included in B, the DBMS will check that a "parent" row exists in A. Probably needs drawing
+--------+ +--------+
|Table A | |Table B |
+--------+ +--------+
|id (PK) |<--|id* (PK)|
|col1 | |colB1 |
| ... | | ... |
+--------+ +--------+
Preface: This is a bad design, as others have noted.
Assumptions:
create table a (a_id number primary key);
create table b (b_id number primary key);
create table v1
(v1_id number primary key, a_id number references a, b_id number references b);
create table v2
(v2_id number primary key, a_id number references a, b_id number references b);
create table v3
(v3_id number primary key, a_id number references a, b_id number references b);
Mandating that in any of the V_i tables that exactly one of the ids from A or B is required (but not both) is pretty easy.
alter table V1
add constraint v1_check check
( (a_id is null and b_id is not null)
or (a_id is not null and b_id is null)
);
If you want to extend that constraint so that exactly one of the ids from A or B is present and that value exists in one and only one row:
create unique index v1_check_unique on v1 ( coalesce (a_id, b_id) );
The hard part is making sure that the ids from A and B exist in one and only one of the V_i tables. That can't be done at DML time, but it can be enforced at commit time.
create materialized view log on v1 with rowid;
create materialized view log on v2 with rowid;
create materialized view log on v3 with rowid;
CREATE MATERIALIZED VIEW CROSS_TABLE
REFRESH FAST ON COMMIT
AS
SELECT V1_ID AS V_ID, 'V1' AS TABLE_NAME, ROWID AS ROW_ID,
COALESCE (A_ID, B_ID) AS OTHER_ID FROM V1
UNION ALL
SELECT V2_ID AS V_ID, 'V2' AS TABLE_NAME, ROWID AS ROW_ID,
COALESCE (A_ID, B_ID) AS OTHER_ID FROM V2
UNION ALL
SELECT V3_ID AS V_ID, 'V3' AS TABLE_NAME, ROWID AS ROW_ID,
COALESCE (A_ID, B_ID) AS OTHER_ID FROM V3
/
ALTER TABLE CROSS_TABLE ADD CONSTRAINT CROSS_TABLE_UNIQUE UNIQUE (OTHER_ID);
This appears to work - but not as awesomely as you'd hope. Oracle can't enforce that uniqueness across the tables at statement time because session A isn't allowed to take into account any other changes other sessions might be making. It can only enforce that uniqueness at commit time.
The following test case fails when run against empty tables - and rolls back the entire transaction, as it can't deduce which is causing the failure. Caveat emptor.
INSERT INTO A VALUES (1);
INSERT INTO B VALUES (1);
INSERT INTO V1 (V1_ID, A_ID, B_ID) VALUES (1, 1, NULL);
INSERT INTO V2 (V2_ID, A_ID, B_ID) VALUES (1, 1, NULL);
COMMIT;