Delete rows from multiple tables with foreign keys - sql

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.

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

SQL - Delete from Multiple Tables (with FK)

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;

SQL selecting multiple record by different variable

Ok, so I have a table Assignment:
[UserId]
[GroupId]
[UpdatedBy]
[UpdatedAt]
Also, I have a function for returning users from a specific group:
select UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId = ?
In Assignment, I want to check all groups that our user is listed and then I want to select ALL users from these groups, without duplicate.
How can I achieve this?
Edit:
Sample output form selecting groupid = 4
for example user "test1" belong to other group where id=2 at the same time and i want selected all users from for example group 2 and 4 (cause in this example test1 said so) without records duplicate
All groups from one UserId (say UserId 10):
select GroupId from Assignment where UserId = 10
Select all users from those groups (without duplicate):
select distinct UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId in (select GroupId from Assignment where UserId = 10)
I hope this is what you wanted.
An inner self join should get you the IDs of the users you're looking for. Join the result with your user table (which you didn't post) to possibly get other information about these users.
SELECT DISTINCT
a2.userid
FROM assignment a1
INNER JOIN assignment a2
ON a2.groupid = a1.groupid
WHERE a1.userid = ?;
(Replace the ? with the ID of the user, you want to start with.)
Assuming your input is a user id:test1 and assuming that you are just looking at one table (Assignment)
DECLARE #UserId INT = 2
;WITH GROUPS AS
(
SELECT DISTINCT GroupId FROM Assignment WHERE UserId = #UserId
)
SELECT distinct assgn.UserName, gps.GroupId FROM Assignment assgn
INNER JOIN
GROUPS gps ON
assgn.GroupId = gps.GroupId
Please let me know if this helps

SQL - Select referential data from multiple tables in one SQL call

For example I have 4 tables, all with say userID (which can be referenced more than once. So for example I can have:
Cars
id, ..., userID // userID = owner of the car
Garages
id, ..., userID // userID = owner of the garage
Tools
id, ..., userID // userID = owner of the tool
Now I want to do a query to delete the user, but I only want to delete the user if all their related data is gone. In other words, I want to make sure there is no referenced data (let's say I'm not allowed to have userID = -1 or null. It has to be assigned to a user
The only way I can see to do the checks is:
SELECT count(*) FROM Cars WHERE USERID = userID
SELECT count(*) FROM Garages WHERE USERID = userID
SELECT count(*) FROM Tools WHERE USERID = userID
Where I have to check if any of the results is greater than 0. Is there a way to do this check across N tables in one SQL SELECT query?
If you want to prevent deleting of users that still have cars, garages or tools you should add a foreign key from those tables to the user table.
If you then try to delete a user which is still referenced you'll get an error which you can catch and deal with, e.g. by displaying an approriate error message to the user.
This has the added benefit that the deletion will always be prevented, regardless on how someone tries to delete a user (SQL commandline, a buggy piece of code in your application, ...)
You can just add up the counts, like this:
SELECT (SELECT count(*) FROM Cars WHERE USERID = userID)
+ (SELECT count(*) FROM Garages WHERE USERID = userID)
+ (SELECT count(*) FROM Tools WHERE USERID = userID)
FROM ...
If the result is non-0, you have a referenced user.
SELECT (SELECT count(*) FROM Cars WHERE USERID = userID) as CarCount
, (SELECT count(*) FROM Garages WHERE USERID = userID) as GarageCount
, (SELECT count(*) FROM Tools WHERE USERID = userID) as ToolCount
You could also try this, if Cars is the main table which you want to change:
SELECT count(*)
FROM Cars
INNER JOIN
Garages
ON Cars.USERID = Garages.USERID,
INNER JOIN
Tools
ON Cars.USERID= Tools.USERID
WHERE Cars.USERID = SOME_USER_ID;
Suggest to create a foreign key for the USERID.

sql selecting from different tables based on boolean

I have a simple stored procedure like so:
ALTER PROCEDURE [dbo].[spList_Report]
#id INT
AS
SET NOCOUNT ON
SELECT *
FROM
tblProducts as products
WHERE
product.intID = #id
I have 2 user tables: MainUser and SubUser
Both tables have a foreign key column productID which is related to the primary key intID of the product table intID. They both also have a column emailAddress. The product table also has a bit column isMainUser.
How can I update my stored procedure to return the column emailAddress based on the isMainUser value? So if the value is true it selects the email address from the MainUser table and if its false then it selects the emailAddress from the SubUser table.
E.g what I want is only one emailAddress column:
ALTER PROCEDURE [dbo].[spList_Report]
#id INT
AS
SET NOCOUNT ON
SELECT
products.*
, myUser.emailAddress
FROM
tblProducts as products
WHERE
product.intID = #id
You have left out some important information. I am assuming that
Products can be joined with MainUser on a UserProductID
Products can be joined with SubUser on a UserProductID
There is 1 Main user for each product. (most likely not but that will need to be adressed when you have given us more information)
There is 1 Sub user for each product.
SQL Statement
SELECT products.*
, CASE WHEN isMainUser=1
THEN MainUser.emailAddress
ELSE SubUser.emailAddress
END
FROM tblProducts as products
LEFT OUTER JOIN MainUser mu ON mu.UserProductID = products.UserProductID
LEFT OUTER JOIN SubUser su ON su.UserProductID = products.UserProductID
WHERE product.intID = #id
Note that it is considered bad practice to use a SELECT *. SELECT * should never be present in production code.
Create a view on the two tables and join to that in your proc