SQL Server Trigger to DELETE one record from multiple tables - triggers

I know this can be done with foreign keys but I cannot add them or something weird happens when I am inserting new records. There are a lot of stored procedures in this database and I don't know what they do since I know nothing about stored procedures. I was hoping someone could help me figure out a trigger that will delete a specific ProductID when I delete it from the Product table. It is also located in tables called CompanyLink, TargetLink, and CategoryLink.
As of right now, when I delete the ProductID from the Product table, I have to manually delete it from the other 3 tables it was inserted into.

You can do it through a trigger like this:
CREATE TRIGGER [dbo].[ProductDeleted]
ON [dbo].[Product]
AFTER DELETE
AS
BEGIN
DELETE FROM CompanyLink WHERE ProductID = (SELECT TOP 1 ProductID FROM DELETED)
DELETE FROM TargetLink WHERE ProductID = (SELECT TOP 1 ProductID FROM DELETED)
END
Obviously the syntax might not be perfect, but this is close to what you need.

Related

Is this the correct way to bulk INSERT ON CONFLICT in Postgres?

I will provide a simplified example of my problem.
I have two tables: reviews and users.
reviews is updated with a bunch of reviews that users post. The process that fetches the reviews also returns information for the user that submitted it (and certain user data changes frequently).
I want to update users whenever I update reviews, in bulk, using COPY. The issue arises for users when the fetched data contains two or more reviews from the same user. If I do a simple INSERT ON CONFLICT, I might end up with errors since and INSERT statement cannot update the same row twice.
A SELECT DISTINCT would solve that problem, but I also want to guarantee that I insert the latest data into the users table. This is how I am doing it. Keep in mind I am doing this in bulk:
1. Create a temporary table so that we can COPY to/from it.
CREATE TEMPORARY TABLE users_temp (
id uuid,
stat_1 integer,
stat_2 integer,
account_age_in_mins integer);
2. COPY data into temporary table
COPY users_temp (
id,
stat_1,
stat_2,
account_age_in_mins) FROM STDIN CSV ENCODING 'utf-8';
3. Lock users table and perform INSERT ON CONFLICT
LOCK TABLE users in EXCLUSIVE MODE;
INSERT INTO users SELECT DISTINCT ON (1)
users_temp.id,
users_temp.stat_1,
users_temp.stat_2,
users_temp.account_age_in_mins
FROM users_temp
ORDER BY 1, 4 DESC, 2, 3
ON CONFLICT (id) DO UPDATE
SET
stat_1 = EXCLUDED.stat_1,
stat_2 = EXCLUDED.stat_2,
account_age_in_mins = EXCLUDED.account_age_in_mins';
The reason I am doing a SELECT DISTINCT and an ORDER BY in step 3) is because I:
Only want to return one instance of the duplicated rows.
From those
duplicates make sure that I get the most up to date record by
sorting on the account_age_in_mins.
Is this the correct method to achieve my goal?
This is a very good approach.
Maybe you can avoid the table-lock, when you lock only tuples you have in your temporary table.
https://dba.stackexchange.com/questions/106121/locking-in-postgres-for-update-insert-combination

Do triggers cause other triggers to execute?

I have a question regarding triggers in TSQL.
Let's say I have 3 tables:
Companies
---------
Id
Employees
---------
Id
CompanyId
Tasks
-----
EmployeeId
Now I create 2 triggers for the top 2 tables Companies and Employees:
CREATE TRIGGER DeleteCompany
ON [dbo].[Companies]
INSTEAD OF DELETE
AS
DELETE FROM [dbo].[Employees]
WHERE CompanyId IN (SELECT Id FROM deleted)
GO
CREATE TRIGGER DeleteEmployee
ON [dbo].[Employees]
INSTEAD OF DELETE
AS
DELETE FROM [dbo].[Tasks]
WHERE EmployeeId IN (SELECT Id FROM deleted)
GO
So far so good. Now, if I delete a company, the trigger DeleteCompany will be executed and the mapped Employees will be removed. My question is, will this cause the trigger DeleteEmployee to execute? Because I am trying to basically do this but only the first trigger (DeleteCompany) is executed.
OK I have found the problem. I was a little confused about what INSTEAD OF actually does. It turns out, it completely replaces the DELETE so I had to delete the actual record after I deleted it's references like so:
CREATE TRIGGER DeleteCompany
ON [dbo].[Companies]
INSTEAD OF DELETE
AS
DELETE FROM [dbo].[Employees]
WHERE CompanyId IN (SELECT Id FROM deleted)
DELETE [dbo].[Companies] WHERE [dbo].[Companies].Id IN (SELECT Id FROM deleted)
GO
CREATE TRIGGER DeleteEmployee
ON [dbo].[Employees]
INSTEAD OF DELETE
AS
DELETE FROM [dbo].[Tasks]
WHERE EmployeeId IN (SELECT Id FROM deleted)
DELETE [dbo].[Employees] WHERE [dbo].[Employees].Id IN (SELECT Id FROM deleted)
GO
This does the trick and the desired cascading delete effect is achieved.
This is the post that led me to this realization: Link

