I try to extract some information from one table and insert it to another. I'm using the following function from https://php.net/mysql_real_escape_string to handle the escape characters.
<?php
function mysql_escape_mimic($inp) {
if(is_array($inp))
return array_map(__METHOD__, $inp);
if(!empty($inp) && is_string($inp)) {
return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $inp);
}
return $inp;
}
?>
The string I deal with is in html form with double and single quotes like
<input type="radio" value="choice_3" checked="true"/> Eat pig's belly and swine's matrix
I have to use string concatenation to write queries because column names and table names are dynamic.
$query .= "'".mysql_escape_mimic($string)."', ";
I know there is some kind of syntax error but I don't know how to fix it. Can anyone help me with it? Thanks.
I suspect your problem is with this line:
$query .= "'".mysql_escape_mimic($string)."', ";
That concatenation will leave a trailing comma, which almost certainly is causing a syntax error in your SQL. In SQL, any set of terms that are to be separated by commas must not have a trailing comma at the end of that set.
You can use a PHP trimming function to trim off the trailing ", " after you are done building the concatenated string.
I would also like to note that you can accomplish what your stated goal is ("extract some information from one table and insert it to another") entirely within the database. That is, you don't need to SELECT it into your application and then re-INSERT into the other table, thus avoiding this problem entirely.
If the two tables have identical columns, then something like this should work:
INSERT INTO table2 SELECT * FROM table1 WHERE condition;
If the two tables do not have identical columns, then something like this should work:
INSERT INTO table2 (column1, column2, column3, ...)
SELECT columnA, columnB, columnC, ...
FROM table1
WHERE condition;
I cribbed these directly from w3schools.com. You can search for many such examples using the search string "mysql select from one table into another".
Related
$this->db->insert('Table One',$data);
This would error. And showing the equivalent sql, insert into.
INSERT INTO `Table` One (`col1`, `col2`) VALUES ('----', '------')
Is there any way to insert?
Maybe the use of a wildcard perhaps? or any special character to substitute space for phpmyadmin to udnerstand? or is it phpmyadmin's fault?
Unfortunately it seems that the active record library doesn't support table names with space in. I looked into the core files and the insert() function calls the protect_identifiers function on the table name and in system/database/DB_driver.php there is the following code
// If the item has an alias declaration we remove it and set it aside.
// Basically we remove everything to the right of the first space
$alias = '';
if (strpos($item, ' ') !== FALSE)
{
$alias = strstr($item, " ");
$item = substr($item, 0, - strlen($alias));
}
So everything after the first space is removed. So it looks like your only options are to do the query like
$this->db->query('INSERT INTO `Table One` ...');
Or to remove spaces in your table names
Sorry. Hope that helps
If you have a space in your table name, you need to quote the full name:
INSERT INTO `Table One` (`col1`, `col2`) VALUES ('----', '------')
I found a similar issue when doing an update call
$this->myBaseTable = "my table";
$this->db->update($this->myBaseTable); //errors
It seems to work fine if you added the ticks into the table declaration ie
$this->myBaseTable = "`my table`";
I have a long query
$s = $dbh->prepare("SELECT name,type,
(select count(opinionid) from fe_opinion where actor=name) as countopinion,
(select count(commentid) from fe_comment where actor=name) as countcomment,
(select count(commentid) from fe_reply where actor=name and replyto<>null) as countreply,
(select count(voteid) from fe_vote where actor=name and replyto<>null) as countvote,
(select count(voteid) from fe_vote where actor=name and replyto<>null and vote=1) as countagree,
(select count(voteid) from fe_vote where actor=name and replyto<>null and vote=0) as countdisagree
from fs_actor where name=:name");
and It gives me a syntax error when I write it like this in multi line. I am unsure about the compiler because i didnt execute it. Is it supposed to work in this format or should I use heredoc?
How can I continue writing a string from next line? Should ı do it by continuing to next lineby pressing enter? Should I use heredoc or Is there a special new line character?
I've found this example in phpdoc
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';
so now I think my syntax error is something else.
Just a shot in the dark here, are you sure it's not that last comma after countdisagree that's giving you a syntax error? You don't put a comma after the last part of the SELECT, and you might not have realized you put it there, I know I've done that quite a bit myself when breaking up a long SQL query, and it will give a syntax error if it's there because it's expecting another statement to select from.
SQL queries, multiline or otherwise, should only give a syntax error if there actually is one, so if you get a syntax error, you can bet that you have one. You could break that up so you only have one word on each line and it won't give a syntax error.
There's no line-continuation character in PHP. You should use Heredoc:
$s = $dbh->prepare(<<<'EOQ'
SELECT name, type,
(SELECT COUNT(opinionid) FROM fe_opinion WHERE actor = name) AS countopinion,
(SELECT COUNT(commentid) FROM fe_comment WHERE actor = name) AS countcomment,
# ...
FROM fs_actor WHERE name = :name"
EOQ
);
The single-quotes around EOQ here are what PHP inexplicably calls "Nowdoc" syntax, which is the same as Heredoc but isn't parsed--the equivalent of using $s = 'Hello $world'; vs. double-quoted $s = "Hello $world";--which might save you a couple milliseconds somewhere down the line (but, incidentally, seems to throw off SO's syntax highlighting).
Your only (reasonable) alternative in PHP--other than storing your queries elsewhere--is to use string concatenation, which gets pretty ugly:
$s = $dbh->prepare(
'SELECT name, type, ' .
' (SELECT COUNT(opinionid) FROM fe_opinion WHERE actor = name) AS countopinion, ' .
' (SELECT COUNT(commentid) FROM fe_comment WHERE actor = name) AS countcomment, ' .
// ...
' FROM fs_actor WHERE name = :name'
);
...which is pretty ugly and requires you to mind your spaces.
Basically i want to add wildcards to the the col value when searching...
Usually I do this the other way around like this:
WHERE cakes.cake_name LIKE '%$cake_search%'
however now i want it to match the inverse:
the user searches for 'treacle
sponge', i want this to match a row
where the cake_name column =
'sponge'.
is this possible?
WHERE '$cake_search' LIKE concat('%',cakes.cake_name, '%')
should work. It will need a full table scan but so will the inverse query. Have you looked into full text search for MySQL? It will likely make this sort of query more efficient.
Why not using MATCH?
MATCH(`cake_name`) AGAINST ('treacle sponge')
You would have to split the user supplied input on the space character and dynamically construct your query to check the column for those values:
$input = "treacle sponge";
$input_words = explode(' ', $input);
$sql_where = "WHERE cakes.cake_name IN('" . implode("','", $input_words) . "')"; // generates: WHERE cakes.cake_name IN('treacle','sponge')
In order to prevent SQL-Injection, I suggest using prepared statements.
$prepStmt = $conn->prepare('SELECT ... WHERE cakes.cake_name LIKE :cake_search
');
if($prepStmt->execute(array('cake_search'=>"%$cake_search%"))) {
...
}
Or, using full text search:
$prepStmt = $conn->prepare('SELECT ... WHERE MATCH (`cake_name`) AGAINST (:cake_search IN BOOLEAN MODE)');
if($prepStmt->execute(array('cake_search'=>$cake_search_words))) {
...
}
See JSON specialchars JSON php 5.2.13 for a complete example.. ;)
As part of a query result, a column with names is returned. I want to apply a function so that the order of first and last name is flipped in my $db results. What is the most efficient way to accomplish this?
There answer probably lies in using either the foreach function, array_walk or array_map but I don't know the proper syntax.
This function does the name flip:
$name = "Lastname, Firstname";
$names = explode(", ", $name);
$name = $names[1] . " " . $names[0];
The $query is similar to this:
$query0="SELECT #__1pgndata.White, #__1pgndata.Black, #__1pgndata.ECO, #__1pgndata.Result, #__1pgndata.EventDate, #__1pgndata.Id
FROM `#__1pgndata` Where #__1pgndata.Id > 155 LIMIT 30"
White and Black are columns for player names (need to be flipped) and correspond to the color of chess pieces. The columns in question are $ginfo->White and $ginfo->Black.
if you are speaking about the order they are put in the array , you can just select them reversed (for example SELECT first_name, last_name, .. FROM users...) but I suggest you use mysql_fetch_array, that way you will be able to access them as you wish (with $row['first_name'], $row['last_name'] in whatever order you want)
PHP has a plenty of string functions. You can use any you wish
You can attempt to replicate the functionality using the MySQL String Functions. The most likely candidate would probably a combination of LOCATE() to find the position of the ', ' and then a pair of SUBSTR() calls to get the portions before and after, then using CONCAT() to put them back together.
would you provide your db code?
$query0="SELECT #__1pgndata.Black, #__1pgndata.White, #__1pgndata.ECO, #__1pgndata.Result, #__1pgndata.EventDate, #__1pgndata.Id
FROM #__1pgndata Where #__1pgndata.Id > 155 LIMIT 30"
you can use like this also right.
I would like to convert an array if IDs, into a string of comma separated values, to use in a MySQL UPDATE query. How would I do this?
Remember to escape values:
'"' . implode('","', array_map('mysql_real_escape_string', $data)) . '"'
implode(',', $array);
Make sure you pass the results through mysql_real_escape_string() before executing your query. This should prevent sql injection if you use implode() as others suggest.
And as nickf mentions, always check to make sure the array isn't empty or null first, and handle those cases. Since you are only dealing with int's, it wouldn't hurt to put some type checking in your assignments, otherwise you'll get sql errors if a string slips in somehow.
Often this type of situation is people building an array from another table for use in a 2nd query.. If this is the case you can use a subquery to accomplish this.
Eg.
UPDATE Table SET Column = Value WHERE ID IN ( SELECT ID FROM Table2 WHERE CONDITIONS )
This is probably better if all ids should be numerical.
Check that it consists of at least one integer with
$ids = array_filter($ids, 'is_int');
if (!$ids) {
//no valid ids returned.
die('or something');
}
$sql .= '(' . implode(',', $ids) . ')';