TSQL, delete row and all foreign key related rows - sql-server

I am wondering if there is a query for deleting a row which also deletes all related foreign key related data.
I have a database with a table which refers through a foreign key to other rows in the same table
ID | ParentID | Data fields
1 | NULL | text and more data
2 | 1 | Text and more data
3 | 2 | ""
As you see item 2 refers to 1 using a foreign key. Currently I am unable to delete object 1 because object 2 and 3 still exist in the database. I want to know if there is a way/query (without changing the table settings) to delete object 1 and therefore also deleting 2 and 3.
DELETE FROM Table WHERE ID = 1 -- And this must then also delete row 2.
DELETE FROM Table WHERE ID = 1 OR ParentID = 1 -- Obviously doesn't work either.
I am aware that it is possible to turn of foreign key constrainst for a table, but I want to know if it can be done with a query without changing these settings.

Best way would be enabling CASCADE DELETE.
Read more here: How do I use cascade delete with SQL Server?

Related

ManyToMany association with same JPA entity(self join) with auxiliary table with additional columns

I am creating an entity Document which points to T_DOCUMENT table. A document record can have a ManyToMany relationship with another Document. This relationship is maintained in an auxiliary table T_DOCUMENT_DOCUMENT. The structure of T_DOCUMENT_DOCUMENT table is below
id |document_batch_id|document_parent_id |document_child_id|document_linker_user_id|creation_time |modification_time |
--------------------------|-------------------------------------|-----------------------|--------------------------|--------------------------|
1 |25 | 500000000| 458000000| 200000002|2020-08-18-12.11.35.026608|2020-08-18-12.11.35.026608|
2 |25 | 500000000| 458000001| 200000003|2020-08-19-08.27.42.853620|2020-08-19-08.27.42.853620|
3 |25 | 458000001| 458000002| 200000003|2020-08-19-08.29.49.497022|2020-08-19-08.29.49.497022|
4 |25 | 500000001| 458000001| 200000003|2020-08-19-08.29.50.030971|2020-08-19-08.29.50.030971|
id = autoincrement primary key of the table
document_batch_id = foreign key from another `DOCUMENT_BATCH` table
document_parent_id = foreign key from `Document`
document_child_id = foreign key from `Document`
document_linker_user_id = foreign key from `DOCUMENT_USER` of the user who created this document link
creation_time = timestamp when record is inserted. Value updated by database trigger
modification_time = timestamp when record is updated. Value updated by database trigger
It's important to note that this link between documents doesn't have to be created while inserting a new document object. It can be linked later on by the user.
I can achieve this functionality by simply creating another DocumentJoinDocument entity which manages the table itself, but I was wondering if there is a way to achieve this only using the Document entity.
Any suggestions?

Best way to delete records in two tables having foreign key?

I created two tables like marks and users. I maintained foreign key relation between two tables, When I delete a row in marks table, I need to delete that particular user in user table based on uid that exists in both tables commonly.can anyone suggest me?
Use the ON DELETE CASCADE option if you want rows deleted in the child table when corresponding rows are deleted in the parent table.
But your case is reverse from it.There is no way to do it reverse
automatically.
You need to use delete trigger explicitly whenever record are delete
from child table.
BTW its not safe to do reverse as there might be many marks record for single user and if you delete any one of them then user is removed from user table.
I suggest to do it logically in sproc.
you can check in sproc that all record for user is deleted in mark table than remove user from user table.
Well for your case, I will recommend using on delete cascade
More about it :
A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted. This is called a cascade delete in SQL Server.
The syntax for creating a foreign key with cascade delete using a CREATE TABLE statement in SQL Server (Transact-SQL) is:
CREATE TABLE child_table
(
column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
CONSTRAINT fk_name
FOREIGN KEY (child_col1, child_col2, ... child_col_n)
REFERENCES parent_table (parent_col1, parent_col2, ... parent_col_n)
ON DELETE CASCADE
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
);
For more read this
In design just use on delete cascade
CREATE TABLE child_table
(
column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
CONSTRAINT fk_name
FOREIGN KEY (child_col1, child_col2, ... child_col_n)
REFERENCES parent_table (parent_col1, parent_col2, ... parent_col_n)
ON DELETE CASCADE
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
);
Now when you delete parent . child will automatically deleted... you don't need to do any thing
check Link for detail
On delete cascade
As I don't like to DELETE any row from related tables, I suggest you this solution:
Add a status field with default value of 1 to your table(s).
Create a VIEW that shows only rows with status <> 0 and use this VIEW to show your valid data.
For parent-child or related tables just show rows with status <> 0 for both of parent and child table like parent.status * child.status <> 0.
[Optional & additional]* Create a log table or a journal for your database or your tables or just your important tables and store some actions like Create, Edit\Modify, Delete, Undelete and so on.
With this solution you can:
Support Undo and Redo.
Support Undelete action!
Be not worry about a child that has no parent.
*Found old data, changes of data and many other information.
And many other benefits and you just store more data that it is not concern with a good RDBMS.
I use DELETE just for a table that is at the end child point and its data is not so important.

