Cascade delete in many-to-many tables - mysql

Assume a set of mailing lists in which individuals may be members of more than one list. I've set up a join table:
members -> members2lists <- lists
If the user wants to remove a member from one list only, it would seem necessary only to delete the appropriate row in the members2lists table. But how do I specify the cascading so as not to leave them as an orphan if they're a member of only one list? In other words, how do I delete a member if and only if they are a member of solely the list I'm removing them from?
I'm using PHP and mySQL with InnoDB tables.

Thanks David for your response. I've solved the problem this way (I hope the first two functions are self-expanatory):
$memberID = getIDFromMembers($pdo, $email);
$currListID = getIDFromList($pdo, $listname);
// remove record from join table
$sql = 'DELETE FROM `members2lists` WHERE `member_fk` = :member AND `list_fk` = :list';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':member', $memberID);
$stmt->bindParam(':list', $currListID);
$stmt->execute();
// check if another record exists in the join table for the same member
$sql = 'SELECT `member_fk` FROM `members2lists` WHERE `member_fk` = :member';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':member', $memberID);
$stmt->execute();
$row = $stmt->fetch();
if($row === false)
{
// there isn't, the member is an orphan, so delete
$sql = 'DELETE FROM `members` WHERE `member_email` = :email';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':email', $email);
$stmt->execute();
}
I'd be glad of comments from members about ways to improve this code!

Related

Updating Multiple Column on MySQL