What am I missing from this DELETE statement

Here is the question that I'am having problems with:
Write a DELETE statement that deletes the row in the Categories table that has an ID of 44444. When you execute this statement, it will produce an error since the category has related rows in the Products table. To fix that, precede the DELETE statement with another DELETE statement that deletes all products in this category.
I don't know why I keep getting this error message:
The DELETE statement conflicted with the REFERENCE constraint
"FK__Products__Catego__145C0A3F". The conflict occurred in database
"MyGuitarShop", table "dbo.Products", column 'CategoryID'.
And here is my SQL statement:
DELETE Categories
FROM Categories JOIN Products
ON Categories.CategoryID = Products.CategoryID
WHERE Categories.CategoryID = 44444;
I have been working on this for a while now and I can't figure out what im doing wrong and any help would be appreciated.
You have to delete the products first, then you will be able to delete the category. You have the error because of a foreign key constraint.
Therefore I would write 2 queries:
DELETE FROM Products WHERE CategoryID = 44444;
Now as there are no products with this id the category can be deleted:
DELETE FROM Categories WHERE CategoryID = 44444;
I know in Postgres at least you can use a cascade modifier to delete related rows.
DELETE FROM Categories WHERE CategoryID = 44444 CASCADE;

Cascade new IDs to a second, related table

I have two tables, Contacts and Contacts_Detail. I am importing records into the Contacts table and need to run a SP to create a record in the Contacts_Detail table for each new record in the Contacts. There is an ID in the Contacts table and a matching ID_D in the Contacts_Detail table.
I'm using this to insert the record into Contacts_Detail but get the 'Subquery returned more than 1 value.' error and I can't figure out why. There are multiple records in Contacts that need have matching records in Contacts_Detail.
Insert into Contacts_Detail (ID_D)
select id from Contacts c
left join Contacts_Detail cd
on c.id = cd.id_d
where id_d is null
I'm open to a better way...
thanks.
It sounds like you're inserting blank child-records into your Contacts_Detail table -- so the first question I'd ask is: Why?
As for why your specific SQL isn't working...
A few things you can check:
Contacts table -- do you have any records there WHERE id is null?
(delete them -- then make the id field a primary key)
Contacts_Detail
table -- do you have any records there WHEERE id_d is null?
(delete them -- then go into your designer and create a relationship
/ enforce referential integrity.)
Verify that c.id is the primary
key, and cd.id_d is the correct foreign key to relate the tables.
Hope that helps
Why not just have a trigger? This seems a little simpler than having to determine for all time which rows are missing - that seems more like something you would do periodically to correct for some anomalies, not something you should have to do after every insert. Something like this should work:
CREATE TRIGGER dbo.NewContacts
ON dbo.Contacts
FOR INSERT
AS
BEGIN
INSERT dbo.Contacts_Detail(ID_D) SELECT ID FROM inserted;
END
GO
But I suspect you have a trigger on the Contacts_Detail table that is not written to correctly handle multi-row inserts, and that's where your subquery error is coming from. Can you show the trigger on Contacts_Detail?

Delete all the records

How to delete all the records in SQL Server 2008?
To delete all records from a table without deleting the table.
DELETE FROM table_name use with care, there is no undo!
To remove a table
DROP TABLE table_name
from a table?
You can use this if you have no foreign keys to other tables
truncate table TableName
or
delete TableName
if you want all tables
sp_msforeachtable 'delete ?'
Use the DELETE statement
Delete From <TableName>
Eg:
Delete from Student;
I can see the that the others answers shown above are right, but I'll make your life easy.
I even created an example for you. I added some rows and want delete them.
You have to right click on the table and as shown in the figure Script Table a> Delete to> New query Editor widows:
Then another window will open with a script. Delete the line of "where", because you want to delete all rows. Then click Execute.
To make sure you did it right right click over the table and click in "Select Top 1000 rows". Then you can see that the query is empty.
If you want to reset your table, you can do
truncate table TableName
truncate needs privileges, and you can't use it if your table has dependents (another tables that have FK of your table,
For one table
truncate table [table name]
For all tables
EXEC sp_MSforeachtable #command1="truncate table ?"
Delete rows in the Results pane if you want to delete records in the database. If you want to delete all of the rows you can use a Delete query.
Delete from Table_name
delete from TableName
isn't a good practice.
Like in Google BigQuery, it don't let to use delete without "where" clause.
use
truncate table TableName
instead
When the table is very large, it's better to delete table itself with drop table TableName and recreate it, if one has create table query; rather than deleting records one by one, using delete from statement because that can be time consuming.
The statement is DELETE FROM YourDatabaseName.SomeTableName; if you are willing to remove all the records with reasonable permission. But you may see errors in the constraints that you defined for your Foreign Keys. So that you need to change your constraints before removing the records otherwise there is a command for MySQL (which may work for others) to ignore the constraints.
SET foreign_key_checks = 0;
Please be aware that this command will disable your foreign keys constrain check, so this can be dangerous for the relationships you created within your schema.