The foreign key constraint

I have a table which contained the following columns.
ID int PK
Name nvarchar(50) NotNull
FID int FK reference to ID
ID Name PK
1 A Null
2 B Null
3 C 1
4 D 1
5 E 1
6 F 2
So, The primary key includes as a primary key in a table. I want to do that if the primary key is deleted, the rows which is contained the primary key as a foreign is deleted automatically. (example: When I delete ID 1 row, I want to delete automatically ID 3, 4, 5 rows.). How to make that the primary key is included as a foreign key in a table? How can I do this. Thanks.
You need to implement a "trigger" that does a "cascading delete".
Here's a good link:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=142564
CREATE TRIGGER test_trig
ON dbo.Table_1
FOR DELETE
AS
BEGIN
delete a from dbo.Table_2 a
JOIN
deleted d
ON a.joincol = d.joincol
END
Here are some other alternatives:
http://www.mssqltips.com/sqlservertip/1508/foreign-key-vs-trigger-referential-integrity-in-sql-server/
And here is a link to Microsoft's documentation on "Cascading Referential Integrity Constraints":
http://msdn.microsoft.com/en-us/library/ms186973.aspx
NOTE: In Microsoft SQL, a cascading delete to a self-referencing table is not allowed. You must either use a trigger, create a stored procedure, or handle the cascading delete from the calling application. An example of this is where a single table has an ID as identity and a ParentID with a relationship to ID in the same table.
see here
The only way will be to add a trigger you can refer the following links for more information.
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b777ec73-e168-4153-a669-835049a96520
another link

how database foreign keys cascade mysql

I created a set of tables in a database.A assigned relations with foreign key.
i am not getting cascading effect of data in mysql.
i created a table named ME and with MY_ID column name
I also created table named MY_Friends with MY_ID column name and foreing key with references to ME(MY_ID).
I am able to notice cascading effect in mysql
Me
My_ID | int(11) | NO | PRI | 0
My_Friends
My_ID | int(11) | YES | MUL | NULL | |
there are two columns description in two tables
FOREIGN KEY and CASCADE will have no effect if the tables are MyISAM. Check if the tables are defined using the InnoDB engine. Give us the output from SHOW CREATE TABLE Me and SHOW CREATE TABLE My_Friends so we can verify if that's the problem.

(PostgreSQL) "Advanced" Check Constraint Question

I use PostgreSQL but am looking for SQL answer as standard as possible.
I have the following table "docs" --
Column | Type | Modifiers
------------+------------------------+--------------------
id | character varying(32) | not null
version | integer | not null default 1
link_id | character varying(32) |
content | character varying(128) |
Indexes:
"docs_pkey" PRIMARY KEY, btree (id, version)
id and link_id are for documents that have linkage relationship between each other, so link_id self references id.
The problem comes with version. Now id is no longer the primary key (won't be unique either) and can't be referenced by by link_id as foreign key --
my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ;
ERROR: there is no unique constraint matching given keys for referenced table "docs"
I tried to search for check constraint on something like "if exists" but didn't find anything.
Any tip will be much appreciated.
I usually do like this:
table document (id, common, columns, current_revision)
table revision (id, doc_id, content, version)
which means that document has a one-to-many relation with it's revisions, AND a one-to-one to the current revision.
That way, you can always select a complete document for the current revision with a simple join, and you will only have one unique row in your documents table which you can link parent/child relations in, but still have versioning.
Sticking as close to your model as possible, you can split your table into two, one which has 1 row per 'doc' and one with 1 row per 'version':
You have the following table "versions" --
Column | Type | Modifiers
------------+------------------------+--------------------
id | character varying(32) | not null
version | integer | not null default 1
content | character varying(128) |
Indexes:
"versions_pkey" PRIMARY KEY, btree (id, version)
And the following table "docs" --
Column | Type | Modifiers
------------+------------------------+--------------------
id | character varying(32) | not null
link_id | character varying(32) |
Indexes:
"docs_pkey" PRIMARY KEY, btree (id)
now
my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ;
is allowed, and you also want:
my_db=# ALTER TABLE versions ADD FOREIGN KEY(id) REFERENCES docs;
of course there is nothing stoping you getting a 'combined' view similar to your original table:
CREATE VIEW v_docs AS
SELECT id, version, link_id, content from docs join versions using(id);
Depending on if it's what you want, you can simply create a FOREIGN KEY that includes the version field. That's the only way to point to a unique row...
If that doesn't work, you can write a TRIGGER (for all UPDATEs and INSERTs on the table) that makes the check. Note that you will also need a trigger on the docs table, that restricts modifications on that table that would break the key (such as a DELETE or UPDATE on the key value itself).
You cannot do this with a CHECK constraint, because a CHECK constraint cannot access data in another table.

Resources