SQL - Delete from Multiple Tables (with FK) - sql

I'm trying to delete data from three tables.
I have an AccountId which I will set, then I want to delete the associated data.
The Id in Appointment.Id and AppointmentExtension.Id is the same value (GUID)
Table:Appointment
---------------------
- Id
- Name
- AccountId
Table: AppointmentExtension
----------------------
- Id
- Settings
Table:SettingItems
---------------------
- Id
- AppointmentExtensionId(FK)
So essentially I want to set the parameter #accountId. = "ABCD"
and delete all the records.
Note that I have a FK on SettingItems.AppointmentExtensionId = AppointmentExtension.Id,
Assume I need to delete all the items in table SettingItems before deleting the other two due to the FK?
An example of how to do this would be great?

you need tot start from the child in order as below:
delete from SettingItems
where AppointmentExtensionId in ( select Id from AppointmentExtension)
delete from AppointmentExtension where id in ( select id from Appointment where #AccountId = accountId
delete from Appointment where #AccountId = accountId

Using delete from join
delete si
from SettingItems si
join Appointment a on si.AppointmentExtensionId = a.id
and a.AccountId = #accountId;
delete ae
from AppointmentExtension ae
join Appointment a on ae.id = a.id
and a.AccountId = #accountId;

Related

How to get a selection from tables related using a many-to-many relationship

I'm new to sql, I've looked at similar questions and answers on the platform, but still couldn't solve my problem.
I have three tables:
CREATE TABLE CartProducts (
Id PRIMARY KEY
ProductId int
Quanity int
)
CREATE TABLE CartCartProducts ( /* <-- many to many table */
CartProductsId PrimaryKey
CartId PrimaryKey
)
CREATE TABLE Cart (
Id PrimaryKey
UserId int
)
Before the query I have the following data:
I know the UserId
I know the ProductId
I know the CartId
I need to get the user's product with the passed product's id and user's id
I tried this:
SELECT
*
FROM
cart_products cp
JOIN cart_cart_products cm2m1 ON cm2m1.cart_id = %d
INNER JOIN cart_cart_products cm2m2 ON cm2m2.cart_products_id = cp.id
I know that using * is not recommended, I will remake it in the future
you always have to join all tables. with their columns, after that you have access to all columns and can extract all information needed.
the use of placehoder and parpameters, i omitted, as i don't know which langua you are using, but a quick search should find you a lot of answers
Following query fund you the quantity of a cart with number 1 of userid 1 and of the product 1
Fromhere you have all possibility, to search for all cart of a user, or all products he purchased
SELECT
cp.Quanity
FROM
cart_products cp
JOIN cart_cart_products cm2m1 ON cm2m1.cart_id = cp.iId
INNER JOIN cart c = c.Id = cm2m1.CartId
WHERE c.UserId = 1 AND c.id = 1 AND cp.ProductId = 1

update email selected from another table using the foreign key relation

I have 3 tables called Contact, APP_User, Customer Table. here I want to select email from my Contact table based on Contact_ID as Foreign key in App_User table and I want to Update the selected email into my Customer table based on App_User_Id as Foreign key in Customer table and primary key in APP_User Table.
Clearly:- I want to fetch email where Contact.contact_ID = APP_User.Contact_ID and Update the fetched email to Customer.emial where APP_User.App_User_Id = Customer.App_User_Id
UPDATE CRM.CRM_CUSTOMER_USER
SET EMAIL = (SELECT EMAIL
FROM QA29.ST_CONTACT
INNER JOIN QA29.ST_APP_USER ON QA29.ST_CONTACT.CONTACT_ID = 129)
WHERE APP_USER_ID = 120;
But it results in:
ORA-01427: single-row subquery returns more than one row
Join condition is missing in the inner query.
There must be multiple rows returned by the following query which is the cause of the issue:
SELECT
EMAIL
FROM
QA29.ST_CONTACT
INNER JOIN QA29.ST_APP_USER ON QA29.ST_CONTACT.CONTACT_ID = 129;
You must restrict this to single record using valid join condition, something like the following:
UPDATE CRM.CRM_CUSTOMER_USER
SET
EMAIL = (
SELECT
EMAIL
FROM
QA29.ST_CONTACT
INNER JOIN QA29.ST_APP_USER
ON QA29.ST_CONTACT.APP_USER_ID = QA29.ST_APP_USER.APP_USER_ID -- OR SOMETHING LIKE THIS
AND QA29.ST_CONTACT.CONTACT_ID = 129
)
WHERE
APP_USER_ID = 120;
Cheers!!

SQL Server Select from table where primary key does not appear as foreign key in another table

I have 3 tables -
User UserID PK
SecurityGroup SecurityGroupID PK, SecurityGroupName
UserSecurityGroup UserSecurityGroupID, UserID FK, SecurityGroupID FK
I am trying to select the names of the security groups that a user is NOT a part of.
A user can be a member of more than one group.
i.e. I have three security groups: Admin, Moderator, Member
I pass through a UserID. Said user is assigned to the Admin and Moderator groups but is NOT part of the Member group. I'm trying to display "Member".
These are my attempts so far:
Attempt 1 -
select tblSecurityGroup.SecurityGroupName
from tblSecurityGroup
inner join tblUserSecurityGroup
on tblSecurityGroup.SecurityGroupID = tblUserSecurityGroup.SecurityGroupID
inner join tblUser
on tblUserSecurityGroup.UserID = tblUser.UserID
where tblUser.UserID = 1
and tblSecurityGroup.SecurityGroupID not in (tblUserSecurityGroup.SecurityGroupID);
Attempt 2 -
select tblSecurityGroup.SecurityGroupName
from tblSecurityGroup
inner join tblUserSecurityGroup
on tblSecurityGroup.SecurityGroupID = tblUserSecurityGroup.SecurityGroupID
inner join tblUser
on tblUserSecurityGroup.UserID = tblUser.UserID
where tblUser.UserID = 1
and not exists (select tblSecurityGroup.SecurityGroupID
from tblSecurityGroup
where tblUserSecurityGroup.SecurityGroupID = tblSecurityGroup.SecurityGroupID);
Guidance for a nooby student would be most appreciated.
Your question can be answered by a not exists query. Here is one method:
select sg.SecurityGroupName
from tblSecurityGroup sg
where not exists (select 1
from tblUserSecurityGroup usg
where sg.SecurityGroupID = usg.SecurityGroupID and
usg.UserID = 1
);
Note that tblUser is not needed because UserID is in tblUserSecurityGroup.

Delete rows from multiple tables with foreign keys

I have three tables
userTable with following rows Id, FirstName, LastName, Email
Product A with following rows Id, UserId(FK), startDate
Product D with following rows Id, UserId(FK), startDate
I want to delete rows from three tables with particular UserId.
What I want to achieve -
Find the id given email (select id from userTable where Email = 'abc.com') - got back id - 3
Delete from Product A where id = 3
Delete from Product D where id = 3
Delete from userTable where id = 3
I want to create a script.
Any help is appreciated or learning reference would be great.
Declare a variable and save the id to that variable. Use that Id for the delete query.
DECLARE #Id INT;
SELECT #Id=id
FROM userTable
WHERE Email = 'abc.com'
DELETE FROM Product A WHERE id = #Id
DELETE FROM Product D WHERE id = #Id
DELETE FROM userTable WHERE id = #Id
But I guess in your case you have UserId as the FK so you should be trying this:
DELETE FROM Product A WHERE UserId= #Id
DELETE FROM Product D WHERE UserId= #Id
DELETE FROM userTable WHERE id = #Id
Note: If you want to do the same thing what's there in question, go for 1st one. If you want to delete the relevant user records from A and D table then go for the 2nd method where you are deleting the records using the FK.
From what I can gather from your question you want something like this:
DELETE FROM
userTable,
ProductA,
ProductB
WHERE
userTable.Id = (select Id from userTable where Email like 'abc.com') AND
userTable.Id = ProductA.Id AND
userTable.Id = ProductB.Id;
And the Email in the subquery in the WHERE clause would be your input parameter
DISCLAIMER: From a Sybase/SQL Anywhere background, this would be possible, I'm not sure if it could be done in SQL-server.

Get latest record from second table left joined to first table

I have a candidate table say candidates having only id field and i left joined profiles table to it. Table profiles has 2 fields namely, candidate_id & name.
e.g. Table candidates:
id
----
1
2
and Table profiles:
candidate_id name
----------------------------
1 Foobar
1 Foobar2
2 Foobar3
i want the latest name of a candidate in a single query which is given below:
SELECT C.id, P.name
FROM candidates C
LEFT JOIN profiles P ON P.candidate_id = C.id
GROUP BY C.id
ORDER BY P.name;
But this query returns:
1 Foobar
2 Foobar3
...Instead of:
1 Foobar2
2 Foobar3
The problem is that your PROFILES table doesn't provide a reliable means of figuring out what the latest name value is. There are two options for the PROFILES table:
Add a datetime column IE: created_date
Define an auto_increment column
The first option is the best - it's explicit, meaning the use of the column is absolutely obvious, and handles backdated entries better.
ALTER TABLE PROFILES ADD COLUMN created_date DATETIME
If you want the value to default to the current date & time when inserting a record if no value is provided, tack the following on to the end:
DEFAULT CURRENT_TIMESTAMP
With that in place, you'd use the following to get your desired result:
SELECT c.id,
p.name
FROM CANDIDATES c
LEFT JOIN PROFILES p ON p.candidate_id = c.id
JOIN (SELECT x.candidate_id,
MAX(x.created_date) AS max_date
FROM PROFILES x
GROUP BY x.candidate_id) y ON y.candidate_id = p.candidate_id
AND y.max_date = p.created_date
GROUP BY c.id
ORDER BY p.name
Use a subquery:
SELECT C.id, (SELECT P.name FROM profiles P WHERE P.candidate_id = C.id ORDER BY P.name LIMIT 1);