Delete rows from binding source with foreign key - vb.net

I have a DataSource with 2 tables one projectDiamter and other diameterSet. ProjectDiameter id contains primary key and diameterset has foreign key constraint with same key.
Now when I select row from projectdiameter table diameterset DataGridView get filtered accordingly. I have lots of rows in diameterset (lets say 15000 for selected project only) which I want to delete when delete button is pressed.
I wanted to know which is the fastest way to delete it from DataGridView and SQL table.
I tried following code but wanted to check if there is any better way of getting the same.
FKProjectDiameterBindingSource.MoveFirst()
For j As Int16 = 0 To FKProjectDiameterBindingSource.Count - 1
For i As Int16 = 0 To FKDiameterDiameterSetBindingSource.Count - 1
FKDiameterDiameterSetBindingSource.Clear()
FKDiameterDiameterSetBindingSource.MoveFirst()
FKDiameterDiameterSetBindingSource.RemoveCurrent()
Next
FKProjectDiameterBindingSource.MoveNext()
Next
Me.Validate()
DiameterTableAdapter.Update(RSM3DDB1.Diameter)
DiameterSetTableAdapter.Update(RSM3DDB1.DiameterSet)

Does the foreign key relationship exist formally in the database? That is, is there an actual relationship defined in SQL? If so, I'd suggest setting that relationship to CASCADE DELETE and then all you have to do is call DiameterSetTableAdapter.UPDATE after you update Diameter.
A good explanation on CASCADE DELETE is here
https://www.mssqltips.com/sqlservertip/2365/sql-server-foreign-key-update-and-delete-rules/ Note that the keyword is just "Cascade" but you apply it to DELETE, the article explains ("It is not necessary that the same rule be applied for both update and delete operations. There may be different rules for each of the update and delete operations on a single FK constraint.")
If the relationship isn't formal, that is it logically exists but isn't enforced, then I'd put a trigger on the Diameter table and in that trigger delete all the rows in DiameterSet where the DiameterID equals the deleted DiameterID. Note that in a trigger a row that is modified (as opposed to deleted) will be in both the INSERTED and DELETED temporary tables, so you have to take steps to make sure you're not removing rows that reference a modified Diameter.
If you take this second approach, you can still just run the 2 UPDATE procedures on the 2 table adapters in VB, it's just more coding in SQL than setting the CASCADE DELETE.
Both approaches are MUCH more efficient than doing it in VB, and it can add up if you have hundreds of rows affected.
Using either of these also has the advantage of being atomic, whereas your approach is not.

Related

How do I automatically delete all associated components while deleting a product in a SQL relational database?

Is this possible?
If so, does it happen automatically or do I need to config the definition of the foreign key in the component table properly?
The foreign key(s) would need to be defined as ON DELETE CASCADE in order for this to occur. Generally I'd recommend against such a setting because can you imagine (say) deleting a row from your GENDER table and suddenly discovering that half of the millon rows in your CUSTOMER table just vanished, and similarly half of the 100 million rows in your CUSTOMER_SALES tables also went.... That's a career limiting move.
If the foreign keys are not defined as ON DELETE CASCADE you could still mine the data dictionary to wor out the relationships in order to build a "delete child before parent" mechanism for those rare scenarios where you might need this

Delete row with foreign key constraints and no cascade deleting SQL

