Duplicate key in foreign table - sql

I have these Oracle tables:
CREATE TABLE AGENT(
ID INTEGER NOT NULL,
GROUP_ID NUMBER(38,0),
........
)
/
CREATE INDEX IX_RELATIONSHIP_AG_GROUP ON AGENT (GROUP_ID)
/
ALTER TABLE AGENT ADD CONSTRAINT AGENTID PRIMARY KEY (ID)
/
CREATE TABLE AGENT_CONFIG(
AGENT_CONFIG_ID INTEGER NOT NULL,
AGENT_ID INTEGER,
.......
)
/
CREATE INDEX IX_RELATIONSHIP16 ON AGENT_CONFIG (AGENT_ID)
/
ALTER TABLE AGENT_CONFIG ADD CONSTRAINT KEY17 PRIMARY KEY (AGENT_CONFIG_ID)
/
ALTER TABLE AGENT_CONFIG ADD CONSTRAINT RELATIONSHIP16 FOREIGN KEY (AGENT_ID) REFERENCES AGENT (ID)
/
I want to use the first table AGENT as main table to store data. Into the second table I want to store configuration about AGENT and use AGENT ID as unique ID.
But I have this problem: I insert successfully row into table AGENT. I need to also add empty row with the same ID into table AGENT_CONFIG and later update that row. How I can duplicate this ID value duplication? Probably with Oracle table trigger? Is three any other way like special relation between the tables?
I use this SQL Query for insert into AGENT table:
INSERT INTO AGENT ("ID, GROUP_ID, NAME.....) VALUES (AGENT_SEQ.nextval, ?, ......)
Is this correct query:
INSERT INTO AGENT (ID, GROUP_ID......) VALUES (AGENT_SEQ.nextval, ?.......)
RETURNING id INTO INSERT INTO AGENT_CONFIG (AGENT_SEQ.nextval, Agent_ID) VALUES (id)"

For this use currval pseudocolumn (as #Nicholas Krasnov specified) of the sequence that you are using after you use nextval for table "AGENT". Currval will duplicate the value that you used for table "AGENT".
So for example :
1. INSERT INTO AGENT (ID, GROUP_ID......) VALUES (AGENT_SEQ.nextval, .......)
2. INSERT INTO AGENT_CONFIG (AGENT_CONFIG_ID,AGENT_ID) VALUES (NULL,AGENT_SEQ.CURRVAL) ;
Link for Sequence Pseudocolumns --> https://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns002.htm

To establish a 1:1 or 1:{1,n} relation is not that easy:
On every insert in the parent table you'd have to make sure an according insert in the child table is also made.
On every delete from the parent table you'd have to make sure to delete the according child records (usually via cascading delete or by mere foreign key constraints).
On every delete from the child table you'd have to make sure it's not the last one for its parent. (And in that case either forbid the delete or delete the parent with it.)
Forbid or react on updates to the IDs.
You can solve this by disabling (i.e. not granting) direct inserts and deletes (and maybe updates) on the table and provide PL/SQL functions to handle these instead.
If you are okay, however, with a 1:{0,1} or 1:{0,n} relation, then you can simply write the parent record and then look up its ID to write the child record(s).

Related

Create constraint for control insert in table

There are two tables - orders and a list of services. In the first there is a bool field that the order is approved, if it is true then you can’t insert / delete values in the second table. With the UPDATE of the first table and the DELETE of the second, it is clear.
INSERT make as
INSERT INTO b (a_id, b_value)
SELECT *
FROM (VALUES (1, 'AA1-BB1'),(1, 'AA1-BB2'),(1, 'AA1-BB3')) va
WHERE (SELECT NOT confirm FROM a WHERE a_id = 2);
https://dbfiddle.uk/?rdbms=postgres_12&fiddle=7b0086967c1c38b0c80ca5624ebe92e9
How to forbid to insert without triggers and stored procedures? Is it possible to compose somehow complex constraint or a foreign key for checking conditions at the DBMS level?
The most recent version of Postgres supports generated columns. So, you can do:
alter table b add confirm boolean generated always as (false) stored;
Then create a unique key in a:
alter table a add constraint unq_a_confirm_id unique (confirm, id);
And finally the foreign key relationship:
alter table b add constraint fk_b_a_id_confirm
foreign key (confirm, a_id) references a(confirm, id);
Now, only confirmed = false ids can be used. Note that this will prevent updates to a that would invalidate the foreign key constraint.

Create a table with a foreign key referencing to a temporary table generated by a query

I need to create a table having a field, which is a foreign key referencing to another query rather than existing table. E.g. the following statement is correct:
CREATE TABLE T1 (ID1 varchar(255) references Types)
but this one throws a syntax error:
CREATE TABLE T2 (ID2 varchar(255) references SELECT ID FROM BaseTypes UNION SELECT ID FROM Types)
I cannot figure out how I can achieve my goal. In the case it’s needed to introduce a temporary table, how can I force this table being updated each time when tables BaseTypes and Types are changed?
I am using Firebird DB and IBExpert management tool.
A foreign key constraint (references) can only reference a table (or more specifically columns in the primary or unique key of a table). You can't use it to reference a select.
If you want to do that, you need to use a CHECK constraint, but that constraint would only be checked on insert and updates: it wouldn't prevent other changes (eg to the tables in your select) from making the constraint invalid while the data is at rest. This means that at insert time the value could meet the constraint, but the constraint could - unnoticed! - become invalid. You would only notice this when updating the row.
An example of the CHECK-constraint could be:
CREATE TABLE T2 (
ID2 varchar(255) check (exists(
SELECT ID FROM BaseTypes WHERE BaseTypes.ID = ID2
UNION
SELECT ID FROM Types WHERE Types.ID = ID2))
)
For a working example, see this fiddle.
Alternatively, if your goal is to 'unite' two tables, define a 'super'-table that contains the primary keys of both tables, and reference that table from the foreign key constraint. You could populate and update (eg insert and delete) this table using triggers. Or you could use a single table, and replace the existing views with an updatable view (if this is possible depends on the exact data, eg IDs shouldn't overlap).
This is more complex, but would give you the benefit that the foreign key is also enforced 'at rest'.

How to disable delete on table for certain id in h2?

Lets suppose we have student table in h2 and every student has id (primary key). Is it possible to implement trigger (or another mechanism) to disable delete operation if id == 100. I want to have such protection on DB level, but not on application level.
One solution is obviously a trigger that prevents deleting or changing the value.
Another method is to use a foreign key constraint. Create a table of ids that you want to keep and use a foreign key reference:
create table keep_these_students (
student_id int,
constraint fk_keep_these_students_student_id foreign key (student_id) references students(id)
);
insert into keep_these_students (student_id)
values (100);
The foreign key definition will require that the row cannot be deleted if the id changes. And, it is easy to add additional ids -- without changing triggers.

SQL Insert values into table

I am trying to insert a row into my database table, but I keep on getting a SQL error.
I have a table called tbl_template_log, it has 3 Forgain Keys, user_id, temp_id, savedtemp_id, at the moment I only want to Insert a row with user_id and set temp_id and savedtemp_id to 0.
Query:
INSERT INTO tbl_template_log (user_id, temp_id, savetemp_id, send_date, send_to, email_send) VALUES (user_id=77, temp_id=0, savetemp_id=0, send_date='2013-10-10', send_to='test#test.com', email_send='hello')
Error:
INSERT INTO tbl_template_log (user_id, temp_id, savetemp_id, send_date, send_to, email_send) VALUES (user_id=77, temp_id=0, savetemp_id=0, send_date='2013-10-10', send_to='test#test.com', email_send='hello')
MySQL said: Documentation
#1452 - Cannot add or update a child row: a foreign key constraint fails (`admin_boltmail`.`tbl_template_log`, CONSTRAINT `tbl_template_log_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `tbl_user` (`user_id`))
From What I understand there is some sort of issue with user_id that the ID of the user has to be existing in tbl_user and ID 77 is an existing user id.....
Could some one point out a mistake I am doing. Thx
You can't add a row to this table unless the other tables specified in your foreign key constraints already have a record with the field value you're trying to insert. That's what a foreign key constraint means.
You're trying to break the rule you defined on your table. No, the database won't let you break the rule. You'll either have to add records to the foreign key tables or disable the constraints.

Create a one to many relationship using SQL Server

How do you create a one to many relationship using SQL Server?
Define two tables (example A and B), with their own primary key
Define a column in Table A as having a Foreign key relationship based on the primary key of Table B
This means that Table A can have one or more records relating to a single record in Table B.
If you already have the tables in place, use the ALTER TABLE statement to create the foreign key constraint:
ALTER TABLE A ADD CONSTRAINT fk_b FOREIGN KEY (b_id) references b(id)
fk_b: Name of the foreign key constraint, must be unique to the database
b_id: Name of column in Table A you are creating the foreign key relationship on
b: Name of table, in this case b
id: Name of column in Table B
This is a simple example of a classic Order example. Each Customer can have multiple Orders, and each Order can consist of multiple OrderLines.
You create a relation by adding a foreign key column. Each Order record has a CustomerID in it, that points to the ID of the Customer. Similarly, each OrderLine has an OrderID value. This is how the database diagram looks:
In this diagram, there are actual foreign key constraints. They are optional, but they ensure integrity of your data. Also, they make the structure of your database clearer to anyone using it.
I assume you know how to create the tables themselves. Then you just need to define the relationships between them. You can of course define constraints in T-SQL (as posted by several people), but they're also easily added using the designer. Using SQL Management Studio, you can right-click the Order table, click Design (I think it may be called Edit under 2005). Then anywhere in the window that opens right-click and select Relationships.
You will get another dialog, on the right there should be a grid view. One of the first lines reads "Tables and Columns Specification". Click that line, then click again on the little [...] button that appears on the right. You will get this dialog:
The Order table should already be selected on the right. Select the Customer table on the left dropdown. Then in the left grid, select the ID column. In the right grid, select the CustomerID column. Close the dialog, and the next. Press Ctrl+S to save.
Having this constraint will ensure that no Order records can exist without an accompanying Customer record.
To effectively query a database like this, you might want to read up on JOINs.
This is how I usually do it (sql server).
Create Table Master (
MasterID int identity(1,1) primary key,
Stuff varchar(10)
)
GO
Create Table Detail (
DetailID int identity(1,1) primary key,
MasterID int references Master, --use 'references'
Stuff varchar(10))
GO
Insert into Master values('value')
--(1 row(s) affected)
GO
Insert into Detail values (1, 'Value1') -- Works
--(1 row(s) affected)
insert into Detail values (2, 'Value2') -- Fails
--Msg 547, Level 16, State 0, Line 2
--The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Detail__MasterID__0C70CFB4".
--The conflict occurred in database "Play", table "dbo.Master", column 'MasterID'.
--The statement has been terminated.
As you can see the second insert into the detail fails because of the foreign key.
Here's a good weblink that shows various syntax for defining FK during table creation or after.
http://www.1keydata.com/sql/sql-foreign-key.html
If you are not using SSMS then here is the syntax:
ALTER TABLE <table_name>
ADD <constraint_name> FOREIGN KEY
(<column_name1> ,
<column_name2> )
REFERENCES <table_name>
(<column_name1> ,
<column_name2>)
http://infogoal.com/sql/sql-add-foreignkey.htm
If you are talking about two kinds of enitities, say teachers and students, you would create two tables for each and a third one to store the relationship. This third table can have two columns, say teacherID and StudentId.
If this is not what you are looking for, please elaborate your question.