How can I delete using INNER JOIN with SQL Server? - sql

I want to delete using INNER JOIN in SQL Server 2008.
But I get this error:
Msg 156, Level 15, State 1, Line 15
Incorrect syntax near the keyword 'INNER'.
My code:
DELETE
FROM WorkRecord2
INNER JOIN Employee
ON EmployeeRun=EmployeeNo
WHERE Company = '1'
AND Date = '2013-05-06'

You need to specify what table you are deleting from. Here is a version with an alias:
DELETE w
FROM WorkRecord2 w
INNER JOIN Employee e
ON EmployeeRun=EmployeeNo
WHERE Company = '1' AND Date = '2013-05-06'

Just add the name of the table between DELETE and FROM from where you want to delete records, because we have to specify the table to delete. Also remove the ORDER BY clause because there is nothing to order while deleting records.
So your final query should be like this:
DELETE WorkRecord2
FROM WorkRecord2
INNER JOIN Employee
ON EmployeeRun=EmployeeNo
WHERE Company = '1'
AND Date = '2013-05-06';

It is possible this will be helpful for you -
DELETE FROM dbo.WorkRecord2
WHERE EmployeeRun IN (
SELECT e.EmployeeNo
FROM dbo.Employee e
WHERE ...
)
Or try this -
DELETE FROM dbo.WorkRecord2
WHERE EXISTS(
SELECT 1
FROM dbo.Employee e
WHERE EmployeeRun = e.EmployeeNo
AND ....
)

Try this:
DELETE FROM WorkRecord2
FROM Employee
Where EmployeeRun=EmployeeNo
And Company = '1'
AND Date = '2013-05-06'

In SQL Server Management Studio I can easily create a SELECT query:
SELECT Contact.Naam_Contactpersoon, Bedrijf.BedrijfsNaam, Bedrijf.Adres, Bedrijf.Postcode
FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
I can execute it, and all my contacts are shown.
Now change the SELECT to a DELETE:
DELETE Contact
FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
All the records you saw in the SELECT statement will be removed.
You may even create a more difficult inner join with the same procedure, for example:
DELETE FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
INNER JOIN LoginBedrijf ON Bedrijf.IDLoginBedrijf = LoginBedrijf.IDLoginBedrijf

It should be:
DELETE zpost
FROM zpost
INNER JOIN zcomment ON (zpost.zpostid = zcomment.zpostid)
WHERE zcomment.icomment = "first"

Try this query:
DELETE WorkRecord2, Employee
FROM WorkRecord2
INNER JOIN Employee ON (tbl_name.EmployeeRun=tbl_name.EmployeeNo)
WHERE tbl_name.Company = '1'
AND tbl_name.Date = '2013-05-06';

You could even do a sub-query. Like this code below:
DELETE FROM users WHERE id IN(
SELECT user_id FROM Employee WHERE Company = '1' AND Date = '2013-05-06'
)

Another way is using CTE:
;WITH cte
AS (SELECT *
FROM workrecord2 w
WHERE EXISTS (SELECT 1
FROM employee e
WHERE employeerun = employeeno
AND company = '1'
AND date = '2013-05-06'))
DELETE FROM cte
Note: We cannot use JOIN inside CTE when you want to delete.

Here's what I currently use for deleting or even, updating:
DELETE w
FROM WorkRecord2 w,
Employee e
WHERE w.EmployeeRun = e.EmployeeNo
AND w.Company = '1'
AND w.Date = '2013-05-06'

You don't specify the tables for Company and Date, and you might want to fix that.
Standard SQL using MERGE:
MERGE WorkRecord2 T
USING Employee S
ON T.EmployeeRun = S.EmployeeNo
AND Company = '1'
AND Date = '2013-05-06'
WHEN MATCHED THEN DELETE;
The answer from Devart is also standard SQL, though incomplete. It should look more like this:
DELETE
FROM WorkRecord2
WHERE EXISTS ( SELECT *
FROM Employee S
WHERE S.EmployeeNo = WorkRecord2.EmployeeRun
AND Company = '1'
AND Date = '2013-05-06' );
The important thing to note about the above is it is clear the delete is targeting a single table, as enforced in the second example by requiring a scalar subquery.
For me, the various proprietary syntax answers are harder to read and understand. I guess the mindset for is best described in the answer by frans eilering, i.e. the person writing the code doesn't necessarily care about the person who will read and maintain the code.

This is a simple query to delete the records from two table at a time.
DELETE table1.* ,
table2.*
FROM table1
INNER JOIN table2 ON table1.id= table2.id where table1.id ='given_id'

