Can I make a unique constraint in Oracle on a combination of 2 columns from 2 different tables? - sql

Column A is the PK of table A. Column B is a column in table B. Column C is a FK is table B that references column A in table A.
Can I define a constraint that says that that a column B AND column C have to be unique? As in, I don't want any repeats of the same combination of values from A and B.
Here's one possibility i'm thinking about:
Create a unique ID column.
unique_id varchar2 GENERATED ALWAYS AS (B || '-' || FK that references column A) VIRTUAL
set it as unique
CONSTRAINT unique_id UNIQUE
If i go with this solution i'm confused about one thing. The docs say: "Virtual columns are not supported for index-organized, external, object, cluster, or temporary tables." Obviously, because they don't get stored like other columns. Would this be a problem if I wanted to make my tables clustered?

Yes, you can create a UNIQUE constraint on two columns. For example:
create table table_a (
a number(6) primary key not null
);
create table table_b (
b number(6) not null,
c number(6) not null,
constraint uq1 unique (b, c),
constraint fk1 foreign key (c) references table_a (a)
);
Then, if you try to insert it will fail for duplicates. For example:
insert into table_a (a) values (1);
insert into table_a (a) values (2);
insert into table_b (b, c) values (10, 1);
insert into table_b (b, c) values (10, 1); -- fails!
insert into table_b (b, c) values (10, 2);
See running example at db<>fiddle.

Related

How to insert multiple rows into table B, and update table A's null foreign keys with the new IDs?

I've found a million things sounding kind of similar on StackOverflow, but not my case exactly. I'll simplify as much as possible:
I have two tables as follows:
CREATE TABLE B (id uuid PRIMARY KEY);
CREATE TABLE A (id uuid PRIMARY KEY, b_id uuid REFERENCES b);
There are some NULL values in A.b_id. I am trying to create a migration that does the following:
For every row in A with no b_id, create a new row in B, and assign its id to A.b_id.
How can I accomplish this in one query?
Assuming you want a distinct entry in b for every row with a missing UUID in a:
WITH upd AS (
UPDATE a
SET b_id = gen_random_uuid()
WHERE b_id IS NULL
RETURNING b_id
)
INSERT INTO b (id)
SELECT b_id FROM upd;
db<>fiddle here
This works because it's a single command, and the FK reference is only enforced at the end of the command.
See:
SET CONSTRAINTS ALL DEFERRED not working as expected
Constraint defined DEFERRABLE INITIALLY IMMEDIATE is still DEFERRED?

Is there an order to how unique constraint violations occur in oracle sql?

Given that we have a table like this,
table name: my_table;
columns: id, a, b, c;
primary key: id;
unique constraints: a, (b, c);
I want to know whether there is an ordering to how the unique constraints would fail.
With this setting, I do the following insert
insert into my_table values (1,2,3,4);
And then I do the same insert once more. Can I be sure that this second insert will fail because of the primary key violation, and not because of the unique key constraints on the other columns?
And then, if I try to do this insert into my_table values (2,2,3,4);, is there a way for me to make sure which unique constraint would fail first (the one on column a or the one on columns (b,c))?

Insert data from one SQL Server table into another

I have to insert data from one table into another. The problem is that the table where the data has to be inserted into has a primary key.
Suppose there are 2 tables A and B.
A has two columns id (primary key) and name
B has two columns id and name
How can we insert data from table B into table A with the primary key column?
For example there are 2 tables A & B as you stated.
insert into A (id,name) values(2, 'Testing');
insert into B (id, foreign_key, name) values(1, 2, 'Hello');
Both tables have a primary key. Primary key of table A is used as a foreign key to connect to the table B so that they interact with each other
Here is its design:

SQL Constraint that one column value cannot be greater than another in a different table

