mysql query text replace issue - mysql

I have a joomla database with 'jos_content' table containing the details about the articles.
In that table, the column 'attribs' is of TEXT datatype, which contains data about the article properties, like:
show_pdf_icon=0
show_print_icon=0
show_email_icon=0
I am trying to modify the property 'show_print_icon' so that it will have 1, like this:
show_pdf_icon=0
show_print_icon=1
show_email_icon=0
For this, i have written a query that replaces the 'show_print_icon=0' to 'show_print_icon=1' in the column.
UPDATE jos_content set attribs=replace("attribs", "%print_icon=0\nshow_email%",
"%print_icon=1\nshow_email%") where attribs like '%print_icon=0\nshow_email%';
For some reason, after executing this query, i got the column values as empty.
I could not understand where did i go wrong. What could be the problem with query?

One way is :
$sql = "Select attribs from jos_content";
$db = JFactory::getDBO():
$db->setQuery($sql):
$contents = $db->loadObjectList();
foreach($contents as $content){
$attribs = $content->attribs;
$attribs = explode("\n", $attribs);
if(!$attribs['show_print_icon']){
$attribs['show_print_icon'] = 1;
$content->attribs = implode("\n", $attribs);
// run the update query here for each content
}
}
I'll let you know other way, using Com Content Model

Check the newline character. It may not be \n, it could be also \r\n or just \r, so you can't reliably match on this rule.
Also, why do you need the text surroundig? It just makes your login more complex than it has to be. You will have to be sure to keep consistent data and not have the variables there in another order for example.
I don't know what is your database structure there, but try to match on exactly what you need to change. If it's not possible now, than try to change your logic so you make it possible

Related

Removing addresses from Column

I have a column within my database that holds text similar to this
CNEWS # Trinidad : "By Any Means Necessary" Watson Duke Swims And Sails To Toco http://somewebsitehere.com
What can I do to remove the entire http address from the column? Please note that some links may be broken so it may have http:// somewebsitehere.com
I was thinking of using a substring index but not sure that would work.
You could use whichever your favorite programming language is to iterate through the rows in the table, pluck out that column, apply a regular expression replacement rule to it, then update the row in the table with the new value.
Here is some pseudo-code:
theRows = SELECT * FROM TheTable WHERE 1;
foreach row in theRows
BEGIN
oldColumnValue = row[theColumnName]
// Removes any link appearing at the end of the column
newColumnValue = oldColumnValue.replace(/http:\/\/[^\s]*$/, '')
UPDATE TheTable SET theColumnName = newColumnValue WHERE id = row[id]
END
For something as small and specific as this, you could use perl with the DBI library to connect to mySQL. Here's a useful resource on regular expressions if you want to go more into it: http://www.regular-expressions.info/perl.html

Escaping single quote inside a variable before database update