Here is my SQL Server version
DECLARE #ProfileId table(Id bigint)
DELETE FROM AspNetUsers
OUTPUT deleted.ProfileId INTO #ProfileId
WHERE Email = #email
DELETE FROM UserProfiles
WHERE Id = (Select Id FROM #ProfileId)

Delete multiple table data using transaction block, table variable and JOIN.
BEGIN TRANSACTION;
declare #deletedIds table ( id int );
DELETE w
output deleted.EmployeeRun into #deletedIds
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
DELETE e
FROM Employee as e
INNER JOIN #deletedIds as d
ON d.id = e.EmployeeNo;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=43330dda6f1b71b8ec4172a24d5b6921
Delete multiple table data with temporary table and JOIN. Drop temporary table after deletion.
BEGIN TRANSACTION;
-- create temporary table
create table #deletedRecords (employeeId int);
-- INSERT INTO #deletedRecords
SELECT e.EmployeeNo
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
-- delete from WorkRecord2
DELETE w
FROM WorkRecord2 w
INNER JOIN #deletedRecords d
ON w.EmployeeRun = d.employeeId;
-- delete from Employee using exists
DELETE
FROM Employee
WHERE EXISTS (SELECT 1
FROM #deletedRecords d
WHERE d.employeeId = EmployeeNo);
-- drop temporary table
DROP TABLE #deletedRecords;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=d52c6c1ed91669d68fcc6bc91cb32d78
Alternative way to create temporary tables by using SELECT INTO
BEGIN TRANSACTION;
SELECT e.EmployeeNo employeeId
INTO #deletedRecords
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
-- delete from WorkRecord2
DELETE w
FROM WorkRecord2 w
INNER JOIN #deletedRecords d
ON w.EmployeeRun = d.employeeId;
-- delete from Employee using exists
DELETE
FROM Employee
WHERE EXISTS (SELECT 1
FROM #deletedRecords d
WHERE d.employeeId = EmployeeNo);
-- drop temporary table
DROP TABLE #deletedRecords;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=0f02f05616ce5b4dcc8fc67c6cf1e640
Remove a single table data using JOIN
DELETE w
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06'
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=84a60d1368556a8837281df36579334a
Delete single table data using CTE
WITH cte AS (
SELECT w.EmployeeRun
FROM WorkRecord2 w
WHERE EXISTS (SELECT 1
FROM Employee
WHERE EmployeeNo = w.EmployeeRun)
AND w.Company = 1
AND w.date = '2013-05-06'
)
DELETE
FROM cte
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=6590007b3c8c2ffad5563bd86606c5b1
Use ON CASCADE DELETE during foreign key creation in child table. If remove parent table data then corresponding child table data is automatically deleted.

Related

Need Combined SQL Query to Update 2 Tables

I am having 2 tables. Table1 and Table2. I need to update these 2 tables based on some conditions.
The SQL select query from Table1 will return multiple records, let's
name it as SQLQuery1
From SQLQuery1 results returned I need to loop through each record and
execute another SQL query from Table2 which will return only 1
record, let's name it as SQLQuery2
Update Table1 and Table2 with the results returned from SQLQuery2.
Is there is a single query to combine the above operations?
If you need more information please let me know
UPDATE:
Following are the Sample Queries used,
SELECT E.Id,E.Name
from Employee E
where E.transdate > '2019-01-201 00:00:01' -- Multiple Results(SQLQuery1)
SELECT top 1 ED.Id,ED.balance
FROM EmployeeDetails ED
where ED.Name= #Name -- Single Results((SQLQuery2)
UPDATE Employee set IsProcessed=true
where Id=#Id
UPDATE EmployeeDetails set IsProcessed=true
where Id=#Id
I would use an UPDATE with an INNER JOIN. I have no idea if it's best practice at this point in time or whether there is a better way to do this but it works for the example I have created in dbfiddle.
Something like this:
UPDATE E
SET IsProcessed = 1
FROM Employee E
INNER JOIN EmployeeDetails ED ON E.Id = ED.Id
WHERE E.transdate >= '2019-01-20 00:00:01' AND ED.name = 'Martin'
UPDATE ED
SET IsProcessed = 1
FROM EmployeeDetails ED
INNER JOIN Employee E ON E.Id = ED.Id
WHERE E.transdate >= '2019-01-20 00:00:01' AND ED.name = 'Martin'
I used >= because I just set all 3 created records to the datetime you have and forgot that looking for a datetime greater than that would provide me with nothing. I also used a hard-coded name Martin instead of using a variable.
Here is my link to the dbfiddle I created in which I created Employee and EmployeeDetails, filled them with test data and then proceeded to identify the correct records using the date, time and name joined by their ID values:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=4492b27a9790f34b0bff0996e7fb6d36
Use INNER JOIN :
update e
set e.IsProcessed = 1 -- assuming BIT type
from employee e inner join
EmployeeDetails ed
on ed.name = e.name and ed.id = e.id
where e.transdate > '2019-01-201 00:00:01';
update ed
set ed.IsProcessed = 1 -- assuming BIT type
from EmployeeDetails ed inner join
Employee e
on ed.name = e.name and ed.id = e.id and
where e.transdate > '2019-01-201 00:00:01';
I wouldn't do it like this.
You can use outer apply to get rid of the cursor:
SELECT *
FROM T_Query1
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = T_Query1.id
) AS tQuery2
Then you can do an update like this:
UPDATE A
SET some_value = tQuery2.some_new_value
FROM T_Query1 AS A
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = A.id
) AS tQuery2
Besides that, you cannot update 2 tables with one update statement, AFAIK.
Your best bet would be
;WITH CTE AS
(
SELECT T_Query1.field1, T_Query2.field2, T_Query2.newField1
FROM T_Query1
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = T_Query1.id
) AS tQuery2
)
-- SELECT * FROM CTE
UPDATE CTE SET field1 = newField1, field2 = newField1
but I don't think CTE updating can handle outer-apply.

