[SQL Server]Incorrect syntax near table [duplicate] - php

This question already has answers here:
What is the difference between single-quoted and double-quoted strings in PHP?
(7 answers)
Closed 4 years ago.
I want to execute one and the same sql statement for a series of tables e.g. 37 tables.
For the table object name of each queried table I want to use a php variable named '$table'. The object names of the tables are provided in an included php file 'tables.php'.
The variable '$table' is generated repetitively from a concatenation of the string '$table' and an array '$numbers' for each table number, and put into the statement.
SQL reads the generated variable e.g. '$table1'. But I get an error from SQL Server for the FROM clause:
[SQL Server]Incorrect syntax near '$table1'.
I put the variable '$table' in brackets and quotation marks but it did not help.
Please help!
//php script one, 'tables.php':
$table1 = 'myTable1';
$table2 = 'myTable2';
...
$table37 = 'myTable37';
//php script two:
include_once('tables.php');
$numbers = range(1,37);
foreach($numbers as $number) {
$table = '$table' . $number;
$stmt = $db_conn->prepare("SELECT * FROM $table;");
$stmt->execute();
}
This is the solution provided by Hasan. The magic is to put the concat for variable '$table' in curly brackets led by $:
include_once('tables.php'); //provides table object names for variables $table1, $table2, etc., e.g. $table1 = 'mytable1_in_database';
//first number of a closed range of variables for tables to be queried
$i = 1;
//last number of closed range of variables for tables to be queried
$j = 37;
for($i=1; $i<=$j; $i++) {
$table = ${'table' . $i};
$stmt = $db_conn->prepare("SELECT * FROM $table;");
$stmt->execute();
}

You're getting error because you're using single quotes and variables can't interpreted, you may use double quotes or choose my below approach
$i = 1;
foreach($numbers as $number) {
$table = 'myTable' . $i;
//$table = "${'table' . $i}"; use it if you have already defined variables
$stmt = $db_conn->prepare("SELECT * FROM $table;");
$stmt->execute();
$i++;
if($i == 38) break;
}
As the question is now on Hold, hope you dont mind me adding a suggestion in your answer its to long for a comment.
This shoudl get you where you want to be, I hope :)
foreach($numbers as $number) {
$t = '$table' . $number;
$table = $t;
$stmt = $db_conn->prepare("SELECT * FROM $table");
$stmt->execute();
}

Related

How to concatenate string with OR-operator in php? [duplicate]

This question already has answers here:
How to make dynamic postgres prepared statements in PHP
(4 answers)
Closed 3 years ago.
I want to build a query based on the output from a for-loop. The query now looks like this:
$result = $pdo->query("SELECT {$fields}, ST_AsGeoJSON(geom, 5) AS geojson FROM government_table WHERE '".$gov_where_statement."' {$order}");
and the $gov_where_statement comes from the for-loop:
for ($i=0; $i<count($gov)-1; $i++){
$gov_where_statement .="government='".$gov[$i]."' "&&" ";
}
for ($i=0; $i<count($gov); $i++){
if( !next( $gov ) ) {
$gov_where_statement .="government='".$gov[$i]."'";
}
}
If there are three governments, I want the query to be interpreted as:
$result = $pdo->query("SELECT {$fields}, ST_AsGeoJSON(geom, 5) AS geojson FROM government_table WHERE government='first' && government='second' && government='third' {$order}");
Problem arises in first part of the for-loop with the "&&". Putting a var_dump($gov_where_statement) after the for-loop returns 11government='third' where 11 comes from the for-loop with the &&-operator. If there would have been four governments it would look like: 111government='fourth'.
How can I produce government='first' && government='second' && government='third' so that the query understand the &&-operator?
I would usually use prepared statement to prevent SQL injection. So I would separately build an array of placeholder and the substitution values. Also since you're looking to build the OR condition against single column and N different values, I think it's better to simply use the IN syntax:
<?php
// build a placeholder array [':gov1', ':gov2', ... ':govN']
$keys = array_map(function ($key) {
return ':gov' . $key;
}, range(1, sizeof($gov)));
// build a value array [':gov1' => $gov[0], ':gov2' => $gov[1], ... ':govN' => $gov[n-1]]
$values = array_combine($keys, $gov);
// form the SQL statement with placeholder for prepare
// i.e. WHERE government IN (:gov1, :gov2, ... :govN)
$where_clause = !empty($gov) ? 'WHERE government IN (' . implode($keys, ', ') . ')' : '';
// prepare the statement
$stmt = $dbh->prepare("SELECT {$fields}, ST_AsGeoJSON(geom, 5) AS geojson FROM government_table {$where_clause} {$order}");
// execute the prepared statement with the values
$result = $stmt->execute($values);
You can use join() to solve it:
$gov_where_statement = [];
for ($i=0; $i<count($gov)-1; $i++){
$gov_where_statement[] = "government='{$gov[i]}'";
}
$gov_where_statement = join(' OR ', $gov_where_statement);
Note that your entire code might be susceptible to SQL Injection Attack. Consider using PDO prepared statements instead.

