This question might probably have been asked somewhere but I just can't seem to find it after much searching.
I have a basic question on how I can prevent the last SQL statement in my code below from executing if it caused any row/data in the table to change.
$query = 'SELECT pdt_code FROM `Products`';
$stmt = $con->query($query);
while ($obj = $stmt->fetch()) {
$pdt_code[] = $obj['pdt_code'];
}
$args = implode(',',
array_map(function($el) {
return '('.implode(',', $el).')';
},
array_chunk(array_fill(0, count($pdt_code), '?'), count($pdt_code))
)
);
$query = 'ALTER TABLE `MapProduct` CHANGE product_code product_code SET '.$args.' COLLATE utf8mb4_unicode_ci NOT NULL';
$stmt = $con->prepare($query);
$stmt->execute($pdt_code); // how do I prevent this line from executing if it causes the data in table `MapProduct` to change?
I am trying to execute this from PHP where I query another table for updates to product codes and update the SET() accordingly. However, I had a horrific experience of losing all my data because the update was not properly executed and all the data in product_code got wiped.
Although mysql's SET data type can be used to restrict list of values being entered. However, it is not flexible and requires an alter table to update the list of values. If you frequently have to do this - and if you build a functionality to do that, then you need to do this frequently - then the SET data type is simply not for you.
I would create a separate table for product types and I would simply reference this table with a foreign key from your mapproduct table. This way adding a new product type to the allowed list inly requires an insert statement.
Related
I'm using PHP in order to create a website where managers have access and review forms that employees have submitted. In the reviewing PHP file, I have created two buttons which basically approve or disapprove the form. After they click on one of the buttons, they are being redirected to another PHP file which actually inserts into the MySQL Database a change in a column I named 'processed'. It changes 0 which is unprocessed to 1, which is processed. The table I am referring to has columns such as formid, fullname, department and other job related stuff, as well as the 'processed' column which allows the managers to see if there is a pending form to be reviewed.
My problem is that I have no idea how to actually allow MySQL to find the proper row and change only the cell with the name 'processed' from 0 to 1 without having to insert every cell again. Here's what I have tried till now:
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "INSERT INTO carforms (processed) where aboveid='$id' and processed='0' and teamformid=$teamformid
VALUES ('0')";
}
else if (isset($_POST['disapproved'])) {
//todo
}
How do I tell SQL to only find the specific row I want and change only one column which is processed?
Also, do I always have to type every column name when I use the INSERT INTO command?
Thanks in advance.
Use the Below code it'll work for you.
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "UPDATE `carforms` SET processed = '1' WHERE `aboveid` = '".$id."' AND `teamformid` = '".$teamformid."'";
}
Try:
"UPDATE carforms SET processed = 1 WHERE aboveid = $id AND teamformid = $teamformid"
From what I have interpreted from your question, it seems like you need to use the MySQL UPDATE command. This will update any existing rows.
For example, let's say you have a table called 'forms', consisting of a Primary Key 'form_id' and a field named 'processed'.
If we want to change the value of 'processed' to '1', we would run...
UPDATE forms SET processed = 1 WHERE form_id = [whatever number the form is];
Obviously this only works where the form (with a form_id) exists already
There is no "INSERT...WHERE" in SQL.
To change an existing record there are 2 options, REPLACE or UPDATE. The former will create the record if it does not already exist and has similar syntax to INSERT. UPDATE uses the WHERE clause to identify the record(s) to be changed.
Using REPLACE is tricky. It needs to work out whether it should INSERT a new record or UPDATE an existing one - it does this by checking if the data values presented already exist in a unique index on the table - if you don't have any unique indexes then it will never update a record. Even if you have unique indexes just now, the structure of these may change over time as your application evolves, hence I would recommend NOT using REPLACE for OLTP.
In your question you write:
where aboveid='$id' and processed='0' and teamformid=$teamformid
(it would have been helpful if you had published the relevant part of the schema)
'id' usually describes a unique identifier. So there shouldn't be multiple records with the same id, and therefore the remainder of the WHERE clause is redundant (but does provide an avenue for SQL injection - not a good thing).
If the relevant record in carforms is uniquely identifed by a value for 'id' then your code should be something like:
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
But there's another problem here. There are 3 possible states for a record:
not yet processed
declined
approved
But you've only told us about 2 possible states. Assuming the initial state is null, then the code should be:
$action=0;
if (isset($_POST['approved'])) {
$action=1;
}
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
if ($id &&
(isset($_POST['disapproved']) || isset($_POST['approved']))
) {
// apply the SQL to the database
} else {
// handle the unexpected outcome.
}
I currently have the following update statement but is there anyway that I can make it retain the current values but insert and new values that are not in the db?
If not what would be the best way to achieve this?
UPDATE INTO {refocus_candidate_category} SET canid=?, categoryid=? WHERE canid=? AND categoryid=?",array($emailCheck['id'], $id, $emailCheck['id'], $id));
Function:
$catParams = array_merge(array($emailCheck['id']), $fields['Occupation']);
$catPlaceholders = '?'.str_repeat(',?',count($fields['Occupation'])-1);
$catCheck = CMS::selectQuery("SELECT * FROM {table} WHERE canid=? AND categoryid IN (".$catPlaceholders.")", $catParams);
if($catCheck != FALSE)
{
for($i=0; $i<count($fields['Occupation']); $i++) {
$id = $fields['Occupation'][$i];
CMS::updateQuery("UPDATE INTO {table} SET canid=?, categoryid=? WHERE canid=? AND categoryid=?",array($emailCheck['id'], $id, $emailCheck['id'], $id));
}
echo 'found update';
}
ID Print
$fields['Occupation'][$i] = 1678
It's not clear to me from your question precisely what you mean, but there are a number of alternatives for inserts/updates that deal with missing or already present values.
Firstly, if you just want to insert into mysql and have it either create a new row or replace an existing row (where existing is determined by the primary key matching) use REPLACE INTO instead of INSERT INTO. REPLACE INTO tries an insert, but if the primary key already exists, it turns the query into a DELETE and then retries the INSERT.
If you want to insert a new row but leave an existing row alone if you've already got one, you can either use INSERT IGNORE INTO (which may also fail to insert if you've got your data types or column info wrong...) or INSERT INTO ... ON DUPLICATE KEY UPDATE which allows you to do much finer grained control of how you handle inserts of items that already exist.
There's other options as well, but those are probably the most relevant.
so I'm trying to change some specific columns in a row in a table of a MySQL database by calling the Doctrine_Query when an option is selected inside an admin panel of my website.
Here are the details:
Table name: chatUsers
I need to find all rows with the person who has
a username of: $chatUsers->username (The column inside chatUsers is
called username)
Once all those rows are found, change the value of all the row's column "type" to "user"
Is this even possible?
So far I have:
$query = Doctrine_Query::create()->from('db_chatUsers')->where('username = $chatUsers->username')->findAll();
...And I'm not sure where to go from there, or if that's even correct. I probably have to use 'foreach' or something. Sorry in advance, I'm not very good with PHP yet.
I just pulled it off from http://www.doctrine-project.org/documentation/manual/1_1/hu/dql-doctrine-query-language
i've never used doctrine and i have no idea if this works.
$query = Doctrine_Query::create()
->update('db_chatUsers')
->set('type', '?', 'user');
->where('username = '.$chatUsers->username);
// If the "user" is column not a value then use instead:
//$query->set('type', 'user');
//execute query
$rows = $query->execute();
echo $rows.' rows updated';
i am using mysql_affected_rows() to check if i have to enter new record or update existing, but the problem is if the user tries to enter exactly same data as record which already exists it runs insert into.
$result = mysql_query("update Data set Score='$score',Comment='$_POST[Comments]' where Date='$_POST[forDay_3]-$_POST[forDay_1]-$_POST[forDay_2]' AND User='$_POST[UserID]';");
$last = mysql_affected_rows();
if ($last==0) {
$result1 = mysql_query("INSERT INTO Data (User,Date,Score,Comment) VALUES ('$_POST[UserID]','$_POST[forDay_3]-$_POST[forDay_1]-$_POST[forDay_2]','$score','$_POST[Comments]')");
what should i do to avoid redundant entries
You could parse mysql_info() output (but the solution itself will be affected by race condition issue)
You could create unique key User + Date and end up with a single query using ON DUPLICATE KEY UPDATE syntax:
INSERT INTO `Data` (User,Date,Score,Comment)
('$_POST[UserID]','$_POST[forDay_3]-$_POST[forDay_1]-$_POST[forDay_2]','$score','$_POST[Comments]')
ON DUPLICATE KEY UPDATE Score='$score',Comment='$_POST[Comments]'
some solutions:
add another query to see if data exists, and then decide if you want to do some action (update/delete) or nothing.
add a 'modified' column with type "TIMESTAMP" and make it on update - CURRENT_TIMESTAMP
i'd go with first option.
btw, you should escape your post data (mysql_real_escape_string) to prevent injects or malformed query string
You may get the number of affected rows with FOUND_ROWS() instead of mysql_affected_rows(). The latter counts the not modified rows as well.
$result = mysql_query("update Data set Score='$score',Comment='$_POST[Comments]' where Date='$_POST[forDay_3]-$_POST[forDay_1]-$_POST[forDay_2]' AND User='$_POST[UserID]';");
$last = mysql_query("SELECT ROW_COUNT();");
$last = mysql_fetch_array($last);
...
Reference: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count
So I have an import/export module for OpenCart, but it's wiping the entire product option table before inserting new data...
I need to develop support for the 3rd party product options module I have, but in the meantime--I figure I'd just stop it from deleting an important column in my product options table.
In the product_option_value table, I have 'product_option,' 'product_id,' 'quantity' etc., and there's one column named 'info' that I want to NOT wipe. The method is below:
function storeOptionsIntoDatabase( &$database, &$options )
{
// find the default language id
$languageId = $this->getDefaultLanguageId($database);
// start transaction, remove options
$sql = "START TRANSACTION;\n";
$sql .= "DELETE FROM `".DB_PREFIX."product_option`;\n";
$sql .= "DELETE FROM `".DB_PREFIX."product_option_description` WHERE language_id=$languageId;\n";
$sql .= "DELETE FROM `".DB_PREFIX."product_option_value`;\n";
$sql .= "DELETE FROM `".DB_PREFIX."product_option_value_description` WHERE language_id=$languageId;\n";
$this->import( $database, $sql );
...more code...
}
I'm not that familiar with MySQL, but I want something to the effect of:
$sql .= "DELETE FROM `".DB_PREFIX."product_option_value` WHERE column != 'info';\n";
Thanks!
Edit:
I tried Michael's suggestion to use UPDATE and explicitly setting them all to NULL... but that returned this error:
Error: Duplicate entry '0' for key 1
Error No: 1062 UPDATE
oc_product_option_value SET
product_option_value_id=NULL,
product_option_id=NULL,
product_id=NULL, quantity=NULL,
subtract=NULL, price=NULL,
prefix=NULL, sort_order=NULL,
weight=NULL, sku=NULL, image=NULL
I tried taking out the primary key:
$sql .= "UPDATE
".DB_PREFIX."product_option_value
SET product_option_id=NULL,
product_id=NULL, quantity=NULL,
subtract=NULL, price=NULL,
prefix=NULL, sort_order=NULL,
weight=NULL;\n";
but I get:
Error: Duplicate entry '1' for key 1
Error No: 1062 INSERT INTO
`oc_product....
Edit:
Okay, so I removed the 'primary_key' field from the INSERT... and I got no error messages from the upload. But when I view a product that product options, I get this message the top of my page:
Notice: Undefined index: name in
/httpdocs/ocart/catalog/model/catalog/product.php
on line 418Notice: Undefined index:
name in
/httpdocs/ocart/catalog/model/catalog/product.php
on line 418Notic.... it repeats
Make sure I understand: You want to clear values from all columns in the table product_option_value except for the column info ? If that's what you want, then the following may work. Please don't run it before we're clear on what you're trying to do!
DELETE FROM syntax implies deleting from a table name, not a column name. What you'll need to do instead is to UPDATE your rows to set all columns except the one you intend to keep to be either NULL or empty or their default value.
Don't forget to add a WHERE condition if you need to keep some rows as they are without modifying them! Without a WHERE, this query will NULL out all columns specified in the whole table.
UPDATE product_option_value
SET
product_option = NULL,
product_id = NULL,
quantity = NULL,
etc...
WHERE (some where condition if you need one)
I'm adding a second answer, taking a completely different approach which avoids SQL problems.
Export your table as a comma-separated text file. You can do this with phpmyadmin, or MySQL Workbench.
Open your CSV in a spreadsheet
Clear out the columns you want to clear out.
Save as a new CSV
Import the CSV back into your database using phpmyadmin, Workbench, or the LOAD DATA LOCAL INFILE syntax.