This might be a very basic question.
I have a variable $name which is input through a form from html page.
Now i have to update value of this $name into the database table using a sql query.
When $name has single quotes in it, the database update fails. Eg. James O'Hara
when it does not have single quotes, the update works fine.
Is there a way to escape this single quote inside a variable before updating the database.?
I dont want to strip the single quote. just want to escape it so the update goes through fine and actual name is updated in the database.
Please let me know. Thanks.
Generally, the best approach to this is to prepare a query and use a placeholder. Then pass the data to the database to populate the prepared query.
An ORM such as DBIx::Class will do this for you automatically.
If you are using DBI directly then you would do something like this:
$sth = $dbh->prepare("SELECT * FROM users WHERE email = ?");
foreach my $email (#emails) {
$sth->execute($email);
$row = $sth->fetchrow_hashref;
[...]
}
Use the provided quoting functions
$dbh->do("
UPDATE `MyTable`
SET `MyField` = ".$dbh->quote($my_value)."
WHERE `id` = ".$dbh->quote($id)."
");
or use placeholders
my $sth = $dbh->prepare("
UPDATE `MyTable`
SET `MyField` = ?
WHERE `id` = ?
");
$sth->execute($my_value, $id);
The latter is prettier, but under some circumstances, the former can be faster (since the DB can optimized the query better knowing the type of the expressions in advance).

add to existing value in mysql column using CONCAT function?

trying to add text to an existing value in mysql using mysql's concat function?
so existing value is currently 'john' and after function has run will be 'johnewvalue'
i am trying to add a piece of text ':reply' to the existing text which is in my subject column in my database ptb_messages.
i am trying to do this using mysql's concat function but im not getting any result what so ever.
$sql = mysql_query("UPDATE ptb_messages SET subject = CONCAT subject, 'newvalue' WHERE id='".$message_id."'");
can someone please show me a way of getting it to do what i want. thanks.
it should be
UPDATE ptb_messages
SET subject = CONCAT( subject, 'newvalue')
WHERE ...
MySQL CONCAT
in PHP
$sql = mysql_query("UPDATE ptb_messages SET subject = CONCAT(subject, 'newvalue') WHERE id='".$message_id."'");
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?

DBIx::Class update only one row

I am using DBIx::Class and I would like to only update one row in my table. Currently this is how I do it:
my $session = my_app->model("DB::Session")->find(1);
$session->update({done_yn=>'y',end_time=>\'NOW()'});
It works, but the problem is that when it does find to find the row, it does this whole query:
SELECT me.id, me.project_id, me.user_id, me.start_time, me.end_time, me.notes, me.done_yn FROM sessions me WHERE ( me.id = ? ): '8'
Which seems a bit much when all I want to do is update a row. Is there anyway to update a row without having to pull the whole row out of the database first? Something like this is what I am looking for:
my_app->model("DB::Session")->update({done_yn=>'y',end_time=>\'NOW()'},{id=>$id});
Where $id is the WHERE id=? part of the query. Does anyone know how to do this? Thanks!
You can run update on a restricted resultset which only matches this single row:
my_app->model("DB::Session")->search_rs({ id=> 1 })->update({done_yn=>'y',end_time=>\'NOW()'});
I suggest you use a DateTime->now object instead of literal SQL for updating the end_time column because it uses the apps servers date and time instead of the database servers and makes your schema more compatible with different RDBMSes.
Do you have a check if the row was found to prevent an error in case it wasn't?
You might want to use update_or_create instead.
You could use the "columns" attribute:
my $session = my_app->model("DB::Session")->find(1, {columns => "id"});

Whats wrong with this MySQL Update Query?

1st I'll give you the query, and then I'll tell you what I am trying to achieve, as I could be soo wrong or soo close.
mysql_query("UPDATE link_building SET
ID=$ID,Site=$Site,Date=$Date,Target_Site=$Target_Site,
Target_Contact_Email=$Target_Contact_Email,
Target_Contact_Name=$Target_Contact_Name,
Link_Type=$Link_Type,Link_Acquired=$Link_Acquired,
Notes=$Notes,Link_URL=$Link_URL WHERE ID=" . $ID);
What am I trying to achieve?
I want to update the fields
("ID","Site","Date","Target_Site","Target_Contact_Email","Target_Contact_Name",
"Link_Type","Link_Acquired","Notes","Link_URL")
in the table link_building with the values stored in the variables
("$ID","$Site","$Date","$Target_Site","$Target_Contact_Email","$Target_Contact_Name",
"$Link_Type","$Link_Acquired","$Notes","$Link_URL")
But I only want to update the record whos Id is equal to $ID.
UPDATE: I DO NOT SEE ANY ERROR. ITS REDIRECTS TO link_building.php and displays success message but doesn't change the data in the MySQL table.
Try escaping the data and removing the update of the ID since its already in your conditions:
mysql_query("UPDATE link_building SET Site='".mysql_real_escape_string($Site)."',Date='".mysql_real_escape_string($Date)."',Target_Site='".mysql_real_escape_string($Target_Site)."', Target_Contact_Email='".mysql_real_escape_string($Target_Contact_Email)."', Target_Contact_Name='".mysql_real_escape_string($Target_Contact_Name)."', Link_Type='".mysql_real_escape_string($Link_Type)."',Link_Acquired='".mysql_real_escape_string($Link_Acquired)."', Notes='".mysql_real_escape_string($Notes)."',Link_URL='".mysql_real_escape_string($Link_URL)."' WHERE ID=" . intval($ID));
For one, you're forgetting that you still need to quote your strings;
mysql_query("UPDATE link_building SET Site='$Site', Date='$Date',".
"Target_Site='$Target_Site', Target_Contact_Email='$Target_Contact_Email',".
"Target_Contact_Name='$Target_Contact_Name', Link_Type='$Link_Type',".
"Link_Acquired='$Link_Acquired', Notes='$Notes', Link_URL='$Link_URL' ".
"WHERE ID=$ID");
Note the added 's around all strings.
Bonus remark; you should really be using mysql_real_escape_string() on your strings before passing them on to the database.
if your columns are named like Target Site (with a space in it), you should adress it like that in your query (wich will force you to add backticks to it). also, you'll have to add quotes to colums that store anything else that strings. your query should look like:
UPDATE
link_building
SET
ID = $ID,
Site = '$Site', // single quotes for values
Date = '$Date', // ...
´Target Site´ = '$Target_Site' // and ´ for fields
[...]
this should solve why the query doesn't work (in addition: not how a bit or formatting makes it much more readable).
you havn't given information about that, but please note that you should always sanitize your variables before using it (your code doesn't look like you do) to avoid sql-injections. you can do this using mysql_real_escape_string or, even better, start using prepared statements.