Dynamic select mysqli query with dynamic parameters returns error doesn't match number of bind variables [duplicate]

This question already has answers here:
Use an array in a mysqli prepared statement: `WHERE .. IN(..)` query [duplicate]
(8 answers)
Closed 11 months ago.
I'm trying to create a select query with dynamic where clause and dynamic parameters but I always get error :
Warning: mysqli_stmt::bind_param(): Number of elements in type
definition string doesn't match number of bind variables
Which I sincerely do not understand since it seems the count is alright. So this is what the code really looks like in its rude format. I can't see what I'm doing wrong.
//get variables
$mediaArray ='Facebook,Twitter,Twitch,';
$otherMedia = 'House';
//convert string to array
$socialArray = explode(',', $mediaArray)
//declare some variables to be used later
$andwhere = '';
$bp = '';
$socialmarray = ''
//get every value from array of social media
foreach($socialArray as $socialmedia){
$socialmarray .=$socialmedia.',';
$andwhere .= " AND socialmedianame=?";
$bp .='s';
}
//test strings
echo $wheres = $andwhere;//AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?
echo $bip = $bp.'s';//ssss
echo $validarayy = rtrim($socialmarray,',');//Facebook,Twitter,Twitch
//select query
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$selectquery->execute();
$resultquery = $selectquery->get_result();
Because:
You are using user-supplied data, you must assume that your query is vulnerable to a malicious injection attack and
the amount of data that is to be built into the query is variable/indefinite and
you are only writing conditional checks on a single table column
You should use a prepared statement and merge all of the WHERE clause logic into a single IN statement.
Building this dynamic prepared statement is more convoluted (in terms of syntax) than using pdo, but it doesn't mean that you need to abandon mysqli simply because of this task.
$mediaArray ='Facebook,Twitter,Twitch,';
$otherMedia = 'House';
$media = array_unique(explode(',', $mediaArray . $otherMedia));
$count = count($media);
$conn = new mysqli("localhost", "root", "", "myDB");
$sql = "SELECT * FROM mediaservices";
if ($count) {
$stmt = $conn->prepare("$sql WHERE socialmedianame IN (" . implode(',', array_fill(0, $count, '?')) . ")");
$stmt->bind_param(str_repeat('s', $count), ...$media);
$stmt->execute();
$result = $stmt->get_result();
} else {
$result = $conn->query($sql);
}
foreach ($result as $row) {
// access values like $row['socialmedianame']
}
For anyone looking for similar dynamic querying techniques:
SELECT with dynamic number of LIKE conditions
INSERT dynamic number of rows with one execute() call
In your query:
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
The ? represents one parameter to pass in, and the evaluation of $wheres adds another three, giving you four total parameters.
bind_param() should take a string representing the types of the variables to insert as the first parameter, and the variables themselves as the subsequent parameters.
In your bind:
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$bip evaluates to ssss and $otherMedia is a single string ("House"). You might expect $validarayy to be three strings, but rtrim() returns a string. Thus, it is only one string ("Facebook,Twitter,Twitch"). You pass through two variables when the query is expecting four:
$conn->prepare("select * from mediaservices where socialmedianame=House AND socialmedianame=Facebook,Twitter,Twitch AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?"
To correct this, you'll want to convert $validarayy back to an array, and use the index for the various inputs:
$socialmarray2 = explode(',', $validarayy);
$selectquery->bind_param("$bip", $otherMedia, $socialmarray2[0], $socialmarray2[1], $socialmarray2[2]);
Also note that your sample code has a few missing semicolons; you'll need to fix these in order for your code to work correctly.
This can be seen working here.
Finally, note that even if you were to split the three strings out correctly, the selection of ... AND socialmedianame=Facebook AND socialmedianame=Twitter AND socialmedianame=Twitch will never match any results; socialmedianame can only contain one value. You're probably looking to substitute your AND statements with OR statements.

Update over 100 fields in mysql

i have 181 fields in my database named S1, S2....S181. I want to update these fields using values from inputs WITH name="S1", .....NAME="S181".
MY CODE IS
$S1=$_POST['S1'];
...
...
$S181=$_POST['S181'];
$sql=mysqli_query($conn,"update 'cap' set S1='$S1'......S181='$S181'")
I am trying something like
for ($i = 1; $i<=181; $i++ ) {
$(S$i)=$_POST['S$i'];
$sql = mysqli_query($conn, "UPDATE `cap4a` SET
S$i='$(S$i)'
WHERE IDID=".$id) or die (mysqli_error($conn));
}
Is there something wrong in the way I use S$i, because I am getting errors:
"Parse error: syntax error, unexpected '(', expecting variable (T_VARIABLE) or '$' in C:\xampp1\htdocs\update_cap4a.php on line 5" ?
I don't think it's a good idea to run 181 queries to alter the same row as you do. Instead, run one query that makes all required changes to the row. The code below will work for you:
$id = (int)$_POST['id'];//remove (int) if id IDID is a string
$snippets = [];//holds little snippets eg: S1='value1'
for($i=1;$i<=181;$i++){
$varname = "S$i"; //S1...S181
if(!isset($_POST[$varname])) continue;
$snippets[] = " $varname='$_POST[$varname]' ";
}
$sql = '"UPDATE cap SET '.implode(",",$snippets)." WHERE IDID=$id";
$result = mysqli_query($conn,$sql) or die (mysqli_error($conn));
I don't cover it in this snippet but you need to add at least two things before using this in production:
Proper error handling, for when your query fails
Prepared statements or escaped values to protect against SQL injection
Is there something wrong in the way I use S$i
To dynamically create a variable named S10 and set it to 'value' when $i=10, do:
$varname = "S$i";
$$varname = 'value'; // $$varname can also be referred to as $S10
See Variable Variables in the docs.
I would gave done it this way:
for ($i = 1; $i<=181; $i++) {
$key = 'S'.$i;
$value = $_POST[$key];
$update[] = "`{$key}` = '".$value."'";
$sql = mysqli_query($conn, "UPDATE `cap4a` SET ".join(",",$update)."
WHERE IDID=".$id) or die (mysqli_error($conn));
}

UPDATE MySQL using PDO, prepared statements and substituting tokens with bindParam; getting 'variables don't match tokens' error [duplicate]

This question already has answers here:
What is the difference between single-quoted and double-quoted strings in PHP?
(7 answers)
Closed 1 year ago.
I am attempting to UPDATE records within my MySQL database.
I build the prepared statement using arrays / loops:
$sql = "UPDATE table01 SET ";
foreach($values as $value)
{
$sql .="$value = :$value, ";
}
$sql = rtrim($sql,', ');
$sql .=" WHERE id = '$id'";
then I prepare this statement:
try
{
$pdo = new PDO('mysql:host=localhost; dbname=db01', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare($sql);
Then I bind each of the tokens / placeholders in the prepared statement to the values to be inserted using another loop:
foreach(array_combine($values, $variables) as $value=>$variable)
{
$stmt->bindParam(':$value', $variable);
}
$stmt->execute();
where $values is an array of column headers in the database (therefore ':$value' is a set of token names corresponding to them) and $variables is an array of variables containing data to be stored.
When I run this, I am given the error:
Error: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
But as you can see I'm forming them from arrays - I've done counts on the arrays to ensure the elements match 1:1 and they do:
FYI:
$count1 = count($values);
$count2 = count($variables);
echo $count1;
echo $count2;
gives:
7575
(they both have 75 elements in them)
Single quotes don't interpolate variables.
$stmt->bindParam(':$value', $variable);
should be
$stmt->bindParam(":$value", $variable);

I don't understand how "?" is being used here

So, I have this PHP code:
$tabid = getTabid($module);
if($tabid==9)
$tabid="9,16";
$sql = "select * from field ";
$sql.= " where field.tabid in(?) and";
Now, how exactly does the ? work here? I vaguely understand that in PHP, ?: is a ternary operator, but the colon isn't being used here, and ? is part of a Postgresql query anyway.
The final query looks a bit like this:
select * from field where field.tabid in('9,16')
So, the question mark is replaced by the contents of $tabid, how does that happen?
The issue is that ('9,16') is not accepted by Postgres as an integer, it needs to be written like (9,16), so how do I do that? How do I remove the apostrophes?
Thanks a lot for the help, have a good day!
edit: More code was requested:
$sql.= " field.displaytype in (1,2,3) and field.presence in (0,2)";
followed by if statements, I think this is the relevant one:
if($tabid == 9 || $tabid==16)
{
$sql.= " and field.fieldname not in('notime','duration_minutes','duration_hours')";
}
$sql.= " group by field.fieldlabel order by block,sequence";
$params = array($tabid);
//Running the query.
$result = $adb->pquery($sql, $params);
Oh, I think I see now, I think it is a place holder, a part of the pquery function:
function pquery($sql, $params, $dieOnError=false, $msg='') {
Stuff
$sql = $this->convert2Sql($sql, $params);
}
Now, this is where it seems to get fun, here's part of the convert2Sql function:
function convert2Sql($ps, $vals) {
for($index = 0; $index < count($vals); $index++) {
if(is_string($vals[$index])) {
if($vals[$index] == '') {
$vals[$index] = "NULL";
}
else {
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'";
}
}
}
$sql = preg_replace_callback("/('[^']*')|(\"[^\"]*\")|([?])/", array(new PreparedQMark2SqlValue($vals),"call"), $ps);
return $sql;
}
The problem I think lies in the
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'"; line.
The sql_escape_string($str) function just returns pg_escape_string($str).
Sorry for the super long edit, but I still haven't been able to get past I am afraid, thanks for all the help!
Edit 2: I fixed the problem, all it took was changin $tabid = "9,16" to $tabid = array(9,16). I have no idea why, oh and I also had to remove the group by statement because Postgresql requires every field to be placed in that statement.
it is a positional parameter for a prepared statement
See: http://php.net/manual/en/function.pg-prepare.php
You don't actually 'remove' the quotes, you have to pass SQL array of ints instead of a string value into the parameter when doing pg_execute
An example:
// Assume that $values[] is an array containing the values you are interested in.
$values = array(1, 4, 5, 8);
// To select a variable number of arguments using pg_query() you can use:
$valuelist = implode(', ', $values);
// You may therefore assume that the following will work.
$query = 'SELECT * FROM table1 WHERE col1 IN ($1)';
$result = pg_query_params($query, array($valuelist))
or die(pg_last_error());
// Produces error message: 'ERROR: invalid input syntax for integer'
// It only works when a SINGLE value specified.
Instead you must use the following approach:
$valuelist = '{' . implode(', ', $values . '}'
$query = 'SELECT * FROM table1 WHERE col1 = ANY ($1)';
$result = pg_query_params($query, array($valuelist));

Categories