I'm trying to do a SELECT * from a table, where the name of that table is itself taken from another query. I think I'm tying myself in knots. Here's what I've got:
SELECT options_table INTO #tableName FROM registrant_fields WHERE id = 9;
SET #sql_text_1 = concat('CREATE TABLE tmp_options LIKE ', #tableName);
PREPARE stmt_1 FROM #sql_text_1 ;
EXECUTE stmt_1;
SET #sql_text_2 = concat('INSERT tmp_options SELECT * FROM ', #tableName);
PREPARE stmt_2 FROM #sql_text_2;
EXECUTE stmt_2;
SELECT * FROM tmp_options;
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
So... when I paste that lot into PHPMyAdmin and run it, I get the results of each statement appended respectively, and learn that yep, my "SELECT * FROM tmp_options;" has indeed got some rows. But how do I GET them??
All I want to do is drop that query into a PHP string and run it with mysqli_query(). Is that not going to work?
I have no clue about PHP, but I happen to know that mysqli_query() works with one SQL statement only (for security reasons).
I'd suggest you do (pseudo code, except SQL parts)
somePHPvariableForTableName = ("SELECT options_table FROM registrant_fields WHERE id = 9;");
query("CREATE TABLE whyDoIneedAtmpTable AS SELECT * FROM $somePHPvariableForTableName");
query("SELECT * FROM whyDoIneedAtmpTable;");
and that's it. No need for that extra INSERT step. And it's not clear, why and if you really need a temp table.
Related
How can i select a table where table name has been stored in a variable.
$a='oop';
I want to refer the table as
select * from '$a';
But this shows error.
What must be the query used instead?
Try this:
$a='oop'; $query='select * from '.$a;
You do not have to enclose $a by single quotes in the query:
$a='oop';
$query="select * from $a";
//then execute the query
You cannot use prepared statements to bind a table name to a variable, so you must use simple string concatenation to assemble such query. Obviously, the assembled query can be executed using a prepared statement, but there is not too much point doing so, unless you have other parameters in your query. This means you have to be extra careful to escape any variables used as table names.
try tihs :-)
SET #tab := 'user';
SELECT CONCAT ('select * from ',#tab,' LIMIT 10') INTO #SQL;
PREPARE stmt FROM #SQL;
EXECUTE stmt;
I am trying to select exact json value in mysql query condition, currently i am using LIKE and it work but like returns false positive.
my code is::
$id='1';
json data example:: ["1","12","38"]
$sql="SELECT * FROM `posts` WHERE `json_column` LIKE '%".$id."%' ";
with this query, it returns both 1 and 12. how can i get just 1?
Note the extra quotes:
$sql="SELECT * FROM posts WHERE json_column LIKE '%\"$id\"%'";
However, this is wide open to SQL inject if $id comes from user input. Be careful.
The more secure method would be to use parameterised queries with PHPs prepared statements as follows:
$stmt = $dbh->prepare("SELECT * FROM posts WHERE json_column LIKE '%\"?\"%'");
$stmt->bindParam(1, $id);
Let's consider i have this line of code
$result = $mysqli->query("SELECT * from myTable where field='".$_GET['var']."');
IMHO this is vulnerable to SQL injections.
So I'd like to prove it trying by sending via Get / URL a "var" param that will inject the query, with potential malicious code.
I actually tryed this:
var = "1'; TRUNCATE myTable; ";
I tryed to print out the SQL string query before executing it and it's actually 2 SQL valid statements.
SELECT * from myTable where field='1'; TRUNCATE myTable;
1st problem
But actually itseems that mysqli->query will not execute 2 statements at once. Isn't it?
2nd problem
I see that a common technique to Inject queries is to per form injection then add comment chars to get rid of the tail of the SQL.
Example:
"SELECT * from myTable where field='".$_GET['var']."' AND field2 IS NOT NULL"
Can be injected with :
var = "1'; TRUNCATE myTable; # ";
But this problem arise and I'm missing the trick to get rid of it
if the SQL string in the code have new lines e.g. :
"SELECT * from myTable where field='".$_GET['var']."'
AND field2 IS NOT NULL"
If i use the above "var" the final result is
SELECT * from myTable where field='1'; TRUNCATE myTable; #
AND field2 IS NOT NULL
Second line won't be commented
How to test injection on this?
Many thanks.
1st problem But actually it seems that mysqli->query will not execute 2
statements at once. Isn't it?
That's right, if you want to execute multiple statements you need to use mysqli->multi_query. You can find a good explanation about multiple statements here: http://www.php.net/manual/en/mysqli.quickstart.multiple-statement.php
But this problem arise and I'm missing the trick to get rid of it
The problem arises because you are using multiple statements, and mysqli->query does not support them.
About your queries:
$result = $mysqli->query("SELECT * from myTable where field='".$_GET['var']."');
You can inject this using for example 1' OR 1=1; that would return all entries of myTable on the query result.
"SELECT * from myTable where field='".$_GET['var']."' AND field2 IS NOT NULL"
Here you could use 1' OR 1=1 UNION ALL SELECT * FROM myTable WHERE '1'='1
Nowadays there are tools that can automatically check SQL injection for you, take a look at SQL Inject Me (Firefox Addon) for example.
Quick question. Whilst using the prepare method in mysqli. It is possible/a good idea; to use it twice within the same mysqli connection? Example:
OOP layered
public function getStuff(){
$posts=array();
$query = $this->DBH->prepare('SELECT * FROM table WHERE stuff =?');
$query->bind_param('s','param');
$query->execute();
$query->bind_result($ID,$col1,$col2,$etc);
while($query->fetch()){
$posts[]=array('ID'=>$ID,'col1'=>$col1,'extras'=>$this->getExtras($ID));
}
$query->close();
return $posts;
}
private function getExtra($postID){
$extras=array();
$query = $this->DBH->prepare('SELECT * FROM anotherTable WHERE moreStuff =?');
$query->bind_param('s',$postID);
$query->execute();
$query->bind_result($ID,$col1,$col2,$etc);
while($query->fetch()){
$extras[]=array('ID'=>$ID,'col1'=>$col1,'etc'=>$etc);
}
$query->close();
return $extras;
}
Right my possible error is that I've used the same variable and the same database connection. I'm not 100% sure this will work as I've called $this->DBH whilst it is already being used in the parent function. Is there a better method to what I'm trying to achieve or is there a better structure I can use. Or should I just give up and use a separate variable? lol
Hopeful outcome:
$posts=array('ID'=>'column ID number','col1'=>'column1 data', 'extras'=>array('ID'=>'second table\'s ID number','col1'=>'second tables data','etc'=>'etc etc etc'));
In your example above, the variables which matter are $query. Each of those is local to its own method, and so the variables themselves will not collide. The MySQLi connection $this->DBH is capable of handling multiple open statements at once if circumstances are right.
The place where you need to use caution is with their execution order. If you prepare and execute a statement but do not fetch all rows from it, you may not be able to prepare() the next one until all rows have been fetched unless you first close it with mysqli_stmt::close() to deallocate the open statement handle.
For example:
// Prepares successfully:
$s1 = $mysqli->prepare("SELECT * FROM t1");
// Also prepares successfully (previous one not executed)
$s2 = $mysqli->prepare("SELECT * FROM t2");
// Then consider:
$s1 = $mysqli->prepare("SELECT id, name FROM t1");
$s1->bind_result($id, $name);
$s1->execute();
// And attempt to prepare another
$s2 = $mysqli->prepare("SELECT id, name FROM t2");
// Fails because $s1 has rows waiting to be fetched.
echo $m->error;
// "Commands out of sync; you can't run this command now"
Edit: misread your example...
Looking at your example above, you are indeed calling getExtras() while you are fetching from the getStuff() statement. You may run into the issue described above. Your two operations in this case may be able to be handled with a single JOIN instead, from which you fetch in only one loop to populate all your variables and build your output array as you want it. Depending on your need, this should either be an INNER JOIN if a related row is expected to exist in the othertable, or a LEFT JOIN if the related othertable may or may not have a row that matches the given ID.
SELECT
maintable.id,
maintable.col1,
othertable.col2,
othertable.col3
FROM
maintable
JOIN othertable ON maintable.id = othertable.id
I have a table user_name with 3 fields, id, Name, Email (id is auto_increment field). I want to execute the following query in PHP, but its not returning any result.
INSERT INTO user_name (Name, Email) VALUES ('Example', 'example#xyz.com');
SELECT LAST_INSERT_ID() AS 'userid';
When I am executing the above query in PHP as below then its not returning anything.
$_SQL="INSERT INTO user_name (Name,Email) VALUES ('Example', 'example#xyz.com');
SELECT LAST_INSERT_ID() AS 'userid';";
$result_last_id = #mysql_query($_SQL);
$rs_insert = mysql_fetch_array($result_last_id);
$new_userid = $rs_insert['userid'];
Can anyone please tell me how to execute both queries into one.
Give a look to the mysql_insert_id() function.
mysql_query($insertStatementOnly);
$new_userid = mysql_insert_id();
It appears you don't need to execute multiple queries, but I included how to do it below. What you want is the last inserted id, which you get from mysql_insert_id.
To execute multiple queries
From comments on documentation of mysql_query:
The documentation claims that "multiple queries are not supported".
However, multiple queries seem to be supported. You just have to pass flag 65536 as mysql_connect's 5 parameter (client_flags). This value is defined in /usr/include/mysql/mysql_com.h:
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
Executed with multiple queries at once, the mysql_query function will return a result only for the first query. The other queries will be executed as well, but you won't have a result for them.
Alternatively, have a look at the mysqli library, which has a multi_query method.
Simple answer really: You just can't do it.
http://php.net/mysql_query
May I also suggest you avoid the error-suppression operator '#' in mysql_query as you may not be made aware of any mysql errors. At the very least do
mysql_query($sql) or die("error: " . mysql_error()) ;
If you are using the Zend Framework with a PDO defined MySQL database, you would just use:
$database=Zend_Db::factory('PDO_MySQL',Array('hostname'=>'localhost','username'=>'x','password'=>'y','dbname'=>'z');
$connectionHandle=$database->getConnection();
$rowsInserted=$connectionHandle->insert('database_name','INSERT INTO x (a,b) VALUES (c,d)');
if ($rowsInserted>0) {
$autoIncrementValue=$connectionHandle->lastInsertId();
}
Yes You can using Shell command <BR>
mysql -user -p -h database -e '
SQL STATEMENT 1;
SQL STATEMENT 2;
SQL STATEMENT 3;
.......;
'
Php / MYSQL Programmer
this might do what u want:
insert into table1 (Name,Emails) values ('qqq','www');
select max(id) as lastinserted from table1;