advice on writing sql delete statement - sql

i'm trying to write a delete statement using sql, based off of certain criteria. i am having trouble with it. here is the criteria.
the program should prompt the user for a ssn and delete that employee from the Employee table (the records from the Technician table and from the Expert table that reference that employee will also be deleted as a result of the ON DELETE CASCADE action)

DELETE FROM Employees WHERE SSN='508-12-1234'
Assuming the Technician and Expert tables have foreign keys set up properly, this should be all you need to do.

Related

What is the easiest (and fastest) way to update 20K employee data records from a CSV data dump in SQL Server?

I have an "employees" table with 50k+ records. We only have 24k employees but some of the employees that are no longer here are tied to historical projects so I don't want to delete them. And, of course, we've hired more employees that are working on NEW projects so they need to be added to the employees table.
I managed to convince HR to give me a CSV file with the employee data we keep in our table and now I need a way to update the existing records (new phone numbers, departments, etc...) and add new.
There are 3 criteria:
if the record exists in the CSV and the "employees" table, UPDATE the data;
if the record exists in the CSV and NOT the "employees" table, INSERT the data;
if the record exists in the "employees" table and NOT the CSV, set the record to "inactive."
This will be a regular (monthly) process so a Stored Procedure or a Function would be doable.
Suggestions please...
UPDATE: The MERGE idea works but only solves 2/3 of the problem (it does not meet criteria #3 because I do not want to delete the record if the employee is not longer with the company). When adding the 2nd UPDATE statement after the NOT MATCHED BY SOURCE, it returns an error indicating I cannot update the same record twice.
Any suggestions to this final piece of the puzzle?
What about using 'merge'?
MERGE target_table USING source_table
ON merge_condition
WHEN MATCHED
THEN update_statement
WHEN NOT MATCHED
THEN insert_statement
WHEN NOT MATCHED BY SOURCE
THEN DELETE;

How do I delete all related records?

I'm trying to delete a user and all the related records tied to him, and I have no clue how to use the SQL INNER JOIN statement, is there any way to do something in the style of:
DELETE * FROM tblUsers, tblEnrollment, tblLinkActivities, tblFullSchedule, tblSchedule, tblLinkMedical
WHERE [IDUser] = ?
(I know that's completely incorrect)
My relationships chart looks like so:
Would it be easier to use 6 delete commands? Or is there another command that does that? Thanks a bunch..
Since you already have defined relationships with referential integrity, simply set the Cascade Delete Related Records option for each relationship.
See https://support.office.com/en-us/article/create-edit-or-delete-a-relationship-dfa453a7-0b6d-4c34-a128-fdebc7e686af#__bmcascade
This way you only need to delete from tblUsers, all related records are deleted automatically.
If you can't or don't want to do this, you need to run separate delete queries on the related tables before deleting the main record.
There's no way to delete records in multiple tables at the same time in single sql query. You need to write multiple delete statements. The better way is to write an inner query with all tables involved and delete in each table.
For ex:
delete from dept where DEPTNO IN (Select a.DEPTNO from emp a , dept b where a.DEPTNO=b.DEPTNO and a.DEPTNO=10)
delete from emp where DEPTNO IN (Select a.DEPTNO from emp a , dept b where a.DEPTNO=b.DEPTNO

SQL Server Trigger on Deleted - Which records are in deleted table?

I'm new to triggers, but I'm having a hard time understanding if I'm taking the right approach here.
I'm using SQL Server 2016. I have 2 tables, Teams and TeamMembers. Teams is the parent table and TeamMembers is the child, using Teams.TeamID as a foreign key.
I also have an Activities table that logs any creates or updates to any of my tables. This table has a TableName text column as well as an IdRow column that references the ID of the row that gets created or updated. I've also got a JSONChanges column which contains a JSON string of what was changed in that activity log item.
So there's only 1 record for each Activity on a table. But potentially many activities performed per record.
So, when a user deletes a team, I need to not only delete all of the Activities logged for that team and the Team Members for that team (which is easy to do within my Team_Delete stored procedure), but I also want to delete any records in my Activities table for the activities on the TeamMembers. Since the Activities table's IdRow column points at the TeamMemberID column in the TeamMembers table, I can't use the TeamID from the delete stored procedure.
My thought was to just create a delete trigger on the TeamMembers table.
Whenever a TeamMember was deleted, I could just delete all of the records in the Activities log that point to the record that was deleted. That would simplify my Team_DELETE stored procedure. I think.
The confusion I have has to do with the records that will be in the deleted table at any given time. If User A deletes a TeamMember, and at the same time, User B runs an Update on another Team Member, won't the deleted table have 2 records in it? If I delete all records in my Activities Table based on what's in the deleted table, then I'm deleting records I shouldn't be deleting. Right?
The other issue is how do I pick just one record to delete? How do I know which record in the deleted table is the one I want from the trigger?
If I had to use a trigger on TeamMembers , I would try:
CREATE TRIGGER [ schema_name .]DeleteTeamMemberActivities ON [ schema_name .]TeamMembers
AFTER DELETE
AS
DELETE
FROM
Activities a
INNER JOIN DELETED d ON d.TeamMemberID = a.IdRow AND a.TableName ='TeamMembers';
I would also use the cascading delete on the foreign key relation between Team and TeamMembers.
[edited 08/09/2017 12:45 correcting the a.TableName join]
FYI, I edited cclarke's code a little bit - here's what I ended up with:
CREATE TRIGGER TRIGGER_DeleteTeamMemberActivities ON TeamMembers
AFTER DELETE
AS
DELETE a
FROM
Activities a
INNER JOIN deleted d ON d.TeamMemberID = a.IDRow AND a.TableName
='TeamMembers';

How to manually find and delete orphaned records - two tables?

I have made a fiddle here: http://sqlfiddle.com/#!9/a67558/1
Due to external constraints, the IDs (EID and DID) were not specified with a PK. I feel like I am close but SQL is throwing syntax errors, problem may be with the program?
The goal is to remove the row where EID = 100 from tableJoin after the record is deleted from the employee table using a trigger.
Edit per Andrew's comment:
I have tried:
CREATE TRIGGER DeOrphan
AFTER DELETE ON employee
FOR EACH ROW DELETE FROM joinTable.* FROM employee
RIGHT JOIN tableJoin ON employee.eid=tableJoin.eid
WHERE employee.eid IS NULL;
DELETE FROM employee
WHERE employee.eid = 100;
The record is succesfully removed from the employee table but persists in the tableJoin.
Try this
DELETE FROM joinTable WHERE EID NOT IN (SELECT eid FROM employee)
This would be a separate call and would clean up ALL orphans, but if you trigger it regularly it should be a fairly quick process.
There's no need for a NOT IN/NOT EXISTS, within a trigger you got access to the deleted row:
CREATE TRIGGER DeOrphan
AFTER DELETE ON employee
FOR EACH ROW
DELETE FROM joinTable WHERE `eid` = old.`eid`;
See fiddle

How to delete records from Child table and Parent table in a single query?

I have a master table and a details table.
On delete cascade is not specified.
I want delete child record as well as master record in a single query.
Suppose I want to delete EmployeeDetails and Employee record where EmpID=20 using a single query.
Is it possible?
Please help.
you cannot do it in a single query unless you have cascade delete turned on or you have a trigger on the PK table that will delete the FK table rows for that relationship
There is no construct in SQL that allows you to delete from two tables in a singe command. You can do that in a single "batch" or in a transaction (which will be preferable).
you could add a trigger on the child table to delete any other children and then the parent. This is not "technically" a single statement, but your application only needs to issue a single DELETE and it is all done for you.