This probably isn't a very nice question as its blending business logic with DB structure, but its not my decision so:
Is it possible to define a constraint the infers the value of one column (Table A, Column X) cannot be greater than the value of another (Table B, Column Y) referenced via a foreign key:
TABLE_A
ID (Primary Key)
X (int value)
TABLE_B
A_ID (Foreign Key to TABLE_A)
Y (int value)
i.e. I want to enforce that for all values of Y, Y < L where L is a value from X where TABLE_B.A_ID == TABLE_A.ID
I'm working with DB2.
Is it possible to define a constraint the infers the value of one column (Table A, Column X) cannot be greater than the value of another (Table B, Column Y) referenced via a foreign key:
No. That would require using a SELECT statement within a CHECK constraint, and DB2 doesn't support that. If it did support using a SELECT statement that way, it would look something like this.
ALTER TABLE_B
ADD CONSTRAINT TABLE_B_Y_LT_L
CHECK (Y < (SELECT X FROM TABLE_A WHERE TABLE_A.ID = TABLE_B.A_ID));
The SELECT statement would return a single value, because TABLE_A.ID is unique. But, like I said, DB2 doesn't support SELECT statements in check constraints. I don't think any current dbms does.
Workarounds
There are a couple of workarounds. First, you could write a trigger. Second, you could store column "X" in both tables, and use a foreign key constraint and a check constraint to implement your requirement.
-- Since "id" is unique, the combination of "id" and "x" is also unique.
-- Declaring "unique (id, x)" lets these two columns be the target of a
-- foreign key reference.
--
create table table_a (
id integer primary key,
x integer not null,
unique (id, x)
);
-- The foreign key references both columns in "table_a". The check constraint
-- indirectly guarantees that y < table_a.x.
--
create table table_b (
a_id integer not null,
a_x integer not null,
y integer not null,
primary key (a_id, a_x, y),
foreign key (a_id, a_x) references table_a (id, x),
check (y < a_x)
);
This is standard SQL. It should work in any current SQL dbms.

Using references in MYSQL

I got an answer to another question here:
DB Schema For Chats?
It's a great answer, but I am not understanding the bit about references. I can do SQL statements but I have never used references.
What are they used for?
How are they used?
Give an example please
The REFERENCES keyword is part of a foreign key constraint and it causes MySQL to require that the value(s) in the specified column(s) of the referencing table are also present in the specified column(s) of the referenced table.
This prevents foreign keys from referencing ids that do not exist or were deleted, and it can optionally prevent you from deleting rows whilst they are still referenced.
A specific example is if every employee must belong to a department then you can add a foreign key constraint from employee.departmentid referencing department.id.
Run the following code to create two test tables tablea and tableb where the column a_id in tableb references the primary key of tablea. tablea is populated with a few rows.
CREATE TABLE tablea (
id INT PRIMARY KEY,
foo VARCHAR(100) NOT NULL
) Engine = InnoDB;
INSERT INTO tablea (id, foo) VALUES
(1, 'foo1'),
(2, 'foo2'),
(3, 'foo3');
CREATE TABLE tableb (
id INT PRIMARY KEY,
a_id INT NOT NULL,
bar VARCHAR(100) NOT NULL,
FOREIGN KEY fk_b_a_id (a_id) REFERENCES tablea (id)
) Engine = InnoDB;
Now try these commands:
INSERT INTO tableb (id, a_id, bar) VALUES (1, 2, 'bar1');
-- succeeds because there is a row in tablea with id 2
INSERT INTO tableb (id, a_id, bar) VALUES (2, 4, 'bar2');
-- fails because there is not a row in tablea with id 4
DELETE FROM tablea WHERE id = 1;
-- succeeds because there is no row in tableb which references this row
DELETE FROM tablea WHERE id = 2;
-- fails because there is a row in tableb which references this row
Important note: Both tables must be InnoDB tables or the constraint is ignored.
The REFERENCES keyword shows a foreign key constraint, which means that:
FOREIGN KEY (`chat_id` ) REFERENCES `chats`.`chat` (`id` )
...the chat_id column in the current table can only contain values that already exist in the chat table, id column.
For example, if the CHAT.id column contains:
id
----
a
b
c
..you can not add any values other than a/b/c into the chat_id column.