I'm hesitant to run this query which deletes data (for obvious reasons).
I would like to delete the the matching rows from two tables, where the ID = the ID of a third table (which i want to remain unaffected)
This is the exact query I would like to run:
DELETE FROM ItemTracker_dbo.Transaction t,
ItemTracker_dbo.Purchase p
USING ItemTracker_dbo.Transaction
INNER JOIN ItemTracer_dbo.Purchase ON p.Transaction_ID = t.Transaction_ID
INNER JOIN ItemTracker_dbo.Item i ON i.Item_ID = p.Item_ID
WHERE i.Client_ID = 1
To test this, i tried running a select replacing DELETE FROM with SELECT * FROM, and I get a syntax error 'near USING'. When I remove USING ... it selects EVERY row in the table (ignoring the client_id=1 clause).
I (essentially) copied the syntax from the mysql manual (obviously replacing the values).
Is this query valid?
I'm sorry I didn't comment instead of post, but I just don't have enough reputation. Why don't you run it as a transaction and see the results? Or am I missing something?
http://dev.mysql.com/doc/refman/5.0/en/commit.html
As far as I know, you can't do that. The way to acomplish that is with a transaction.
START TRANSACTION;
DELETE FROM tableOne WHERE criteria;
DELETE FROM tableTwo WHERE criteria;
COMMIT;
If something goes wrong between the statements, you can issue a ROLLBACK and your data will be there.
The catch is, THIS WON'T WORK WITH MyISAM. MyISAM doesn't support transactions, so it will simply delete the data and there is no way to roll it back. They need to be InnoDB tables. It does this silently. I've lost a production table that way (good thing I had a backup and it wasn't updated much).
Easiest way to find out if the tables are InnoDB?
SHOW CREATE TABLE tableName;
At the end, it will have something like 'Engine = InnoDB' or 'Engine = MyISAM'.
I'm not familiar with this (non-standard?) use of USING to join tables in the above, but if you just want to delete rows from only some of the tables in the join the normal way would be:
DELETE Purchase, `Transaction`
FROM Item
JOIN Purchase ON Purchase.Item_ID=Item.Item_ID
JOIN `Transaction` ON `Transaction`.Transaction_ID=Purchase.Transaction_ID
WHERE Item.Client_ID=1;
Assuming I understand your schema right. It seems a bit unusual to be deleting the Transaction that is referenced from the Purchase as this would naturally be a many-Purchases-to-one-Transaction relation. Is there a UNIQUE constraint to ensure it is one-to-one? If not, can you be sure no other Purchase will be referencing the deleted Transaction?
You can test the above construct as a SELECT simply:
SELECT Purchase.Purchase_ID, `Transaction`.Transaction_ID
FROM Item ...
Related
Let's assume I have a customer table that has a customer_id column and a has_orders column among others. Let's also assume I have an order table that has a customer_id column referencing customers in the customer table.
If I want to update the has_orders column, I can run the following statement:
update customer set has_orders = customer_id in (select customer_id from order)
This works. However, it's slow, even though I have indexes on customer_id in both tables. Is there another update statement (e.g. using joins) that can be faster?
An index on customer_id in the order table should already be pretty optimal. You could write your update using exists instead:
UPDATE customer c
SET has_orders = EXISTS (SELECT 1 FROM order o WHERE o.customer_id = c.customer_id);
The possible advantage of the above versus using IN is that EXISTS will stop as soon as it finds a match.
If has_orders is defined as boolean not null default false (a good choice), and orders can never be deleted (likely), update using a join:
update orders o
join customer c on c.id = o.customer_id
set has_orders = true
See live demo.
If order can be deleted (unlikely), update using an outer join, although this will be slower:
update customer c
left join `order` o on o.customer_id = c.id
set has_orders = o.customer_id is not null
See live demo.
Side note: If possible, prefer not naming tables/columns with reserved words, such as order, because it can require inconvenient delimiting with back-ticks to avoid syntax errors.
Are you really sure you need to update the customer table asynchronously? I guess it might be a poor practice as the integrity of the data can be lost. Moreover this approach breakes normal form idea as the data is duplicated. It seems that a much better way is to retreive the value of has_orders selecting the flag (using exists statement proposed by #Tim-Biegeleisen or any other) from order table on demand and joining it to the dataset from customers table.
If the excess column is inevitable i would update it any time upon inserting/updating/deleting the order table and using affected customer id only. This can be done in a trigger. It will be rather fast.
A religious war:
The DB purist would point out that has_order is redundant info, hence a no-no.
The performance fanatic would insist on having (and maintaining) has_order
I bring up that debate, not to wage a war, but to point out that getting rid of the flag may be better overall. When you need the flag, simply do a LEFT JOIN or AND EXISTS(SELECT..) or some other dynamic test.
I have three tables. One is a table of deletion candidates. This table was created with certain criteria, but did not include a couple of factors for consideration (limitations of the system). The other two tables were created considering those "left out" factors. So, I need to run a SELECT query on these three tables to come up with a deletion list.
What I started with is:
SELECT inactive.id
FROM inactive, renamed, returned
WHERE NOT EXISTS (inactive.id = remamed.id and inactive.id = returned.id)
But this is giving me an error. Can someone point out my error here?
Thank you
It's not entirely clear what you are trying to do here.
I assume you want a list of all rows from the inactive table that do not exist in either the renamed table or the inactive table. Is that right?
If so you can use a query like this:
SELECT inactive.id
FROM inactive
WHERE NOT EXISTS (select null from renamed where renamed.id = inactive.id)
AND NOT EXISTS (select null from returned where returned.id = inactive.id)
I've got two tables, we'll call them email_bounces and master_email_list.
master_email_list is ~3.5m records.
email_bounces is ~100,000 records.
I'm trying to do a query where I update bounce=1 in master_email_list if the email address is found in email_bounces.
Here's what I have.
update 'master_email_list' set bounce=1 where email in (select email FROM 'email_bounces')
Except that doesn't seem to work, it queries, then hangs indefinitely (I left it running overnight, after about 4 hours running prior).
Help is appreciated.
Use
update master_email_list l
inner join email_bounces b on b.email = l.email
set bounce = 1
You could also try to deactivate keys during the update to speed things up:
ALTER TABLE master_email_list DISABLE KEYS;
And afterwards
ALTER TABLE master_email_list ENABLE KEYS;
By using table alias names you have to set it.
In this i am using inner join
update master_email_list mel
inner join email_bounces eb
on mel.email = eb.email
set mel.bounce = 1
If that simple query takes hours, I can only see two possible reasons;
You're missing an index with master_email_list.email as a first column.
CREATE INDEX ix_email ON master_email_list(email);
...should speed things up significantly.
You have an active transaction on the table that holds a lock. Check that you have no uncommitted transactions pending, and if you can't find them, check this answer how to look for them.
I have tried this many different ways but am getting errors strange results in all of them. I have a master table of transactions: Transactions and a query ArchiveDelete that finds new transactions from a temporary table based on the LastModifyDate. I'd like to delete transactions where ConfirmationNumber in Transactions = ConfirmationNumber in ArchiveDelete.
My first attempt was simple:
DELETE Transactions.*
FROM Transactions INNER JOIN ArchiveDelete ON Transactions.ConfirmationNumber = ArchiveDelete.ConfirmationNumber;
and I received an error: 'Could not delete from specified tables.' Clicking help is useless. I have full rights to the tables. I've attempted to Google the error and one suggestion was to run this instead:
DELETE Transactions.*
FROM Transactions Where Transactions.ConfirmationNumber in (Select ConfirmationNumber from ArchiveDelete)
But this takes forever and I don't have all day for a simple delete. There are only 183 transactions I need to remove.
I also tried the Delete using Exists here: How to delete in MS Access when using JOIN's?
DELETE Transactions.*
FROM Transactions
Where Exists(Select 1 from ArchiveDelete Where ArchiveDelete.ConfirmationNumber = Transactions.ConfirmationNumber) = True
But now it wants to delete all 47073 rows in my table, not just the 183 that match.
What am I doing wrong? Why is this so difficult?
I believe because ArchiveDelete is a query might be why you are having trouble. Try making a temporary table ArchiveDeleteTemp instead (at least to test) and using that instead.
DELETE Transactions.*
FROM Transactions INNER JOIN ArchiveDeleteTemp ON Transactions.ConfirmationNumber = ArchiveDeleteTemp.ConfirmationNumber;
I need to update some information which are stored in two tables. To update one of the table, a JOIN with the other table must be done. I was wondering, if I can update both with a single query. Some posts suggested using a trigger. I was hoping there's another way, since I will have to do it in C#. Also I saw other posts saying it's possible using something like this:
update pd, pr
set pd.Name = 'Test',
pr.Date = '2012-07-31',
from prDetail pd
left join pr on pd.ID = pr.ID
where pd.Code = '45007'
and pr = '2019'
and pr.Item = '1'
This is not working for me (it's showing this error: Incorrect syntax near ','). Can this be achieved in some way?
No.
You can only update one table at a time.
Separate your update into two update queries, and if necessary, wrap them in a transaction.
Yes, As #podiluska said you can only update one table at a time. And you can also use transaction for executing both query with a single transaction.
Else,
If your table/relation has dependency (foreign key and primary key ) relation , then you can use cascade options.
Else,
You can use Trigger.
No, it's not possible to update two at a time but you may consider wrapping it up in a stored procedure and calling that instead. You should try to avoid triggers for something like this if possible.