Link all query (select and delete) in one

I am trying to make one statement(automated) of the following queries.
All i know proposal id from my UI. i do query manually like below
select * from tblAssessment where ProposalID like '%0081/2013/0587B%'
select * from tblAssessmentVersion where AssessmentID=587
select * from tblIdentifiedThreatenedSpecies where AssessmentVersionID=731
delete from tblIdentifiedThreatenedSpecies where PercentGain=0 and AssessmentVersionID=731
once i know the proposal id ,i query in to tblassessment to get the assessment id then use the assessment id to query in to assessmentversion table to find the assessment version ID then use the assessment version id in to Identified species table to delete the record where percentgain column is 0.
Appreciate all your help,thanks in advance
You can use DELETE FROM .. JOIN:
DELETE s
FROM tblIdentifiedThreatenedSpecies s
INNER JOIN tblAssessmentVersion v
ON v.AssessmentVersionID = s.AssessmentVersionID
INNER JOIN tblAssessment a
ON a.AssessmentID = v.AssessmentID
WHERE
a.ProposalID LIKE '%0081/2013/0587B%'
AND PercentGain = 0
To check for rows to be deleted, SELECT first:
SELECT s.*
FROM tblIdentifiedThreatenedSpecies s
INNER JOIN tblAssessmentVersion v
ON v.AssessmentVersionID = s.AssessmentVersionID
INNER JOIN tblAssessment a
ON a.AssessmentID = v.AssessmentID
WHERE
a.ProposalID LIKE '%0081/2013/0587B%'
AND PercentGain = 0
join all your SELECT in one subquery
delete from tblIdentifiedThreatenedSpecies
where PercentGain=0 and AssessmentVersionID in
(
select av.Id
from
tblAssessmentVersion av
join tblAssessment a on a.Id = av.AssessmentID
where a.ProposalID like '%0081/2013/0587B%'
)
I hope this will work.
delete from tblIdentifiedThreatenedSpecies
where PercentGain=0 and AssessmentVersionID=(
select top 1 AssessmentVersionID from tblAssessmentVersion where AssessmentID=(
select top 1 AssessmentID from tblAssessment where ProposalID like '%0081/2013/0587B%'
)
);
Here top 1 is used if query returns more than one records, which is optional it your query doesn't.
Thank you.

Multiple rows update in oracle sql using for loop

