Delete from multiple tables with MyISAM - php

I already tried lots and lots of combinations but none seem to work =(
I have these two SQL commands:
$sql = "DELETE FROM infogt2000_partner_lead_invoice WHERE infogt2000_partner_lead_invoice_lead_id = ".$id_invoice;
$sql = "DELETE FROM infogt2000_partner_lead WHERE infogt2000_partner_lead_id = ".$id;
And they have to execute "together". Well, if I delete an information from partner_lead it also has to delete the same info from infogt2000_partner_lead_invoice.
The id in infogt2000_partner_lead_id and infogt2000_partner_lead_invoice_lead_id are the same but I cannot write it correctly.
I am currently using MySQL and the type is MyISAM

I gess you will need to use inner join:
DELETE infogt2000_partner_lead_invoice, infogt2000_partner_lead
FROM infogt2000_partner_lead_invoice
INNER JOIN infogt2000_partner_lead
WHERE infogt2000_partner_lead_invoice.infogt2000_partner_lead_invoice_lead_id = infogt2000_partner_lead.infogt2000_partner_lead_id
AND infogt2000_partner_lead_invoice_lead_id = $id

You should consider converting your database tables to InnoDB so that you can create foreign key constraints to cascade on delete. Otherwise, you must write multiple queries, starting from the lowest item in the chain of hierarchy working your way up to the parent-most table. Eg: delete grandchildren, then children, then parents.

Related

MySQL update query in PHP and get multiple ids returned

I want to perform a mysql UPDATE query and then get an array of ids that were effected in the change.
This is my update query
mysql_query("UPDATE table SET deleted='1' WHERE id='$id' OR foo='$foo' OR bar='$bar'");
I know that I can do something like this to get the created id from an INSERT query
mysql_query("INSERT INTO table (id,foo,bar) VALUES ('$id','$foo','$bar')");
$newid = mysql_insert_id();
I don't think MySQL has anything like the OUTPUT or RETURNING clauses that other databases support. You can get the list of ids by running a select before the update:
create table temp_table ids_to_update as
SELECT id
FROM table
WHERE (deleted <> '1' or deleted is null) and *id='$id' OR foo='$foo' OR bar='$bar');
Note that MySQL doesn't do an update when the value doesn't change. Hence the first condition -- which you may or may not find important.
Then, to ensure integrity (in the event of intervening transactions that change the data), you can do:
update table t join
temp_table tt
on t.id = tt.id
set deleted = '1';
You could also wrap the two queries in a single transaction, but I think using a temp table to store the ids is probably easier.

Storing MySQL values as integers

I have two database tables that I am using to create a Twitter-style following system.
sh_subscriptions
=> id
=> user_id
=> feed_id
sh_feeds
=> id
=> item
=> shop_name
=> feed_id
The problem with storing feed_id rather than shop_name in sh_subscriptions is that it requires a lot of table joining:
$id = $_POST['id'];
$user_id = $id['id'];
$shop_name = mysqli_escape_string($con, $_POST['shop_name']);
$query = "SELECT * FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
$result = mysqli_query($con, $query) or die(mysqli_error($con));
if (mysqli_num_rows($result) > 0)
{
$query2 = "DELETE FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
$result2 = mysqli_query($con, $query2) or die(mysqli_error($con));
}
else
{
// insert the row instead
}
(I know there's an error somewhere in the if statement, but I'll worry about that later.)
If I were to replace feed_id with shop_name, I would be able to replace line 5 with this:
$query = "SELECT * FROM sh_subscriptions WHERE user_id = $user_id AND shop_name = '$shop_name'";
My question is: is it always preferable to store MySQL values as integers where possible, or in a situation like this, would it be faster to have sh_subscriptions contain shop_name rather than feed_id?
Your sh_subscriptions table is actually a many-to-many join table that relates users to feeds. This is considered a fine way to design database schemas.
Your basic concept is this: you have a collection of users and a collection of feeds. Each user can subscribe to zero or more feeds, and each feed can have zero or more subscribers.
To enter a subscription you create a row in the sh_subscriptions table. To cancel it you delete the row.
You say there's "a lot of table joining." With respect, this is not a lot of table joining. MySQL is made for this kind of joining, and it will work well.
I have some suggestions about your sh_subscriptions table.
get rid of the id column. Instead make the user_id and feed_id columns into a composite primary key. That way you will automatically prevent duplicate subscriptions.
add an active column ... a short integer ... to the table. When it is set to a value of 1 your suscription is active. That way you can cancel a subscription by setting active to 0.
you might also add a subscribed_date column if you care about that.
create two compound non unique indexes (active,user_id,feed_id) and (active,feed_id,userId) on the table. These will greatly accelerate queries that join tables like this.
Query fragment:
FROM sh_feed f
JOIN sh_subscription s ON (f.feed_id = s.feed_id AND s.active = 1)
JOIN sh_users u ON (s.user_id = u.user_id)
WHERE f.shop_name = 'Joe the Plumber'
If you get to the point where you have hundreds of millions of users or feeds, you may need to consider denormalizing this table.. that is, for example, relocating the shop name text so it's in the sh_subscriptions table. But not now.
Edit I am proposing multiple compound covering indexes. If you're joining feeds to users, for example, MySQL starts satisfying your query by determining the row in sh_feeds that matches your selection.
It then determines the feed_id, and random-accesses your compound index on feed_id. Then, it needs to look up all the user_id values for that feed_id. It can do that by scanning the index from the point where it random-accessed it, without referring back to the table. This is very fast indeed. It's called a covering index.
The other covering index deals with queries that start with a known user and proceed to look up the feeds. The order of columns in indexes matters: random access can only start with the first (leftmost) column of the index.
The trick to understand is that these indexes are both randomly accessible and sequentially scannable.
one other note If you only have two columns in the join table, one of your covering indexes is also your primary key, and the other contains the columns in the reverse order from the primary key. You don't need any duplicate indexes.