I want to update members_roosevelt table ACCOUNT column starting with 3000+ value I also want to update ACCOUNT column on loan_roosevelt table that is related to my member_roosevelt. What's wrong with my query? Thank you!
$query1 = "SELECT ACCOUNT
FROM
`members_roosevelt`";
$result_q1 = $link->query($query1) or die($link->error);
while ($obj = $result_q1->fetch_object()) {
$members[] = $obj->ACCOUNT;
}
$ids = implode(',', $members);
$sql = "UPDATE `members_roosevelt` as `memb`
JOIN `loan_roosevelt` as `loan`
ON `memb`.`ACCOUNT` = `loan`.`ACCOUNT`
SET
(`memb`.`ACCOUNT`,
`loan`.`ACCOUNT`) = CASE ACCOUNT";
foreach ($members as $id => $ordinal) {
$sql .= sprintf("WHEN %d THEN %d ", $ordinal, (3000+$id));
}
$sql .= "END WHERE memb.ACCOUNT IN ($ids)";
$link->query($sql) or die($link->error);
SET (`memb`.`ACCOUNT`, `loan`.`ACCOUNT`) = CASE ACCOUNT...
This is simply not part of SQL syntax. You can't set two columns at a time like this. The left side of an assignment operator must be one column.
A better solution is to use a session variable.
SET #acct = 3000;
UPDATE members_roosevelt as memb
JOIN loan_roosevelt as loan
ON memb.ACCOUNT = loan.ACCOUNT
SET memb.ACCOUNT = (#acct:=#acct+1),
loan.ACCOUNT = (#acct);
This way you don't have to run the SELECT query at all, and you don't have to create a huge UPDATE statement with potentially thousands of WHEN clauses.
Demo: SQLFiddle

How to INSERT an entry without content into a table in ZF2?

In my database there is a table, that contains only one row: id. It's something like a facade for another table:
Now I want to add an entry into whatever_set, in order to be able to create entries in the dependent tables. In SQL I would write:
INSERT INTO whatever_set VALUES ();
But when I try it with Zend\Db
$action = new Insert(whatever_set');
$data = [];
$action->values($data);
$sql = new Sql($this->dbAdapter);
$statement = $sql->prepareStatementForSqlObject($action);
$result = $statement->execute();
I get an exception:
values or select should be present
There are some possible workarounds (see below). But is there though a "Zend way" to save empty with no VALUES? How to do this?
Workaround 1
Custom Insert class.
Workaround 2
Raw SQL like
$sql = 'INSERT INTO whatever_set VALUES ();';
$result = $this->dbAdapter->getDriver()->getConnection()->execute($sql);

Update database using mySQL & php PDO

I've created a database for one of my classes simulating a hotel reservation form.
my database table name that I am trying to get values from is tblNameRes and the fields are fldName and pkEmail
I have gotten the values from the database and displayed them in this table here:
http://www.uvm.edu/~cchessia/cs148/assign4/strugg.php
I want to add a column to be able to update and delete these records, but I don't really understand how. I have this code:
$updating = $db->prepare('UPDATE `tblNameRes` SET `name` = `name` + ? WHERE `id` = ?');
$updating->execute(array(20, $id));
but I want to be able to click a link that says "update" and it will take me to another page that allows me to edit the data and submit it back to the database. I would also like to be able to delete the data in the same way.
I'm a little confused to what you would like, would you like the PDO code to both update and delete items from your DB? If so I use this, I'm also new to PDO. Also try not to use ' around table/field names.
/** Code to update */
$query = "UPDATE tblNameRes SET name ='$name' WHERE id = :id";
$stmt = $db->prepare($query);
$stmt->BindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
/** Code to delete */
$query = "DELETE FROM tblNameRes WHERE id = :id";
$stmt = $db->prepare($query);
$stmt->BindValue(':id', $id, PDO::PARAM_INT);
$query->execute();
Let me know if this helps, or is not what you wanted. I'm new here so I can't post 'comments'.
/* code for update and remove this 'at the beginning an at the end*/
$query = "UPDATE tblNameRes SET name =:fname WHERE id = :id";
$stmt = $db->prepare($query);
$stmt->BindValue('fname',$fname);
$stmt->execute();

Insert on first request; update on all subsequent requests

I'm inserting a row into a MySQL database table. On the first insertion I want a new row to be added, but after that I just want that row to be updated. Here's how I'm doing it. An Ajax request calls the following php file:
<?php
include "base.php";
$bookID = $_POST['bookID'];
$shelfID = $_POST['shelfID'];
$userID = $_SESSION['user_id'];
$query = mysql_query("SELECT shelfID FROM shelves WHERE userID = '$userID' AND shelfID = '$shelfID' AND bookID = '$bookID'");
if (mysql_num_rows($query) == 0) {
$insert = "INSERT INTO shelves (bookID,shelfID,userID) VALUES ('$bookID','$shelfID','$userID')";
mysql_query($insert) or die(mysql_error());
} elseif (mysql_num_rows($query) == 1) { //ie row already exists
$update = "UPDATE shelves SET shelfID = '$shelfID' WHERE userID = '$userID' AND bookID = '$bookID'";
mysql_query($update) or die(mysql_error());
}
?>
As it stands it adds a new row every time.
You should consider using PDO for data access. There is a discussion on what you need to do here: PDO Insert on Duplicate Key Update
I'd flag this as duplicate, but that question is specifically discussing PDO.
You can use the INSERT ... ON DUPLICATE KEY UPDATE syntax. As long as you have a unique index on the data set (i.e. userid + shelfid + bookid) you are inserting, it will do an update instead.
http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html

Update with Zend_DB on multiple rows

I am using Zend Framework. I have tree tables. Users and Groups and one table linking them.
I want to increment a field from users of a given group. To increment one User I do:
$table = 'users';
$update = array(
'ACLVersion' => new Zend_Db_Expr('ACLVersion + 1')
);
$where[] = $db->quoteInto('id = ?', $user);
$db->update($table, $update, $where);
I tried to use multiple wheres.
I have no clue how to join the tables in a where with Zend.
To use a JOIN with Zend_Db_Table, you have to disable the integrity check.
See example #27 in the ZF Reference Guide for Zend_Db_Table:
$table = new Bugs();
// retrieve with from part set, important when joining
$select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
$select->setIntegrityCheck(false)
->where('bug_status = ?', 'NEW')
->join('accounts', 'accounts.account_name = bugs.reported_by')
->where('accounts.account_name = ?', 'Bob');
$rows = $table->fetchAll($select);
Note that disabling the integrity check will also disable some of the automagic of the resulting recordset:
The resulting row or rowset will be
returned as a 'locked' row (meaning
the save(), delete() and any
field-setting methods will throw an
exception).
Load $num with a array of id's from a given group
The following code will do the job
$table = 'users';
$update = array(
'ACLVersion' => new Zend_Db_Expr('ACLVersion + 1')
);
$where = $db->quoteInto('id IN (?)', $num);
$db->update($table, $update, $where);