the below FOR loop doesn't work. I have two columns PID, PAYMENT in table t1 and table t2. I want to update PAYMENT in table t1 from table t2 where t1.PID=t2.PID
FOR X IN(select paymentterm,pid from temp_project)
LOOP
update project p
set p.paymentterm=temp_project.PID
where p.PID=X.PID;
END LOOP;
commit;
You can achieve this behavior without looping:
UPDATE project
SET paymentterm = (SELECT peymentterm
FROM temp_project
WHERE project.pid = temp_project.pid)
WHERE pid IN (SELECT pid FROM temp_project)
Try:
update project p
set paymentterm = (select t.paymentterm
from temp_project tp
where tp.pid = p.pid)
where pid in (select pid from temp_project)
... or, if temp_project.pid is constrained to be unique:
update (select p.pid,
p.paymentterm,
t.paymentterm new_paymentterm
from project p join temp_project t on p.pid = t.pid)
set paymentterm = new_paymentterm;
You might make sure that you're not making changes where none are required with:
update (select p.pid,
p.paymentterm,
t.paymentterm new_paymentterm
from project p join temp_project t on p.pid = t.pid
where coalesce(p.paymentterm,-1000) != coalesce(t.paymentterm,-1000))
set paymentterm = new_paymentterm;
(Guessing at -1000 being an impossible value for paymentterm there).
This could also be written as a MERGE statement.

Delete row from sql table where values not found in another table with multiple joins

I have the following query which returns the desired data. What I want to do is delete that data, however when I change the Select DQ.* to DELETE FROM DQ, I get an error indicating that
'... not updatable because the modification affects multiple base table'
I need to delete entries from the tbaccess_groupPermission table where appropriate module records are not found in the tbaccess_companyModules table.
WITH DQ AS
(
SELECT GP.* FROM tbaccess_groupPermission GP
JOIN tbaccess_groups G ON GP.GroupID = G.ID
WHERE G.CompanyID=6
AND GP.RoleName NOT IN
(
select Distinct(R.RoleName)
FROM tbAccess_Roles R
INNER JOIN tbAccess_CompanyModules C on R.ModuleID = C.ModuleID
WHERE C.CompanyID = 6)
)
SELECT * FROM DQ
Why not change the WITH statement to use an IN clause?
Something like
WITH DQ AS
(
SELECT GP.* FROM tbaccess_groupPermission GP
WHERE GP.GroupID IN (SELECT G.ID FROM tbaccess_groups G WHERE G.CompanyID=6)
AND GP.RoleName NOT IN
(
select Distinct(R.RoleName)
FROM tbAccess_Roles R
INNER JOIN tbAccess_CompanyModules C on R.ModuleID = C.ModuleID
WHERE C.CompanyID = 6)
)

How to merge two fields into single field using INNER JOIN

I have two tables.
**EmployeeInfo**
EmployeeName varchar(50)
EmailAddress varchar(100)
BranchID int
**BranchInfo**
BranchID int
opMgr varchar(100)
BranchMgr varchar(100)
I want a stored procedure in which if I pass email address as parameter and it should display the OpMgr and BranchMgr column from branchinfo table into single column of the relevant branch of EmployeeInfo. I am trying to write the following but no luck as i am getting multipart error.
SELECT BranchInfo.OpMgr FROM EmployeesInfo
UNION
SELECT BranchInfo.BranchMgr FROM EmployeesInfo
INNER JOIN BranchInfo ON EmployeesInfo.BranchID = BranchInfo.BranchID
WHERE AND EMPLOYEESINFO.EMAILADDRESS='john.d#mydomain.com'
Try this:
SELECT
E.EmployeeName,
E.EmailAddress,
B.BranchID,
B.BranchMgr + ' ' + B.opMgr ColName
FROM EmployeesInfo E
INNER JOIN BranchInfo B
ON E.BranchID = B.BranchID
WHERE E.EMAILADDRESS='john.d#mydomain.com'
it should display the OpMgr and BranchMgr column from branchinfo table
into single column of the relevant branch of EmployeeInfo
DECLARE #opMgr VARCHAR(100), #BranchMgr VARCHAR(100)
SELECT #opMgr = b.opMgr, #BranchMgr = b.BranchMgr
FROM EmployeeInfo e
JOIN BranchInfo b ON e.BranchID = b.BranchID
WHERE e.EMAILADDRESS='john.d#mydomain.com'
SELECT details
FROM ( VALUES (#opMgr),(#BranchMgr))
AS t(details)
you can have JOIN like this
SELECT b.opMgr + b.BranchMgr as Branch
FROM EmployeeInfo e
JOIN BranchInfo b ON b.BranchID = BranchID
WHERE e.EMAILADDRESS='john.d#mydomain.com'
Try this,
SELECT BranchInfo.OpMgr, BranchInfo.BranchMgr
FROM EmployeesInfo
INNER JOIN BranchInfo ON EmployeesInfo.BranchID = BranchInfo.BranchID
WHERE AND EMPLOYEESINFO.EMAILADDRESS = 'john.d#mydomain.com'