I want to get data from a set of tables in a cascade way for a given predicate.
As an example, there is a parent table which has customer information (i.e. CustomerID) and then there would be 10s of child tables. I want to select data from a limited number of child tables for that customer (or even selecting from all child tables is not a super bad idea).
I can totally start a transaction and query all the tables specifically for that customer but I am looking for a cascade query to select all the objects in one query like Oracle has cascade delete.
Is it possible to achieve that? If yes, how?
No. You would have to write the code yourself (hard-coded) or have code generate the code based on data dictionary traversal of the FK/PK constraints.
Related
Have a difficulties with query. I am new in SQL so trying to make better query for deleting a trip.
Does anyone know how to make it easier in one query?
Thank you
If you want to perform a delete across all your tables in one single statement and you happen to be using a SQL Engine that support CASCADE you might be in luck.
From your sample query it appears that all tables share a chained PK\FK relationship.
Venues through checkpoint_id
Checkpoints through day_id
Days through trip_id
Trips (at the top)
My inference is that TRIP is the top of the chain. If you specifically define the PK\FK relationship 'CONSTRAINT' which you should for good DB design, then on each table, you can alter the constraint with the option CASCADE. With that done simply deleting a row from trip will automatically delete all other rows below via the defined relationship.
In other words, with CASCADE and a SQL ENGINE that supports it - you can simply issue the last delete statement and the rest is implied.
DELETE FROM trips WHERE id = 27
Check table constraint options here. Pay attention to CASCADE definition. Similar question with explanations here.
I need to delete entries from two tables, using some ids found from a unique SELECT query.
What is the most performant way of doing this using SQL Server?
I currently use a Table Variable :
DECLARE #emailIdsToDelete TABLE(id int NOT NULL);
INSERT INTO #emailIdsToDelete
SELECT id
FROM ...;
DELETE organisations_emails
FROM #emailIdsToDelete etd
INNER JOIN ...;
DELETE emails
FROM #emailIdsToDelete etd
INNER JOIN ...;
But since I need that table only to store the result of the SELECT, and only for the scope of this specific query, I was wondering if there was a more performant solution.
I think I can't use CTE (using the "with()" clause) since it allows only one following statement, not two.
Is there a way to delete from those two tables, without having to create a temporary table first? Some kind of join? Or is my solution already optimal?
UPDATE : Let's say there is no "ON DELETE CASCADE" between any of those tables.
Cascade Delete is an option, however you would need to test to validate it is more performant, also sometimes even with FKs this can leave orphans records.
Soft Delete You could add a isDeleteFlag column set it to bit default(0) and update it to 1 when you run your query, again would have to test it. If you wanted to stop there you would need to change your usp_ to accommodate not to return these records. where isDeleteFlag = 0
To follow up with the most performant, you could use the soft delete and then at night do smaller batches of deletes, or you could store the delete ids in a separate table and remove them at night in batches. This might work for you depending on what you are trying to accomplish, if it is okay to steal performance at night rather than during normal business operations, sometimes it's not viable.
In the end the answer is it depends and mileage will vary, you'll need to test the solutions to compare performance.
Optionally you could use your approach and use a variable table / temp table or a user defined table type.
Edit: Also you could output the deleted ids and daisy chain deletes in a transaction.
The other way would be to have a foreign key between organisations_emails and emails with ON DELETE CASCADE. Then you would merely need to delete from emails, and matching rows in organisations_emails would be deleted automatically.
Assuming that the foreign key is appropriate in your schema, of course.
Let's say I have a Customers table with columns ID and CompanyId.
I need to delete some companies from the DB.
The problem is, the table has a lot of child tables and those tables also has a lot of child tables and so on...
Just to clarify, all the relationships are with constraints.
How can I accomplish that ?
Thanks.
EDIT: Notice that what i'm trying to do is a one time operation.
Whether i will change the constraints or add triggers or anything like that, I'm planning on removing it in the end.
The inbuilt solution to this problem is to set up your FK constraints with ON DELETE CASCADE.
However many people (myself included) are somewhat uneasy about doing this as a mistaken delete will silently propagate through the database.
Here are three ways:
Use a stored procedure to delete child first then up to the parent row in a transation.
I personally wouldn't make it dynamic and would have a specific "DeleteCompany" proc. Your may need a rule that such as "no delete if sales > 100 million" that needs checked
CASCADE DELETEs on your foreign keys
This can be tricky if you have multiple cascade paths, but simple otherwise
INSTEAD OF trigger
An INSTEAD OF trigger is like a stored procedure in operation. Note: You'll get an FK violation before an AFTER trigger fires
Personally, I'd use a stored proc so I have explicit deletes. The effect is the same as cascading FKs but more obvious.
For SQL Server 2008, this is the solution:
Generate Delete Statement From Foreign Key Relationships in SQL 2008?
With this solution, you can easily find the correct sequence of DELETE respecting, in the meantime, the foreign keys' relationships.
If you are interested in this theme, you can read also the ORACLE PL/SQL solution:
How to generate DELETE statements in PL/SQL, based on the tables FK relations?
When I create a view I can base it on multiple columns from different tables.
When I want to create a lookup table I need information from one table, for example the foreign key of an order table, to get customer details from another table. I can create a view having parameters to make sure it will get all data that I need. I could also - from what I have been reading - make a lookup table. What is the difference in this case and when should I choose for a lookup table?? I hope this ain't a bad question, I'm not very into db's yet ;).
Creating a view gives you a "live" representation of the data as it is at the time of querying. This comes at the cost of higher load on the server, because it has to determine the values for every query.
This can be expensive, depending on table sizes, database implementations and the complexity of the view definition.
A lookup table on the other hand is usually filled "manually", i. e. not every query against it will cause an expensive operation to fetch values from multiple tables. Instead your program has to take care of updating the lookup table should the underlying data change.
Usually lookup tables lend themselves to things that change seldomly, but are read often. Views on the other hand - while more expensive to execute - are more current.
I think your usage of "Lookup Table" is slightly awry. In normal parlance a lookup table is a code or reference data table. It might consist of a CODE and a DESCRIPTION or a code expansion. The purpose of such tables is to provide a lsit of permitted values for restricted columns, things like CUSTOMER_TYPE or PRIORITY_CODE. This category of table is often referred to as "standing data" because it changes very rarely if at all. The value of defining this data in Lookup tables is that they can be used in foreign keys and to populate Dropdowns and Lists Of Values.
What you are describing is a slightly different scenario:
I need information from one table, for
example the foreign key of an order
table, to get customer details from
another table
Both these tables are application data tables. Customer and Order records are dynamic. Now it is obviously valid to retrieve additional data from the Customer table to display along side the Order data, and in that sense Customer is a "lookup table". More pertinently it is the parent table of Order, because it has the primary key referenced by the foreign key on Order.
By all means build a view to capture the joining logic between Order and Customer. Such views can be quite helpful when building an application that uses the same joined tables in several places.
Here's an example of a lookup table. We have a system that tracks Jurors, one of the tables is JurorStatus. This table contains all the valid StatusCodes for Jurors:
Code: Value
WS : Will Serve
PP : Postponed
EM : Excuse Military
IF : Ineligible Felon
This is a lookup table for the valid codes.
A view is like a query.
Read this tutorial and you may find helpful info when a lookup table is needed:
SQL: Creating a Lookup Table
Just learn to write sql queries to get exactly what you need. No need to create a view! Views are not good to use in many instances, especially if you start to base them on other views, when they will kill performance. Do not use views just as a shorthand for query writing.
I have two tables:
Cartoon containing P_Name,U_Of_Pack,Weight,No_Cart,No_Pack,Tot_weight
Product containing P_Name,U_Of_Pack,Weight,No_Cart,No_Pack,Tot_weight
When any changes in the Product table are made to No_Cart, No_Pack, Tot_weight columns, these values should be subtracted from the same column's of Cartoon table & the updates should be applied in the Cartoon table (remaining column values).
MS Access does not support triggers on tables.
It would almost seem that Cartoon can be made up of a Query using Product instead of an actauls table. This will then still give you live results from the Product table.
If this is not the case, you would have to create an additinal query to update the Cartoon table each time you update the Product table.
Reading the comments to the question, to give you the benefit of the doubt and assume there is no design error I think we'd also need to assume that the columns common to both tables (all of them, it would appear) represent a key, in which case you could use the ON UPDATE CASCADE referential action on the referencing table Cartoon.