Trying to figure out how to delete a row in a SQL table that has multiple foreign keys pointing to it, and more keys pointing to those, etc, etc. Cascading Deletes aren't turned on (I have no control to turn them on), and I'm trying to avoid performing a delete on EVERY single row that is affected by this one delete.
So if I have table XXX, with columns YYY and ZZZ, where YYY is the primary key and ZZZ is a column that has multiple foreign keys pointing to it, how would I go about deleting a row based on the primary key value?
Syntax would be:
DELETE FROM XXX
WHERE YYY = some_value
Is this even possible (without performing a ton of individual deletes)? And if so, how would I do it?
No.
Either you need the foreign key constraints to cascade the delete (something I'm not terribly fond of, it makes it too easy for some application/ developer to think they can delete and re-insert some data rather than updating it in place without inadvertently causing all the child rows to be deleted) or you have to delete the child rows before you delete the parent.
Normally, if you want to delete the data from the child tables, it is easier to just manually write the various DELETE statements. It would be possible to query the data dictionary (dba_constraints, dba_cons_columns, etc.) and dynamic SQL to walk all the constraints and generate the appropriate DELETE statements. In the vast majority of cases, it wouldn't make sense to do that unless you're trying to generate delete statements for a large number of tables.
How about turning off the foreign key constraint check?
SET FOREIGN_KEY_CHECKS = 0;
Then turning it on back when you delete the row?
SET FOREIGN_KEY_CHECKS = 1;

How to Delete a Row from multiply tables in sql?

so i have to tables that have a relation between them - relation type: one to many.
and i thought that the following query:
DELETE Orderstbl.*, ItemsInOrdertbl.*
FROM Orderstbl INNER JOIN ItemsInOrdertbl ON Orderstbl.OrderID = ItemsInOrdertbl.OrderId
WHERE (((Orderstbl.OrderID)=26));
will delete all the rows in both tables that contain the OrderID = 26
but to my surprise it filled the following error :
could not delete from specified tables
tried to find an answer on google , didnt help much thanks in advance :D
You could also create a relationship that includes CASCADE DELETE, then when you delete from one it will delete from the other
from microsoft:
If you select the Cascade Delete Related Records check box when you
define a relationship, any time that you delete records in the primary
table, Microsoft Access automatically deletes related records in the
related table. For example, if you delete a customer record from the
Customers table, all the customer's orders are automatically deleted
from the Orders table (this includes records in the Order Details
table related to the Orders records). When you delete records from a
form or datasheet with the Cascade Delete Related Records check box
selected, Microsoft Access warns you that related records may also be
deleted. However, when you delete records using a delete query,
Microsoft Access automatically deletes the records in related tables
without displaying a warning.
Using the CASCADE DELETE is a simple and clean way to make sure the correct records are removed from both tables.
Here is another article discussing CASCADE DELETE with MS-Access.
Delete one or more records from an Access database
If you have a foreign key set between columns in two tables, you have to be sure to delete the child column first, and then the master. The proper way to do this is to set a constraint upon deletion of the master, such as UPDATE or DELETE. The constraint takes care of the foreign key relations, so you never wind up with orphan rows all over the place.
To create the constraints in MySQL (for example)...
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
The other option is to do it programmatically, deleting the row in child tables first, and then the master.

Define One to Many Relationships with SQL

I'm looking for a way to set up a one to many relationship between 2 tables. The table structures is explained below but I've tried to leave everything off that has nothing to do with the problem.
Table objects has 1 column called uuid.
Table contents has 3 columns called content, object_uuid and timestamp.
The basic idea is to insert a row into objects and get a new uuid from the database. This uuid is then used stored for every row in contents to associate contents with objects.
Now I'm trying to use the database to enforce that:
Each row in contents references a row in objects (a foreign key should do)
No row in objects exists without at least a row in contents
These constraints should be enforced on commit of transactions.
Ordinary triggers can't help probably because when a row in the objects table is written, there can't be a row in contents yet. Postgres does have so called constraint triggers that can be deferred until the end of the transaction. It would be possible to use those but they seem to be some sort of internal construct not intended for everyday use.
Ideas or solutions should be standard SQL (preferred) or work with Postgres (version does not matter). Thanks for any input.
Your main problem is that other than foreign key constraints; no constraint can reference another table.
Your best bet is to denormalize this a little and have a column on object containing the count of contents that reference it. You can create a trigger to keep this up to date.
contents_count INTEGER NOT NULL DEFAULT 0
This won't be as unbreakable unless you put some user security over who can update this column. But if you keep it up to date with a trigger and all you're looking to avoid is accidental corruption, this should be sufficient.
EDIT: As per the comment, CHECK constraints are not deferrable. This solution would raise an error if all the contents are removed even if the intention is to add more in the same transaction.
Maybe what you want to do is normalize a little bit more. You need a third table, that references elements of the other tables. Table objects should have its own uuid and table contents sholud have also its own uuid and no reference to the table objects. The third table should have only the references to the other two tables, but the primary key is the combination of both references.
so for example you have an uuid of the table objects and you want all the contents of that uuid, assuming that the third table has as columns object_uuid and content_uuid, and the table contents has its own serial column named uuid, your query should be like this:
SELECT * FROM thirdtable,contents
WHERE thirdtable.content_uuid = contents.uuid AND thirdtable.object_uuid=34;
Then you can use an on insert trigger on every table
CREATE TRIGGER my_insert_trigger AFTER INSERT OR UPDATE ON contents
FOR EACH ROW EXECUTE PROCEDURE my_check_function();
and then in function my_check_function() delete every row in objects that is not present in the third table. Somebody else answered first while I was answering, if you guys like my solution I could help you to make the my_check_function() function.

How do the Postgres foreign key 'on update' and 'on delete' options work?

Can anyone provide a clear explanation / example of what these functions do, and when it's appropriate to use them?
Straight from the manual...
We know that the foreign keys disallow creation of orders that do not relate to any products. But what if a product is removed after an order is created that references it? SQL allows you to handle that as well. Intuitively, we have a few options:
Disallow deleting a referenced product
Delete the orders as well
Something else?
CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT,
order_id integer REFERENCES orders ON DELETE CASCADE,
quantity integer,
PRIMARY KEY (product_no, order_id)
);
Restricting and cascading deletes are the two most common options. RESTRICT prevents deletion of a referenced row. NO ACTION means that if any referencing rows still exist when the constraint is checked, an error is raised; this is the default behavior if you do not specify anything. (The essential difference between these two choices is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not.) CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. There are two other options: SET NULL and SET DEFAULT. These cause the referencing columns to be set to nulls or default values, respectively, when the referenced row is deleted. Note that these do not excuse you from observing any constraints. For example, if an action specifies SET DEFAULT but the default value would not satisfy the foreign key, the operation will fail.
Analogous to ON DELETE there is also ON UPDATE which is invoked when a referenced column is changed (updated). The possible actions are the same.
edit: You might want to take a look at this related question: When/Why to use Cascading in SQL Server?. The concepts behind the question/answers are the same.
I have a PostGreSQL database and I use On Delete when I have a user that I delete from the database and I need to delete it's information from other table. This ways I need to do only 1 delete and FK that has ON delete will delete information from other table.
You can do the same with ON Update. If you update the table and the field have a FK with On Update, if a change is made on the FK you will be noticed on the FK table.
What Daok says is true... it can be rather convenient. On the other hand, having things happen automagically in the database can be a real problem, especially when it comes to eliminating data. It's possible that in the future someone will count on the fact that FKs usually prevent deletion of parents when there are children and not realize that your use of On Delete Cascade not only doesn't prevent deletion, it makes huge amounts of data in dozens of other tables go away thanks to a waterfall of cascading deletes.
#Arthur's comment.
The more frequently "hidden" things happen in the database the less likely it becomes that anyone will ever have a good handle on what is going on. Triggers (and this is essentially a trigger) can cause my simple action of deleting a row, to have wide ranging consequences throughout my database. I issue a Delete statement and 17 tables are affected with cascades of triggers and constraints and none of this is immediately apparent to the issuer of the command. OTOH, If I place the deletion of the parent and all its children in a procedure then it is very easy and clear for anyone to see EXACTLY what is going to happen when I issue the command.
It has absolutely nothing to do with how well I design a database. It has everything to do with the operational issues introduced by triggers.
Instead of writing the method to do all the work, of the cascade delete or cascade update, you could simply write a warning message instead. A lot easier than reinventing the wheel, and it makes it clear to the client (and new developers picking up the code)