SQL Query result, comparison and where clause

I am building a site and i need to retrieve some information. I have this query.
$SQL = "SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106,
richiesta_ccnl_107, coop_va_109, nome_pdv_110,
indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22 ";
I need to add this other code:
WHERE civicrm_event.title_en_US='".addslashes($_GET["titles"])."'
but it's not working...
i need to compare let's say the id of another table with the id of the current table... How to do that?
Thanks in advance...
You should learn something about joining tables...
Do not know what the relation is between the two tables (simply said: what column from one table is pointing to what column at other one), but try something similar (modification needed to meet You DB structure) - now lets assume both tables have related column called event_id:
$SQL = "SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106,
richiesta_ccnl_107, coop_va_109, nome_pdv_110,
indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22 cvistlsp22
LEFT JOIN civicrm_event ce ON ce.event_id = cvistlsp22.event_id
WHERE ce.title_en_US='".mysql_real_escape_string($_GET["titles"])."'";
civicrm_value_informazioni_su_tute_le_schede_p_22 table name is very long and You will not be able to create a table with such long name in other DBMS (e.g. ORACLE), so try to make it shorter while still self-describing...
If You want to join tables they have to have a relation, read more about relations and how to use them here: http://net.tutsplus.com/tutorials/databases/sql-for-beginners-part-3-database-relationships/
You are retrieving the data from table civicrm_value_informazioni_su_tute_le_schede_p_22 in your query while the where clause you are adding, refers to the table civicrm_event. You need to add this new table in the from clause and do a join among the two tables using some common key. Example below:
$SQL = "
SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106, richiesta_ccnl_107, coop_va_109, nome_pdv_110, indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22
JOIN civicrm_event ON civicrm_value_informazioni_su_tute_le_schede_p_22.ID_PK = civicrm_event.ID_FK
WHERE civicrm_event.title_en_US='".addslashes($_GET["titles"])
";
You need to replace the ID_PK and ID_FK with the relevant Primary and Foreign Keys that bind the tables together.
Please note using query params like that is not recommended. Please read PHP Documentation here for more explanation.

Can this mySQL query be optimized better? Not a mySQL guru but I think I got it right

Basically, I have two tables that have a 1 to 1 relation.
When I delete a row from subset_panel_options I also want to delete the related row in subset_panel_options_list
Here is some of structure for the two tables. There is no need to show the full table.
[subset_panel_options]
->id
->subset_panel_id
[subset_panel_options_list]
->id
->subset_panel_options_id
DELETE subset_panel_options, subset_panel_options_list
FROM subset_panel_options
JOIN subset_panel_options_list
WHERE subset_panel_options.id = subset_panel_options_list.subset_panel_options_id
AND subset_panel_id = $subsetPanelId
Yes, it can:
DELETE FROM subset_panel_options
LEFT JOIN subset_panel_options_list
ON (subset_panel_options.id = subset_panel_options_list.subset_panel_options_id)
WHERE subset_panel_options.subset_panel_id = $subsetPanelId
Using LEFT JOIN you ensure you are deleting from "subset_panel_options" even if there is no corresponding match in the subset_panel_options_list table.
You may also want use referential integrity features available in InnoDB engine. In this case, you need to define subset_panel_options_id as a FK (foreign key) in the subset_panel_options_list table, and an "ON DELETE CASCADE" constraint on it, meaning that when rows at subset_panel_options are deleted, the "orphan" rows in subset_panel_options_list should be immediately deleted too.

I can't delete records from MySql

I have two tables. table a references table b I believe.
When I try to delete the package alltogether like this:
$query="DELETE a, b FROM classified as a, $sql_table as b WHERE a.ad_id = '$id'
AND a.classified_id = b.classified_id AND a.poster_password='$pass'";
b MUST be deleted first I guess.
Even in PhpMyAdmin I cant delete a if b is still there, so I delete b first.
But what decides the order in which comes first?
The tables are alla InnoDB.
What should I do?
Thanks
The MySQL manual says about multi-table DELETE and foreign keys:
If you use a multiple-table DELETE
statement involving InnoDB tables for
which there are foreign key
constraints, the MySQL optimizer might
process tables in an order that
differs from that of their
parent/child relationship. In this
case, the statement fails and rolls
back. Instead, you should delete from
a single table and rely on the ON
DELETE capabilities that InnoDB
provides to cause the other tables to
be modified accordingly.
So that when a record in your main table is deleted, so are its foreign references, e.g:
ALTER TABLE products
ADD CONSTRAINT fk_supplier
FOREIGN KEY (supplier_id, supplier_name)
REFERENCES supplier(supplier_id, supplier_name)
ON DELETE CASCADE;
Your Delete syntax is invalid. You need to do this in two statements (unless as nuqqsa mentioned, you have CASCADE DELETE enabled on the relationship between table a and table b):
Delete From b
Where Exists (
Select 1
From a
Where a.poster_password = '$pass'
And a.ad_id = '$id'
And a.classified_id = b.classified_id
)
Delete From a
Where a.poster_password = '$pass'
And a.ad_id = '$id'
What decides which comes first is the foreign keys relationships. Whichever table is the parent table must be deleted from last.

Categories